8000 Add detailed Garbage Collection statistics. (#301) · flixgithub/client_python@c0cee96 · GitHub
[go: up one dir, main page]

Skip to content

Commit c0cee96

Browse files
tcolgatebrian-brazil
authored andcommitted
Add detailed Garbage Collection statistics. (prometheus#301)
This patch adds details stats for the python garbage collector. - `python_gc_collected_objects`: Histogram of the number of objects collected, by GC generation. - `python_gc_uncollectable_objects`: Histogram of the number of objects count to be uncollectable, by GC generation. - `python_gc_duration_seconds`: Histogram of the duration of each GC generation. Signed-off-by: Tristan Colgate <tristan@qubit.com>
1 parent 8586b8d commit c0cee96

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

prometheus_client/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from . import exposition
55
from . import process_collector
66
from . import platform_collector
7+
from . import gc_collector
78

89
__all__ = ['Counter', 'Gauge', 'Summary', 'Histogram', 'Info', 'Enum']
910

@@ -35,6 +36,8 @@
3536
PlatformCollector = platform_collector.PlatformCollector
3637
PLATFORM_COLLECTOR = platform_collector.PLATFORM_COLLECTOR
3738

39+
GCCollector = gc_collector.GCCollector
40+
GC_COLLECTOR = gc_collector.GC_COLLECTOR
3841

3942
if __name__ == '__main__':
4043
c = Counter('cc', 'A counter')

prometheus_client/gc_collector.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/python
2+
3+
from __future__ import unicode_literals
4+
5+
import gc
6+
import time
7+
8+
from . import core
9+
10+
class GCCollector(object):
11+
"""Collector for Garbage collection statistics."""
12+
def __init__(self, registry=core.REGISTRY, gc=gc):
13+
if not hasattr(gc, 'callbacks'):
14+
return
15+
16+
collected = core.Histogram(
17+
'python_gc_collected_objects',
18+
'Objects collected during gc',
19+
['generation'],
20+
buckets=[500, 1000, 5000, 10000, 50000],
21+
registry=registry
22+
)
23+
24+
uncollectable = core.Histogram(
25+
'python_gc_uncollectable_objects',
26+
'Uncollectable object found during GC',
27+
['generation'],
28+
buckets=[500, 1000, 5000, 10000, 50000],
29+
registry=registry
30+
)
31+
32+
latency = core.Histogram(
33+
'python_gc_duration_seconds',
34+
'Time spent in garbage collection',
35+
['generation'],
36+
registry=registry
37+
)
38+
39+
times = {}
40+
41+
def _cb(phase, info):
42+
gen = info['generation']
43+
44+
if phase == 'start':
45+
times[gen] = time.time()
46+
47+
if phase == 'stop':
48+
delta = time.time() - times[gen]
49+
latency.labels(gen).observe(delta)
50+
if 'collected' in info:
51+
collected.labels(gen).observe(info['collected'])
52+
if 'uncollectable' in info:
53+
uncollectable.labels(gen).observe(info['uncollectable'])
54+
55+
gc.callbacks.append(_cb)
56+
57+
58+
GC_COLLECTOR = GCCollector()
59+
"""Default GCCollector in default Registry REGISTRY."""

tests/test_gc_collector.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from __future__ import unicode_literals
2+
3+
import unittest
4+
5+
from prometheus_client import CollectorRegistry, GCCollector
6+
7+
8+
class TestGCCollector(unittest.TestCase):
9+
def setUp(self):
10+
self.registry = CollectorRegistry()
11+
self.gc = _MockGC()
12+
13+
def test_working(self):
14+
collector = GCCollector(registry=self.registry, gc=self.gc)
15+
self.gc.start_gc({'generation': 0})
16+
self.gc.stop_gc({'generation': 0, 'collected': 10, 'uncollectable': 2})
17+
18+
self.assertEqual(1,
19+
self.registry.get_sample_value(
20+
'python_gc_duration_seconds_count',
21+
labels={"generation": "0"}))
22+
23+
self.assertEqual(1,
24+
self.registry.get_sample_value(
25+
'python_gc_collected_objects_count',
26+
labels={"generation": "0"}))
27+
28+
self.assertEqual(1,
29+
self.registry.get_sample_value(
30+
'python_gc_uncollectable_objects_count',
31+
labels={"generation": "0"}))
32+
33+
self.assertEqual(10,
34+
self.registry.get_sample_value(
35+
'python_gc_collected_objects_sum',
36+
labels={"generation": "0"}))
37+
38+
self.assertEqual(2,
39+
self.registry.get_sample_value(
40+
'python_gc_uncollectable_objects_sum',
41+
labels={"generation": "0"}))
42+
43+
44+
class _MockGC(object):
45+
def __init__(self):
46+
self.callbacks = []
47+
48+
def start_gc(self, info):
49+
for cb in self.callbacks:
50+
cb('start', info)
51+
52+
def stop_gc(self, info):
53+
for cb in self.callbacks:
54+
cb('stop', info)

0 commit comments

Comments
 (0)
0