|  | 
| 44 | 44 |         "process.runtime.memory": ["rss", "vms"], | 
| 45 | 45 |         "process.runtime.cpu.time": ["user", "system"], | 
| 46 | 46 |         "process.runtime.gc_count": None, | 
|  | 47 | +        "cpython.gc.collections": None, | 
| 47 | 48 |         "process.runtime.thread_count": None, | 
| 48 | 49 |         "process.runtime.cpu.utilization": None, | 
| 49 | 50 |         "process.runtime.context_switches": ["involuntary", "voluntary"], | 
|  | 
| 136 | 137 |     "process.runtime.memory": ["rss", "vms"], | 
| 137 | 138 |     "process.runtime.cpu.time": ["user", "system"], | 
| 138 | 139 |     "process.runtime.gc_count": None, | 
|  | 140 | +    "cpython.gc.collections": None, | 
| 139 | 141 |     "process.runtime.thread_count": None, | 
| 140 | 142 |     "process.runtime.cpu.utilization": None, | 
| 141 | 143 |     "process.runtime.context_switches": ["involuntary", "voluntary"], | 
| @@ -196,6 +198,7 @@ def __init__( | 
| 196 | 198 |         self._runtime_memory_labels = self._labels.copy() | 
| 197 | 199 |         self._runtime_cpu_time_labels = self._labels.copy() | 
| 198 | 200 |         self._runtime_gc_count_labels = self._labels.copy() | 
|  | 201 | +        self._runtime_gc_collections_labels = self._labels.copy() | 
| 199 | 202 |         self._runtime_thread_count_labels = self._labels.copy() | 
| 200 | 203 |         self._runtime_cpu_utilization_labels = self._labels.copy() | 
| 201 | 204 |         self._runtime_context_switches_labels = self._labels.copy() | 
| @@ -470,6 +473,19 @@ def _instrument(self, **kwargs: Any): | 
| 470 | 473 |                     unit="By", | 
| 471 | 474 |                 ) | 
| 472 | 475 | 
 | 
|  | 476 | +        if "cpython.gc.collections" in self._config: | 
|  | 477 | +            if self._python_implementation == "pypy": | 
|  | 478 | +                _logger.warning( | 
|  | 479 | +                    "The cpython.gc.collections metric won't be collected because the interpreter is PyPy" | 
|  | 480 | +                ) | 
|  | 481 | +            else: | 
|  | 482 | +                self._meter.create_observable_counter( | 
|  | 483 | +                    name="cpython.gc.collections", | 
|  | 484 | +                    callbacks=[self._get_runtime_gc_collections], | 
|  | 485 | +                    description="The number of times a generation was collected since interpreter start.", | 
|  | 486 | +                    unit="{collection}", | 
|  | 487 | +                ) | 
|  | 488 | + | 
| 473 | 489 |         if "process.runtime.thread_count" in self._config: | 
| 474 | 490 |             self._meter.create_observable_up_down_counter( | 
| 475 | 491 |                 name=f"process.runtime.{self._python_implementation}.thread_count", | 
| @@ -885,6 +901,16 @@ def _get_runtime_gc_count( | 
| 885 | 901 |             self._runtime_gc_count_labels["count"] = str(index) | 
| 886 | 902 |             yield Observation(count, self._runtime_gc_count_labels.copy()) | 
| 887 | 903 | 
 | 
|  | 904 | +    def _get_runtime_gc_collections( | 
|  | 905 | +        self, options: CallbackOptions | 
|  | 906 | +    ) -> Iterable[Observation]: | 
|  | 907 | +        """Observer callback for garbage collection""" | 
|  | 908 | +        for index, count in enumerate(gc.get_count()): | 
|  | 909 | +            self._runtime_gc_collections_labels["generation"] = str(index) | 
|  | 910 | +            yield Observation( | 
|  | 911 | +                count, self._runtime_gc_collections_labels.copy() | 
|  | 912 | +            ) | 
|  | 913 | + | 
| 888 | 914 |     def _get_runtime_thread_count( | 
| 889 | 915 |         self, options: CallbackOptions | 
| 890 | 916 |     ) -> Iterable[Observation]: | 
|  | 
0 commit comments