Skip to content

Commit d676efb

Browse files
authored
opentelemetry-instrumentation-system-metrics: fix cpython metrics (open-telemetry#4092)
* opentelemetry-instrumentation-system-metrics: fix cpython metrics Use the proper attribute per semantic convention for the generation. Don't break the backward compatibility for now, add a TODO to remove the wrong attribute in following releases.
1 parent 3188f36 commit d676efb

3 files changed

Lines changed: 42 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5858
([#4068](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4068))
5959
- `opentelemetry-instrumentation-mysqlclient`: Replace SpanAttributes with semconv constants
6060
([#4067](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4067))
61+
- `opentelemetry-instrumentation-system-metrics`: Use proper numeric `cpython.gc.generation` attribute in CPython metrics, out of spec `generation` attribute is deprecated and will be removed in the future
62+
([#4092](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4092))
6163

6264
## Version 1.39.0/0.60b0 (2025-12-03)
6365

instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@
112112
from opentelemetry.instrumentation.system_metrics.package import _instruments
113113
from opentelemetry.instrumentation.system_metrics.version import __version__
114114
from opentelemetry.metrics import CallbackOptions, Observation, get_meter
115+
from opentelemetry.semconv._incubating.attributes.cpython_attributes import (
116+
CPYTHON_GC_GENERATION,
117+
)
115118
from opentelemetry.semconv._incubating.metrics.process_metrics import (
116119
create_process_cpu_utilization,
117120
)
@@ -958,6 +961,8 @@ def _get_runtime_gc_collections(
958961
) -> Iterable[Observation]:
959962
"""Observer callback for garbage collection"""
960963
for index, stat in enumerate(gc.get_stats()):
964+
self._runtime_gc_collections_labels[CPYTHON_GC_GENERATION] = index
965+
# TODO: remove this a few releases after 1.40.0
961966
self._runtime_gc_collections_labels["generation"] = str(index)
962967
yield Observation(
963968
stat["collections"], self._runtime_gc_collections_labels.copy()
@@ -968,6 +973,10 @@ def _get_runtime_gc_collected_objects(
968973
) -> Iterable[Observation]:
969974
"""Observer callback for garbage collection collected objects"""
970975
for index, stat in enumerate(gc.get_stats()):
976+
self._runtime_gc_collected_objects_labels[
977+
CPYTHON_GC_GENERATION
978+
] = index
979+
# TODO: remove this a few releases after 1.40.0
971980
self._runtime_gc_collected_objects_labels["generation"] = str(
972981
index
973982
)
@@ -981,6 +990,10 @@ def _get_runtime_gc_uncollectable_objects(
981990
) -> Iterable[Observation]:
982991
"""Observer callback for garbage collection uncollectable objects"""
983992
for index, stat in enumerate(gc.get_stats()):
993+
self._runtime_gc_uncollectable_objects_labels[
994+
CPYTHON_GC_GENERATION
995+
] = index
996+
# TODO: remove this a few releases after 1.40.0
984997
self._runtime_gc_uncollectable_objects_labels["generation"] = str(
985998
index
986999
)

instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -983,9 +983,15 @@ def test_runtime_get_gc_collections(self, mock_gc_get_stats):
983983
}
984984
)
985985
expected_gc_collections = [
986-
_SystemMetricsResult({"generation": "0"}, 10),
987-
_SystemMetricsResult({"generation": "1"}, 20),
988-
_SystemMetricsResult({"generation": "2"}, 30),
986+
_SystemMetricsResult(
987+
{"cpython.gc.generation": 0, "generation": "0"}, 10
988+
),
989+
_SystemMetricsResult(
990+
{"cpython.gc.generation": 1, "generation": "1"}, 20
991+
),
992+
_SystemMetricsResult(
993+
{"cpython.gc.generation": 2, "generation": "2"}, 30
994+
),
989995
]
990996
self._test_metrics(
991997
"cpython.gc.collections",
@@ -1007,9 +1013,15 @@ def test_runtime_get_gc_collected_objects(self, mock_gc_get_stats):
10071013
}
10081014
)
10091015
expected_gc_collected_objects = [
1010-
_SystemMetricsResult({"generation": "0"}, 100),
1011-
_SystemMetricsResult({"generation": "1"}, 200),
1012-
_SystemMetricsResult({"generation": "2"}, 300),
1016+
_SystemMetricsResult(
1017+
{"cpython.gc.generation": 0, "generation": "0"}, 100
1018+
),
1019+
_SystemMetricsResult(
1020+
{"cpython.gc.generation": 1, "generation": "1"}, 200
1021+
),
1022+
_SystemMetricsResult(
1023+
{"cpython.gc.generation": 2, "generation": "2"}, 300
1024+
),
10131025
]
10141026
self._test_metrics(
10151027
"cpython.gc.collected_objects",
@@ -1031,9 +1043,15 @@ def test_runtime_get_gc_uncollectable_objects(self, mock_gc_get_stats):
10311043
}
10321044
)
10331045
expected_gc_uncollectable_objects = [
1034-
_SystemMetricsResult({"generation": "0"}, 1),
1035-
_SystemMetricsResult({"generation": "1"}, 2),
1036-
_SystemMetricsResult({"generation": "2"}, 3),
1046+
_SystemMetricsResult(
1047+
{"cpython.gc.generation": 0, "generation": "0"}, 1
1048+
),
1049+
_SystemMetricsResult(
1050+
{"cpython.gc.generation": 1, "generation": "1"}, 2
1051+
),
1052+
_SystemMetricsResult(
1053+
{"cpython.gc.generation": 2, "generation": "2"}, 3
1054+
),
10371055
]
10381056
self._test_metrics(
10391057
"cpython.gc.uncollectable_objects",

0 commit comments

Comments
 (0)