|
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