0
# Runtime Configuration
1
2
Runtime configuration for the Temporal Python SDK, including telemetry, logging, metrics collection, and performance monitoring. The runtime manages the underlying thread pool and provides observability features for Temporal applications.
3
4
## Capabilities
5
6
### Runtime Management
7
8
Core runtime that manages internal resources and telemetry configuration for clients and workers.
9
10
```python { .api }
11
class Runtime:
12
@staticmethod
13
def default() -> Runtime: ...
14
15
@staticmethod
16
def set_default(runtime: Runtime, *, error_if_already_set: bool = True) -> None: ...
17
18
def __init__(self, *, telemetry: TelemetryConfig) -> None: ...
19
20
@property
21
def metric_meter(self) -> temporalio.common.MetricMeter: ...
22
```
23
24
#### Usage Examples
25
26
```python
27
from temporalio.runtime import Runtime, TelemetryConfig, LoggingConfig, PrometheusConfig
28
29
# Use default runtime
30
runtime = Runtime.default()
31
32
# Create custom runtime with metrics
33
telemetry = TelemetryConfig(
34
metrics=PrometheusConfig(bind_address="0.0.0.0:9090")
35
)
36
custom_runtime = Runtime(telemetry=telemetry)
37
38
# Set as default before creating clients/workers
39
Runtime.set_default(custom_runtime)
40
41
# Access metrics from runtime
42
meter = runtime.metric_meter
43
counter = meter.create_counter("workflow_count", "Number of workflows")
44
```
45
46
### Telemetry Configuration
47
48
Comprehensive telemetry configuration for logging, metrics, and observability.
49
50
```python { .api }
51
@dataclass(frozen=True)
52
class TelemetryConfig:
53
logging: Optional[LoggingConfig] = LoggingConfig.default
54
metrics: Optional[Union[OpenTelemetryConfig, PrometheusConfig, MetricBuffer]] = None
55
global_tags: Mapping[str, str] = field(default_factory=dict)
56
attach_service_name: bool = True
57
metric_prefix: Optional[str] = None
58
```
59
60
### Logging Configuration
61
62
Configure logging output from the Temporal Core and Python SDK components.
63
64
```python { .api }
65
@dataclass(frozen=True)
66
class LoggingConfig:
67
filter: Union[TelemetryFilter, str]
68
forwarding: Optional[LogForwardingConfig] = None
69
70
default: ClassVar[LoggingConfig]
71
72
@dataclass
73
class TelemetryFilter:
74
core_level: str
75
other_level: str
76
77
def formatted(self) -> str: ...
78
79
@dataclass
80
class LogForwardingConfig:
81
logger: logging.Logger
82
append_target_to_name: bool = True
83
prepend_target_on_message: bool = True
84
overwrite_log_record_time: bool = True
85
append_log_fields_to_message: bool = True
86
```
87
88
#### Usage Examples
89
90
```python
91
import logging
92
from temporalio.runtime import (
93
TelemetryConfig,
94
LoggingConfig,
95
TelemetryFilter,
96
LogForwardingConfig
97
)
98
99
# Basic logging configuration
100
logging_config = LoggingConfig(
101
filter=TelemetryFilter(core_level="INFO", other_level="WARN")
102
)
103
104
# Forward Core logs to Python logger
105
logger = logging.getLogger("temporal.core")
106
logger.setLevel(logging.INFO)
107
108
forward_config = LogForwardingConfig(
109
logger=logger,
110
append_target_to_name=True,
111
prepend_target_on_message=True
112
)
113
114
logging_config = LoggingConfig(
115
filter="INFO",
116
forwarding=forward_config
117
)
118
119
telemetry = TelemetryConfig(logging=logging_config)
120
```
121
122
### Metrics Configuration
123
124
Multiple options for metrics collection including OpenTelemetry, Prometheus, and in-memory buffering.
125
126
#### Prometheus Metrics
127
128
Export metrics to Prometheus-compatible endpoints.
129
130
```python { .api }
131
@dataclass(frozen=True)
132
class PrometheusConfig:
133
bind_address: str
134
counters_total_suffix: bool = False
135
unit_suffix: bool = False
136
durations_as_seconds: bool = False
137
histogram_bucket_overrides: Optional[Mapping[str, Sequence[float]]] = None
138
```
139
140
#### OpenTelemetry Metrics
141
142
Export metrics to OpenTelemetry collectors.
143
144
```python { .api }
145
class OpenTelemetryMetricTemporality(Enum):
146
CUMULATIVE = 1
147
DELTA = 2
148
149
@dataclass(frozen=True)
150
class OpenTelemetryConfig:
151
url: str
152
headers: Optional[Mapping[str, str]] = None
153
metric_periodicity: Optional[timedelta] = None
154
metric_temporality: OpenTelemetryMetricTemporality = OpenTelemetryMetricTemporality.CUMULATIVE
155
durations_as_seconds: bool = False
156
http: bool = False
157
```
158
159
#### Metrics Buffer
160
161
In-memory metrics collection for testing and custom processing.
162
163
```python { .api }
164
class MetricBufferDurationFormat(Enum):
165
MILLISECONDS = 1
166
SECONDS = 2
167
168
class MetricBuffer:
169
def __init__(
170
self,
171
buffer_size: int,
172
duration_format: MetricBufferDurationFormat = MetricBufferDurationFormat.MILLISECONDS,
173
): ...
174
175
def retrieve_updates(self) -> Sequence[BufferedMetricUpdate]: ...
176
177
class BufferedMetric(Protocol):
178
@property
179
def name(self) -> str: ...
180
181
@property
182
def description(self) -> Optional[str]: ...
183
184
@property
185
def unit(self) -> Optional[str]: ...
186
187
@property
188
def kind(self) -> BufferedMetricKind: ...
189
190
class BufferedMetricUpdate(Protocol):
191
@property
192
def metric(self) -> BufferedMetric: ...
193
194
@property
195
def value(self) -> Union[int, float]: ...
196
197
@property
198
def attributes(self) -> temporalio.common.MetricAttributes: ...
199
```
200
201
#### Usage Examples
202
203
```python
204
from temporalio.runtime import (
205
Runtime,
206
TelemetryConfig,
207
PrometheusConfig,
208
OpenTelemetryConfig,
209
MetricBuffer,
210
MetricBufferDurationFormat,
211
OpenTelemetryMetricTemporality
212
)
213
from datetime import timedelta
214
215
# Prometheus metrics
216
prometheus_config = PrometheusConfig(
217
bind_address="0.0.0.0:9090",
218
counters_total_suffix=True,
219
durations_as_seconds=True,
220
histogram_bucket_overrides={
221
"temporal_workflow_task_execution_time": [0.1, 0.5, 1.0, 5.0, 10.0]
222
}
223
)
224
225
# OpenTelemetry metrics
226
otel_config = OpenTelemetryConfig(
227
url="http://localhost:4317",
228
headers={"Authorization": "Bearer token"},
229
metric_periodicity=timedelta(seconds=10),
230
metric_temporality=OpenTelemetryMetricTemporality.DELTA,
231
durations_as_seconds=True
232
)
233
234
# Buffered metrics for testing
235
buffer = MetricBuffer(
236
buffer_size=10000,
237
duration_format=MetricBufferDurationFormat.SECONDS
238
)
239
240
# Use in telemetry configuration
241
telemetry = TelemetryConfig(
242
metrics=prometheus_config, # or otel_config or buffer
243
global_tags={"service": "my-service", "environment": "production"},
244
metric_prefix="myapp_temporal_"
245
)
246
247
runtime = Runtime(telemetry=telemetry)
248
249
# For buffered metrics, retrieve updates periodically
250
if isinstance(telemetry.metrics, MetricBuffer):
251
updates = buffer.retrieve_updates()
252
for update in updates:
253
print(f"Metric: {update.metric.name}, Value: {update.value}")
254
```
255
256
### Advanced Configuration
257
258
Global tags, service naming, and metric prefixing for better observability organization.
259
260
```python
261
# Comprehensive telemetry configuration
262
telemetry = TelemetryConfig(
263
logging=LoggingConfig(
264
filter=TelemetryFilter(core_level="INFO", other_level="WARN"),
265
forwarding=LogForwardingConfig(logger=logging.getLogger("temporal"))
266
),
267
metrics=PrometheusConfig(
268
bind_address="0.0.0.0:9090",
269
durations_as_seconds=True
270
),
271
global_tags={
272
"service": "order-service",
273
"environment": "production",
274
"region": "us-west-2"
275
},
276
attach_service_name=True,
277
metric_prefix="orders_temporal_"
278
)
279
```
280
281
### Integration with Clients and Workers
282
283
The runtime is automatically used by clients and workers when set as default.
284
285
```python
286
from temporalio.client import Client
287
from temporalio.worker import Worker
288
from temporalio.runtime import Runtime, TelemetryConfig, PrometheusConfig
289
290
# Configure runtime before creating clients
291
telemetry = TelemetryConfig(
292
metrics=PrometheusConfig(bind_address="0.0.0.0:9090")
293
)
294
Runtime.set_default(Runtime(telemetry=telemetry))
295
296
# Clients and workers will use the configured runtime
297
client = await Client.connect("localhost:7233")
298
worker = Worker(
299
client,
300
task_queue="my-queue",
301
workflows=[MyWorkflow],
302
activities=[my_activity]
303
)
304
305
# Access metrics from the runtime
306
meter = Runtime.default().metric_meter
307
workflow_counter = meter.create_counter(
308
"workflows_executed",
309
"Number of workflows executed"
310
)
311
```
312
313
## Types
314
315
```python { .api }
316
from typing import Union, Optional, Sequence, Mapping, Protocol
317
from datetime import timedelta
318
from enum import Enum
319
import logging
320
321
# Metric buffer constants
322
BufferedMetricKind = NewType("BufferedMetricKind", int)
323
BUFFERED_METRIC_KIND_COUNTER = BufferedMetricKind(0)
324
BUFFERED_METRIC_KIND_GAUGE = BufferedMetricKind(1)
325
BUFFERED_METRIC_KIND_HISTOGRAM = BufferedMetricKind(2)
326
327
# Configuration types
328
MetricsConfig = Union[OpenTelemetryConfig, PrometheusConfig, MetricBuffer]
329
LogFilter = Union[TelemetryFilter, str]
330
```
331
332
## Performance Considerations
333
334
- **Runtime Creation**: Each runtime creates a new internal thread pool, so create sparingly and reuse
335
- **Buffer Size**: Set MetricBuffer size to a high value (tens of thousands) and drain regularly
336
- **Log Forwarding**: Avoid TRACE level logging with log forwarding as it can be high volume
337
- **Metric Periodicity**: Balance between observability needs and performance overhead
338
339
## Best Practices
340
341
1. **Set Runtime Early**: Configure the runtime before creating any clients or workers
342
2. **Single Runtime**: Use one runtime instance per application to avoid resource duplication
343
3. **Metric Naming**: Use consistent prefixes and global tags for better metric organization
344
4. **Log Levels**: Use appropriate log levels for production (WARN for Core, ERROR for others)
345
5. **Metrics Export**: Choose the appropriate metrics backend for your monitoring infrastructure