|
3 | 3 | from __future__ import unicode_literals
|
4 | 4 |
|
5 | 5 | import gc
|
6 |
| -import os |
7 |
| -import time |
8 | 6 |
|
9 |
| -from .metrics import Histogram |
| 7 | +from .metrics_core import CounterMetricFamily |
10 | 8 | from .registry import REGISTRY
|
11 | 9 |
|
12 | 10 |
|
13 | 11 | class GCCollector(object):
|
14 | 12 | """Collector for Garbage collection statistics."""
|
15 | 13 |
|
16 |
| - def __init__(self, registry=REGISTRY, gc=gc): |
17 |
| - # To work around the deadlock issue described in |
18 |
| - # https://github.com/prometheus/client_python/issues/322, |
19 |
| - # the GC collector is always disabled in multiprocess mode. |
20 |
| - if 'prometheus_multiproc_dir' in os.environ: |
| 14 | + def __init__(self, registry=REGISTRY): |
| 15 | + if not hasattr(gc, 'get_stats'): |
21 | 16 | return
|
| 17 | + registry.register(self) |
22 | 18 |
|
23 |
| - if not hasattr(gc, 'callbacks'): |
24 |
| - return |
25 |
| - |
26 |
| - collected = Histogram( |
27 |
| - 'python_gc_collected_objects', |
| 19 | + def collect(self): |
| 20 | + collected = CounterMetricFamily( |
| 21 | + 'python_gc_objects_collected', |
28 | 22 | 'Objects collected during gc',
|
29 |
| - ['generation'], |
30 |
| - buckets=[500, 1000, 5000, 10000, 50000], |
31 |
| - registry=registry |
| 23 | + labels=['generation'], |
32 | 24 | )
|
33 |
| - |
34 |
| - uncollectable = Histogram( |
35 |
| - 'python_gc_uncollectable_objects', |
| 25 | + uncollectable = CounterMetricFamily( |
| 26 | + 'python_gc_objects_uncollectable', |
36 | 27 | 'Uncollectable object found during GC',
|
37 |
| - ['generation'], |
38 |
| - buckets=[500, 1000, 5000, 10000, 50000], |
39 |
| - registry=registry |
| 28 | + labels=['generation'], |
40 | 29 | )
|
41 | 30 |
|
42 |
| - latency = Histogram( |
43 |
| - 'python_gc_duration_seconds', |
44 |
| - 'Time spent in garbage collection', |
45 |
| - ['generation'], |
46 |
| - registry=registry |
| 31 | + collections = CounterMetricFamily( |
| 32 | + 'python_gc_collections', |
| 33 | + 'Number of times this generation was collected', |
| 34 | + labels=['generation'], |
47 | 35 | )
|
48 | 36 |
|
49 |
| - times = {} |
50 |
| - |
51 |
| - # Avoid _cb() being called re-entrantly |
52 |
| - # by setting this flag and clearing it once |
53 |
| - # the callback operation is complete. |
54 |
| - # See https://github.com/prometheus/client_python/issues/322#issuecomment-438021132 |
55 |
| - self.gc_cb_active = False |
56 |
| - |
57 |
| - def _cb(phase, info): |
58 |
| - try: |
59 |
| - if self.gc_cb_active: |
60 |
| - return |
61 |
| - self.gc_cb_active = True |
62 |
| - |
63 |
| - gen = info['generation'] |
64 |
| - |
65 |
| - if phase == 'start': |
66 |
| - times[gen] = time.time() |
67 |
| - |
68 |
| - if phase == 'stop': |
69 |
| - delta = time.time() - times[gen] |
70 |
| - latency.labels(gen).observe(delta) |
71 |
| - if 'collected' in info: |
72 |
| - collected.labels(gen).observe(info['collected']) |
73 |
| - if 'uncollectable' in info: |
74 |
| - uncollectable.labels(gen).observe(info['uncollectable']) |
75 |
| - finally: |
76 |
| - self.gc_cb_active = False |
| 37 | + for generation, stat in enumerate(gc.get_stats()): |
| 38 | + generation = str(generation) |
| 39 | + collected.add_metric([generation], value=stat['collected']) |
| 40 | + uncollectable.add_metric([generation], value=stat['uncollectable']) |
| 41 | + collections.add_metric([generation], value=stat['collections']) |
77 | 42 |
|
78 |
| - gc.callbacks.append(_cb) |
| 43 | + return [collected, uncollectable, collections] |
79 | 44 |
|
80 | 45 |
|
81 | 46 | GC_COLLECTOR = GCCollector()
|
|
0 commit comments