Skip to content

Commit

Permalink
Add PeriodicExportingMetricReader interval when is_lambda
Browse files Browse the repository at this point in the history
  • Loading branch information
tammy-baylis-swi committed Oct 4, 2024
1 parent cfbc9d7 commit 98a7bac
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 5 deletions.
18 changes: 13 additions & 5 deletions solarwinds_apm/configurator.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,11 +437,19 @@ def _configure_metrics_exporter(
"Creating PeriodicExportingMetricReader using %s",
exporter_name,
)
# Inf interval to not invoke periodic collection
reader = PeriodicExportingMetricReader(
exporter,
export_interval_millis=math.inf,
)

reader = None
if apm_config.is_lambda:
# Inf interval to not invoke periodic collection
reader = PeriodicExportingMetricReader(
exporter,
export_interval_millis=math.inf,
)
else:
# Use default interval 60s else OTEL_METRIC_EXPORT_INTERVAL
reader = PeriodicExportingMetricReader(
exporter,
)
metric_readers.append(reader)

# Use configured Resource attributes then merge with
Expand Down
193 changes: 193 additions & 0 deletions tests/unit/test_configurator/test_configurator_metrics_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,87 @@ def test_configure_metrics_exporter_valid(
]
)
mock_pemreader.assert_called_once()
mock_pemreader.assert_has_calls(
[
mocker.call(
mock_exporter,
)
]
)
trace_mocks.get_tracer_provider.assert_called_once()
trace_mocks.get_tracer_provider().get_tracer.assert_called_once()
mock_meterprovider.assert_called_once()

# Restore old EXPORTER
if old_metrics_exporter:
os.environ["OTEL_METRICS_EXPORTER"] = old_metrics_exporter

def test_configure_metrics_exporter_valid_is_lambda(
self,
mocker,
mock_apmconfig_enabled_is_lambda,
mock_pemreader,
mock_meterprovider,
):
# Save any EXPORTER env var for later
old_metrics_exporter = os.environ.get("OTEL_METRICS_EXPORTER", None)
if old_metrics_exporter:
del os.environ["OTEL_METRICS_EXPORTER"]

# Mock entry points
mock_exporter = mocker.Mock()
mock_exporter_class = mocker.Mock()
mock_exporter_class.configure_mock(return_value=mock_exporter)
mock_load = mocker.Mock()
mock_load.configure_mock(return_value=mock_exporter_class)
mock_exporter_entry_point = mocker.Mock()
mock_exporter_entry_point.configure_mock(
**{
"load": mock_load,
}
)
mock_points = iter([mock_exporter_entry_point])
mock_iter_entry_points = mocker.patch(
"solarwinds_apm.configurator.iter_entry_points"
)
mock_iter_entry_points.configure_mock(
return_value=mock_points
)
mocker.patch.dict(
os.environ,
{
"OTEL_METRICS_EXPORTER": "valid_exporter"
}
)

# Mock Otel
get_resource_mocks(mocker)
trace_mocks = get_trace_mocks(mocker)
mock_histogram = mocker.patch(
"solarwinds_apm.configurator.Histogram"
)
mock_agg_temp = mocker.patch(
"solarwinds_apm.configurator.AggregationTemporality"
)
mock_agg_temp.DELTA = "foo-delta"

# Test!
test_configurator = configurator.SolarWindsConfigurator()
test_configurator._configure_metrics_exporter(
mock_apmconfig_enabled_is_lambda,
)
mock_exporter_entry_point.load.assert_called_once()
mock_exporter_entry_point.load.assert_has_calls(
[
mocker.call(),
mocker.call()(
preferred_temporality={
mock_histogram: "foo-delta"
}
)
]
)
mock_pemreader.assert_called_once()
mock_pemreader.assert_has_calls(
[
mocker.call(
Expand Down Expand Up @@ -411,6 +492,118 @@ def test_configure_metrics_exporter_valid_invalid_mixed(
)
# Called for the valid one
mock_pemreader.assert_called_once()
mock_pemreader.assert_has_calls(
[
mocker.call(
mock_exporter,
)
]
)
# Rest not called at all
trace_mocks.get_tracer_provider.assert_not_called()
trace_mocks.get_tracer_provider().get_tracer.assert_not_called()
mock_meterprovider.assert_not_called()

# Restore old EXPORTER
if old_metrics_exporter:
os.environ["OTEL_METRICS_EXPORTER"] = old_metrics_exporter

def test_configure_metrics_exporter_valid_invalid_mixed_is_lambda(
self,
mocker,
mock_apmconfig_enabled_is_lambda,
mock_pemreader,
mock_meterprovider,
):
# Save any EXPORTER env var for later
old_metrics_exporter = os.environ.get("OTEL_METRICS_EXPORTER", None)
if old_metrics_exporter:
del os.environ["OTEL_METRICS_EXPORTER"]

# Mock entry points
mock_exporter = mocker.Mock()
mock_exporter_class = mocker.Mock()
mock_exporter_class.configure_mock(return_value=mock_exporter)
mock_load = mocker.Mock()
mock_load.configure_mock(return_value=mock_exporter_class)
mock_exporter_entry_point = mocker.Mock()
mock_exporter_entry_point.configure_mock(
**{
"load": mock_load,
}
)
mock_exporter_class_invalid = mocker.Mock()
mock_exporter_class_invalid.configure_mock(
side_effect=Exception("mock error invalid exporter")
)
mock_exporter_entry_point_invalid = mocker.Mock()
mock_exporter_entry_point_invalid.configure_mock(
**{
"load": mock_exporter_class_invalid
}
)

mock_points = iter(
[
mock_exporter_entry_point,
mock_exporter_entry_point_invalid,
]
)
mock_iter_entry_points = mocker.patch(
"solarwinds_apm.configurator.iter_entry_points"
)
mock_iter_entry_points.configure_mock(
return_value=mock_points
)
mocker.patch.dict(
os.environ,
{
"OTEL_METRICS_EXPORTER": "valid_exporter,invalid_exporter"
}
)

# Mock Otel
get_resource_mocks(mocker)
trace_mocks = get_trace_mocks(mocker)
mock_histogram = mocker.patch(
"solarwinds_apm.configurator.Histogram"
)
mock_agg_temp = mocker.patch(
"solarwinds_apm.configurator.AggregationTemporality"
)
mock_agg_temp.DELTA = "foo-delta"

# Test!
test_configurator = configurator.SolarWindsConfigurator()
with pytest.raises(Exception):
test_configurator._configure_metrics_exporter(
mock_apmconfig_enabled_is_lambda,
)
mock_iter_entry_points.assert_has_calls(
[
mocker.call("opentelemetry_metrics_exporter", "valid_exporter"),
mocker.call("opentelemetry_metrics_exporter", "invalid_exporter"),
]
)
mock_exporter_entry_point.load.assert_called_once()
mock_exporter_entry_point.load.assert_has_calls(
[
mocker.call(),
mocker.call()(
preferred_temporality={
mock_histogram: "foo-delta"
}
)
]
)
mock_exporter_entry_point_invalid.load.assert_called_once()
mock_exporter_entry_point_invalid.load.assert_has_calls(
[
mocker.call(),
]
)
# Called for the valid one
mock_pemreader.assert_called_once()
mock_pemreader.assert_has_calls(
[
mocker.call(
Expand Down

0 comments on commit 98a7bac

Please sign in to comment.