Custom metric support (#384) · temporalio/sdk-python@3fade95 · GitHub
Skip to content

Commit 3fade95

Browse files
authored
Custom metric support (#384)
1 parent aa829d3 commit 3fade95

16 files changed

Lines changed: 1257 additions & 17 deletions

File tree

‎temporalio/activity.py‎

Lines changed: 43 additions & 0 deletions

‎temporalio/bridge/metric.py‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
"""Metrics using SDK Core. (unstable)
2+
3+
Nothing in this module should be considered stable. The API may change.
4+
"""
5+
6+
from __future__ import annotations
7+
8+
from typing import Mapping, Optional, Union
9+
10+
import temporalio.bridge.runtime
11+
import temporalio.bridge.temporal_sdk_bridge
12+
13+
14+
class MetricMeter:
15+
"""Metric meter using SDK Core."""
16+
17+
@staticmethod
18+
def create(runtime: temporalio.bridge.runtime.Runtime) -> Optional[MetricMeter]:
19+
"""Create optional metric meter."""
20+
ref = temporalio.bridge.temporal_sdk_bridge.new_metric_meter(runtime._ref)
21+
if not ref:
22+
return None
23+
return MetricMeter(ref)
24+
25+
def __init__(
26+
self, ref: temporalio.bridge.temporal_sdk_bridge.MetricMeterRef
27+
) -> None:
28+
"""Initialize metric meter."""
29+
self._ref = ref
30+
self._default_attributes = MetricAttributes(ref.default_attributes)
31+
32+
@property
33+
def default_attributes(self) -> MetricAttributes:
34+
"""Default attributes for the metric meter."""
35+
return self._default_attributes
36+
37+
38+
class MetricCounter:
39+
"""Metric counter using SDK Core."""
40+
41+
def __init__(
42+
self,
43+
meter: MetricMeter,
44+
name: str,
45+
description: Optional[str],
46+
unit: Optional[str],
47+
) -> None:
48+
"""Initialize counter metric."""
49+
self._ref = meter._ref.new_counter(name, description, unit)
50+
51+
def add(self, value: int, attrs: MetricAttributes) -> None:
52+
"""Add value to counter."""
53+
if value < 0:
54+
raise ValueError("Metric value must be non-negative value")
55+
self._ref.add(value, attrs._ref)
56+
57+
58+
class MetricHistogram:
59+
"""Metric histogram using SDK Core."""
60+
61+
def __init__(
62+
self,
63+
meter: MetricMeter,
64+
name: str,
65+
description: Optional[str],
66+
unit: Optional[str],
67+
) -> None:
68+
"""Initialize histogram."""
69+
self._ref = meter._ref.new_histogram(name, description, unit)
70+
71+
def record(self, value: int, attrs: MetricAttributes) -> None:
72+
"""Record value on histogram."""
73+
if value < 0:
74+
raise ValueError("Metric value must be non-negative value")
75+
self._ref.record(value, attrs._ref)
76+
77+
78+
class MetricGauge:
79+
"""Metric gauge using SDK Core."""
80+
81+
def __init__(
82+
self,
83+
meter: MetricMeter,
84+
name: str,
85+
description: Optional[str],
86+
unit: Optional[str],
87+
) -> None:
88+
"""Initialize gauge."""
89+
self._ref = meter._ref.new_gauge(name, description, unit)
90+
91+
def set(self, value: int, attrs: MetricAttributes) -> None:
92+
"""Set value on gauge."""
93+
if value < 0:
94+
raise ValueError("Metric value must be non-negative value")
95+
self._ref.set(value, attrs._ref)
96+
97+
98+
class MetricAttributes:
99+
"""Metric attributes using SDK Core."""
100+
101+
def __init__(
102+
self, ref: temporalio.bridge.temporal_sdk_bridge.MetricAttributesRef
103+
) -> None:
104+
"""Initialize attributes."""
105+
self._ref = ref
106+
107+
def with_additional_attributes(
108+
self, new_attrs: Mapping[str, Union[str, int, float, bool]]
109+
) -> MetricAttributes:
110+
"""Create new attributes with new attributes appended."""
111+
return MetricAttributes(self._ref.with_additional_attributes(new_attrs))

‎temporalio/bridge/src/lib.rs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use pyo3::prelude::*;
22
use pyo3::types::PyTuple;
33

44
mod client;
5+
mod metric;
56
mod runtime;
67
mod testing;
78
mod worker;
@@ -13,6 +14,14 @@ fn temporal_sdk_bridge(py: Python, m: &PyModule) -> PyResult<()> {
1314
m.add_class::<client::ClientRef>()?;
1415
m.add_function(wrap_pyfunction!(connect_client, m)?)?;
1516

17+
// Metric stuff
18+
m.add_class::<metric::MetricMeterRef>()?;
19+
m.add_class::<metric::MetricAttributesRef>()?;
20+
m.add_class::<metric::MetricCounterRef>()?;
21+
m.add_class::<metric::MetricHistogramRef>()?;
22+
m.add_class::<metric::MetricGaugeRef>()?;
23+
m.add_function(wrap_pyfunction!(new_metric_meter, m)?)?;
24+
1625
// Runtime stuff
1726
m.add_class::<runtime::RuntimeRef>()?;
1827
m.add_function(wrap_pyfunction!(init_runtime, m)?)?;
@@ -44,6 +53,11 @@ fn connect_client<'a>(
4453
client::connect_client(py, &runtime_ref, config)
4554
}
4655

56+
#[pyfunction]
57+
fn new_metric_meter(runtime_ref: &runtime::RuntimeRef) -> Option<metric::MetricMeterRef> {
58+
metric::new_metric_meter(&runtime_ref)
59+
}
60+
4761
#[pyfunction]
4862
fn init_runtime(telemetry_config: runtime::TelemetryConfig) -> PyResult<runtime::RuntimeRef> {
4963
runtime::init_runtime(telemetry_config)

‎temporalio/bridge/src/metric.rs‎

Lines changed: 175 additions & 0 deletions

0 commit comments

Comments
 (0)