dagster-cloud 1.12.10__py3-none-any.whl → 1.12.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dagster_cloud/agent/dagster_cloud_agent.py +43 -86
- dagster_cloud/instance/__init__.py +1 -28
- dagster_cloud/pex/grpc/server/manager.py +3 -3
- dagster_cloud/version.py +1 -1
- dagster_cloud/workspace/docker/__init__.py +2 -1
- dagster_cloud/workspace/ecs/client.py +1 -1
- dagster_cloud/workspace/ecs/launcher.py +8 -4
- dagster_cloud/workspace/kubernetes/launcher.py +5 -3
- dagster_cloud/workspace/kubernetes/utils.py +6 -3
- dagster_cloud/workspace/user_code_launcher/user_code_launcher.py +41 -104
- dagster_cloud/workspace/user_code_launcher/utils.py +14 -0
- {dagster_cloud-1.12.10.dist-info → dagster_cloud-1.12.12.dist-info}/METADATA +16 -13
- {dagster_cloud-1.12.10.dist-info → dagster_cloud-1.12.12.dist-info}/RECORD +15 -37
- {dagster_cloud-1.12.10.dist-info → dagster_cloud-1.12.12.dist-info}/WHEEL +1 -1
- dagster_cloud/agent/instrumentation/__init__.py +0 -0
- dagster_cloud/agent/instrumentation/constants.py +0 -2
- dagster_cloud/agent/instrumentation/run_launch.py +0 -23
- dagster_cloud/agent/instrumentation/schedule.py +0 -34
- dagster_cloud/agent/instrumentation/sensor.py +0 -34
- dagster_cloud/opentelemetry/__init__.py +0 -0
- dagster_cloud/opentelemetry/config/__init__.py +0 -73
- dagster_cloud/opentelemetry/config/exporter.py +0 -81
- dagster_cloud/opentelemetry/config/log_record_processor.py +0 -40
- dagster_cloud/opentelemetry/config/logging_handler.py +0 -14
- dagster_cloud/opentelemetry/config/meter_provider.py +0 -9
- dagster_cloud/opentelemetry/config/metric_reader.py +0 -39
- dagster_cloud/opentelemetry/controller.py +0 -319
- dagster_cloud/opentelemetry/enum.py +0 -58
- dagster_cloud/opentelemetry/factories/__init__.py +0 -1
- dagster_cloud/opentelemetry/factories/logs.py +0 -113
- dagster_cloud/opentelemetry/factories/metrics.py +0 -121
- dagster_cloud/opentelemetry/metrics/__init__.py +0 -0
- dagster_cloud/opentelemetry/metrics/meter.py +0 -140
- dagster_cloud/opentelemetry/observers/__init__.py +0 -0
- dagster_cloud/opentelemetry/observers/dagster_exception_handler.py +0 -40
- dagster_cloud/opentelemetry/observers/execution_observer.py +0 -178
- {dagster_cloud-1.12.10.dist-info → dagster_cloud-1.12.12.dist-info}/top_level.txt +0 -0
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from collections.abc import Mapping
|
|
3
|
-
from threading import Lock
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Optional
|
|
5
|
-
|
|
6
|
-
import dagster_cloud.opentelemetry.factories.logs as logs_factory
|
|
7
|
-
import dagster_cloud.opentelemetry.factories.metrics as metrics_factory
|
|
8
|
-
from dagster_cloud.opentelemetry.metrics.meter import Meter
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from opentelemetry._logs import LoggerProvider as APILoggerProvider
|
|
12
|
-
from opentelemetry.metrics import MeterProvider as APIMeterProvider
|
|
13
|
-
from opentelemetry.sdk._logs import LogRecordProcessor
|
|
14
|
-
from opentelemetry.sdk._logs.export import LogExporter
|
|
15
|
-
from opentelemetry.sdk.metrics.export import MetricExporter, MetricReader
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
DEFAULT_SHUTDOWN_TIMEOUT_MILLIS = 5_000
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class OpenTelemetryController:
|
|
22
|
-
"""The OpenTelemetryController manages the initialization and shutdown of OpenTelemetry components.
|
|
23
|
-
|
|
24
|
-
Provided with a configuration, the OpenTelemetryController will initialize the logging and metrics components.
|
|
25
|
-
The python logging will be instrumented with OpenTelemetry and captured and exported.
|
|
26
|
-
|
|
27
|
-
The get_meter() method allow to obtain a meter than can create metric instruments.
|
|
28
|
-
See: https://opentelemetry.io/docs/languages/python/instrumentation/#metrics
|
|
29
|
-
|
|
30
|
-
Note: As some OpenTelemetry pipeline components run their own thread, it's important to shut down properly.
|
|
31
|
-
|
|
32
|
-
Examples:
|
|
33
|
-
.. code-block:: python
|
|
34
|
-
import logging
|
|
35
|
-
import sys
|
|
36
|
-
import time
|
|
37
|
-
|
|
38
|
-
from dagster_cloud.opentelemetry.controller import OpenTelemetryController
|
|
39
|
-
|
|
40
|
-
otel_config = {
|
|
41
|
-
"enabled": True,
|
|
42
|
-
"logging": {
|
|
43
|
-
"enabled": True,
|
|
44
|
-
"exporter": {
|
|
45
|
-
"type": "ConsoleLogExporter",
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
"metrics": {
|
|
49
|
-
"enabled": True,
|
|
50
|
-
"reader": {
|
|
51
|
-
"type": "PeriodicExportingMetricReader",
|
|
52
|
-
"params": {
|
|
53
|
-
# this is the interval at which metrics are captured and exported
|
|
54
|
-
"export_interval_millis": 800,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
"exporter": {
|
|
58
|
-
"type": "ConsoleMetricExporter",
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def main():
|
|
65
|
-
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
|
66
|
-
logger = logging.getLogger("my_logger")
|
|
67
|
-
|
|
68
|
-
logger.info("OpenTelemetry is not started. This log will not be captured by OpenTelemetry.")
|
|
69
|
-
opentelemetry = OpenTelemetryController(
|
|
70
|
-
instance_id="my_instance",
|
|
71
|
-
version="0.0.1",
|
|
72
|
-
config=otel_config,
|
|
73
|
-
logger=logger, # this and its children will be instrumented with OpenTelemetry
|
|
74
|
-
)
|
|
75
|
-
logger.info("OpenTelemetry started. This log will be exported by OpenTelemetry.")
|
|
76
|
-
meter = opentelemetry.get_meter(name="item_processor", attributes={"environment": "dev"})
|
|
77
|
-
# the counter should be captured as a metric
|
|
78
|
-
counter = meter.create_counter(
|
|
79
|
-
name="items_processed", description="The number of items processed.", unit="unit"
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
# simulate doing some work, and emitting metrics that will be exported by OpenTelemetry
|
|
83
|
-
counter.add(1)
|
|
84
|
-
time.sleep(1)
|
|
85
|
-
counter.add(1)
|
|
86
|
-
time.sleep(1)
|
|
87
|
-
|
|
88
|
-
opentelemetry.dispose()
|
|
89
|
-
logger.info("OpenTelemetry stopped. This log will not be captured by OpenTelemetry.")
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if __name__ == "__main__":
|
|
93
|
-
main()
|
|
94
|
-
"""
|
|
95
|
-
|
|
96
|
-
def __init__(
|
|
97
|
-
self,
|
|
98
|
-
instance_id: str,
|
|
99
|
-
version: str,
|
|
100
|
-
config: Optional[Mapping[str, Any]] = None,
|
|
101
|
-
logger: Optional[logging.Logger] = None,
|
|
102
|
-
):
|
|
103
|
-
"""Initialize the telemetry instance.
|
|
104
|
-
params:
|
|
105
|
-
instance_id: str: The unique identifier of the service instance.
|
|
106
|
-
version: str: The version of the service.
|
|
107
|
-
config: dict: The configuration for the telemetry components.
|
|
108
|
-
logger: Logger: The logger to use for telemetry logs. Defaults to the root logger.
|
|
109
|
-
"""
|
|
110
|
-
self._shutdown = False
|
|
111
|
-
|
|
112
|
-
self._log_exporter: Optional[LogExporter] = None
|
|
113
|
-
self._logger_provider: APILoggerProvider = logs_factory.build_noop_logger_provider()
|
|
114
|
-
self._log_record_processor: Optional[LogRecordProcessor] = None
|
|
115
|
-
self._logging_handler: Optional[logging.Handler] = None
|
|
116
|
-
|
|
117
|
-
self._metric_exporter: Optional[MetricExporter] = None
|
|
118
|
-
self._metric_reader: Optional[MetricReader] = None
|
|
119
|
-
self._meter_provider: APIMeterProvider = metrics_factory.build_noop_meter_provider()
|
|
120
|
-
self._meters: dict[str, Meter] = {}
|
|
121
|
-
|
|
122
|
-
self._config = config or {}
|
|
123
|
-
|
|
124
|
-
service_name = self._config["service_name"]
|
|
125
|
-
|
|
126
|
-
self._logger = logger or logging.getLogger()
|
|
127
|
-
self._resource_attributes = {
|
|
128
|
-
"service.name": service_name,
|
|
129
|
-
"service.version": version,
|
|
130
|
-
"service.instance.id": instance_id,
|
|
131
|
-
}
|
|
132
|
-
self._lock = Lock()
|
|
133
|
-
self._initialize()
|
|
134
|
-
|
|
135
|
-
def _initialize(self):
|
|
136
|
-
"""Initialize the OpenTelemetry components."""
|
|
137
|
-
# an initialized controller can be used in code without having to check if it's
|
|
138
|
-
# enabled as the components will default to NoOp implementations if disabled
|
|
139
|
-
if not self.enabled:
|
|
140
|
-
self._logger.debug(
|
|
141
|
-
"OpenTelemetry is disabled by configuration. Telemetry will not be captured."
|
|
142
|
-
)
|
|
143
|
-
return
|
|
144
|
-
|
|
145
|
-
self._initialize_logging()
|
|
146
|
-
self._initialize_metrics()
|
|
147
|
-
# TODO - self._initialize_tracing()
|
|
148
|
-
|
|
149
|
-
@property
|
|
150
|
-
def enabled(self):
|
|
151
|
-
"""Check if the OpenTelemetry instance is enabled. If not enabled,
|
|
152
|
-
all the components will default to NoOp implementations.
|
|
153
|
-
"""
|
|
154
|
-
if not self._config:
|
|
155
|
-
return False
|
|
156
|
-
|
|
157
|
-
if not self._config.get("enabled", False):
|
|
158
|
-
return False
|
|
159
|
-
|
|
160
|
-
# If no specific opentelemetry components are enabled, then we can effectively disable opentelemetry
|
|
161
|
-
return any(
|
|
162
|
-
[
|
|
163
|
-
self._config.get("metrics", {}).get("enabled", False),
|
|
164
|
-
self._config.get("logging", {}).get("enabled", False),
|
|
165
|
-
self._config.get("tracing", {}).get("enabled", False),
|
|
166
|
-
]
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
@property
|
|
170
|
-
def active(self) -> bool:
|
|
171
|
-
"""Check if the OpenTelemetry instance is active.
|
|
172
|
-
|
|
173
|
-
Returns: bool: True if the instance is active, otherwise False.
|
|
174
|
-
"""
|
|
175
|
-
return not self._shutdown
|
|
176
|
-
|
|
177
|
-
@property
|
|
178
|
-
def logging_enabled(self) -> bool:
|
|
179
|
-
"""Check if the logging component is enabled."""
|
|
180
|
-
return self.enabled and self._config.get("logging", {}).get("enabled", False)
|
|
181
|
-
|
|
182
|
-
@property
|
|
183
|
-
def metrics_enabled(self) -> bool:
|
|
184
|
-
"""Check if the metrics component is enabled."""
|
|
185
|
-
return self.enabled and self._config.get("metrics", {}).get("enabled", False)
|
|
186
|
-
|
|
187
|
-
@property
|
|
188
|
-
def tracing_enabled(self) -> bool:
|
|
189
|
-
"""Check if the tracing component is enabled."""
|
|
190
|
-
return self.enabled and self._config.get("tracing", {}).get("enabled", False)
|
|
191
|
-
|
|
192
|
-
def dispose(self):
|
|
193
|
-
"""Shutdown the OpenTelemetry components."""
|
|
194
|
-
with self._lock:
|
|
195
|
-
if self._shutdown:
|
|
196
|
-
self._logger.warning("OpenTelemetry: Already shutdown, skipping.")
|
|
197
|
-
return
|
|
198
|
-
|
|
199
|
-
# TODO - self._shutdown_tracing()
|
|
200
|
-
self._shutdown_metrics()
|
|
201
|
-
self._shutdown_logging()
|
|
202
|
-
self._shutdown = True
|
|
203
|
-
|
|
204
|
-
def get_meter(
|
|
205
|
-
self,
|
|
206
|
-
name: str,
|
|
207
|
-
version: Optional[str] = None,
|
|
208
|
-
schema_url: Optional[str] = None,
|
|
209
|
-
attributes: Optional[Mapping[str, Any]] = None,
|
|
210
|
-
) -> Meter:
|
|
211
|
-
"""Get or create a meter.
|
|
212
|
-
|
|
213
|
-
params:
|
|
214
|
-
name: str: The name of the meter.
|
|
215
|
-
version: str: The version of the meter.
|
|
216
|
-
schema_url: str: The schema URL of the meter.
|
|
217
|
-
attributes: dict: The attributes of the meter.
|
|
218
|
-
|
|
219
|
-
Returns: Meter: The meter instance.
|
|
220
|
-
"""
|
|
221
|
-
if self._shutdown:
|
|
222
|
-
raise RuntimeError("OpenTelemetry: Cannot get meter, already shutdown.")
|
|
223
|
-
|
|
224
|
-
with self._lock:
|
|
225
|
-
# guarding with a lock because concurrent calls to get_meter
|
|
226
|
-
# could attempt to create multiple identical meters
|
|
227
|
-
if name not in self._meters:
|
|
228
|
-
meter = self._meter_provider.get_meter(
|
|
229
|
-
name=name,
|
|
230
|
-
version=version,
|
|
231
|
-
schema_url=schema_url,
|
|
232
|
-
attributes=attributes,
|
|
233
|
-
)
|
|
234
|
-
self._meters[name] = Meter(meter)
|
|
235
|
-
return self._meters[name]
|
|
236
|
-
|
|
237
|
-
def _initialize_logging(self):
|
|
238
|
-
logging_config = self._config.get("logging", {})
|
|
239
|
-
if not logging_config.get("enabled"):
|
|
240
|
-
self._logger.info(
|
|
241
|
-
"OpenTelemetry: Logging instrumentation is disabled by configuration."
|
|
242
|
-
)
|
|
243
|
-
return
|
|
244
|
-
|
|
245
|
-
self._log_exporter = logs_factory.build_log_exporter(logging_config.get("exporter")) # pyright: ignore[reportArgumentType]
|
|
246
|
-
self._log_record_processor = logs_factory.build_log_record_processor(
|
|
247
|
-
self._log_exporter, logging_config.get("processor", {})
|
|
248
|
-
)
|
|
249
|
-
self._logger_provider = logs_factory.build_logger_provider(
|
|
250
|
-
self._log_record_processor, self._resource_attributes
|
|
251
|
-
)
|
|
252
|
-
self._logging_handler = logs_factory.build_logging_handler(
|
|
253
|
-
self._logger_provider, # pyright: ignore[reportArgumentType]
|
|
254
|
-
logging_config.get("handler", {}),
|
|
255
|
-
)
|
|
256
|
-
self._logger.addHandler(self._logging_handler)
|
|
257
|
-
|
|
258
|
-
def _initialize_metrics(self):
|
|
259
|
-
metrics_config = self._config.get("metrics", {})
|
|
260
|
-
if not metrics_config.get("enabled"):
|
|
261
|
-
self._logger.info("OpenTelemetry: Metric instrumentation is disabled by configuration.")
|
|
262
|
-
return
|
|
263
|
-
|
|
264
|
-
self._metric_exporter = metrics_factory.build_metric_exporter(
|
|
265
|
-
metrics_config.get("exporter", {})
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
self._metric_reader = metrics_factory.build_metric_reader(
|
|
269
|
-
self._metric_exporter, metrics_config.get("reader", {})
|
|
270
|
-
)
|
|
271
|
-
self._meter_provider = metrics_factory.build_meter_provider(
|
|
272
|
-
[self._metric_reader], self._resource_attributes
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
def _initialize_tracing(self):
|
|
276
|
-
tracing_config = self._config.get("tracing", {})
|
|
277
|
-
if not tracing_config.get("enabled"):
|
|
278
|
-
self._logger.info(
|
|
279
|
-
"OpenTelemetry: Tracing instrumentation is disabled by configuration."
|
|
280
|
-
)
|
|
281
|
-
return
|
|
282
|
-
raise NotImplementedError("Tracing instrumentation is not yet implemented.")
|
|
283
|
-
|
|
284
|
-
def _shutdown_logging(self):
|
|
285
|
-
if self._logger and self._logging_handler:
|
|
286
|
-
self._logging_handler.flush()
|
|
287
|
-
self._logger.removeHandler(self._logging_handler)
|
|
288
|
-
|
|
289
|
-
# The LoggerProvider will shut down the record processor, which in turns handles the exporter.
|
|
290
|
-
if self._logger_provider:
|
|
291
|
-
# The NoOpLoggerProvider does not have a force_flush or shutdown method.
|
|
292
|
-
if _validate_object_has_method(self._logger_provider, "force_flush"):
|
|
293
|
-
self._logger_provider.force_flush(timeout_millis=DEFAULT_SHUTDOWN_TIMEOUT_MILLIS) # type: ignore
|
|
294
|
-
if _validate_object_has_method(self._logger_provider, "shutdown"):
|
|
295
|
-
self._logger_provider.shutdown() # pyright: ignore[reportAttributeAccessIssue]
|
|
296
|
-
|
|
297
|
-
def _shutdown_metrics(self):
|
|
298
|
-
# The meter provider will shut down the reader and the PeriodicExportingMetricReader will handle the exporter.
|
|
299
|
-
# Note: the InMemoryMetricReader will not shut down the exporter, it should only be used for testing and
|
|
300
|
-
# does not accept an exporter and one should not exist.
|
|
301
|
-
if self._meter_provider:
|
|
302
|
-
# Duck typing: The base interface and the NoOpMeterProvider do not have a force_flush or shutdown method.
|
|
303
|
-
if _validate_object_has_method(self._meter_provider, "force_flush"):
|
|
304
|
-
self._meter_provider.force_flush(timeout_millis=DEFAULT_SHUTDOWN_TIMEOUT_MILLIS) # type: ignore
|
|
305
|
-
if _validate_object_has_method(self._meter_provider, "shutdown"):
|
|
306
|
-
self._meter_provider.shutdown() # type: ignore
|
|
307
|
-
self._meters = {}
|
|
308
|
-
|
|
309
|
-
def _shutdown_tracing(self):
|
|
310
|
-
# TODO - Tracing instrumentation is not yet implemented.
|
|
311
|
-
pass
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
def _validate_object_has_method(obj, method_name) -> bool:
|
|
315
|
-
"""Check if an object has a callable method.
|
|
316
|
-
|
|
317
|
-
Some OpenTelemetry components do not have some methods, so we need to check if they exist before calling them.
|
|
318
|
-
"""
|
|
319
|
-
return hasattr(obj, method_name) and callable(getattr(obj, method_name))
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class CompressionEnum(Enum):
|
|
5
|
-
GZIP = "gzip"
|
|
6
|
-
DEFLATE = "deflate"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class LoggingExporterEnum(Enum):
|
|
10
|
-
ConsoleLogExporter = "ConsoleLogExporter"
|
|
11
|
-
HttpProtoOTLPExporter = "HttpProtoOTLPExporter"
|
|
12
|
-
GrpcProtoOTLPExporter = "GrpcProtoOTLPExporter"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class LogRecordProcessorEnum(Enum):
|
|
16
|
-
BatchLogRecordProcessor = "BatchLogRecordProcessor"
|
|
17
|
-
SimpleLogRecordProcessor = "SimpleLogRecordProcessor"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class MetricsExporterEnum(Enum):
|
|
21
|
-
ConsoleMetricExporter = "ConsoleMetricExporter"
|
|
22
|
-
HttpProtoOTLPExporter = "HttpProtoOTLPExporter"
|
|
23
|
-
GrpcProtoOTLPExporter = "GrpcProtoOTLPExporter"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class MetricsReaderEnum(Enum):
|
|
27
|
-
PeriodicExportingMetricReader = "PeriodicExportingMetricReader"
|
|
28
|
-
InMemoryMetricReader = "InMemoryMetricReader"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class TracingExporterEnum(Enum):
|
|
32
|
-
HttpProtoOTLPExporter = "HttpProtoOTLPExporter"
|
|
33
|
-
GrpcProtoOTLPExporter = "GrpcProtoOTLPExporter"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class MetricsInstrumentTypesEnum(Enum):
|
|
37
|
-
Counter = "Counter"
|
|
38
|
-
UpDownCounter = "UpDownCounter"
|
|
39
|
-
Histogram = "Histogram"
|
|
40
|
-
Gauge = "Gauge"
|
|
41
|
-
ObservableCounter = "ObservableCounter"
|
|
42
|
-
ObservableUpDownCounter = "ObservableUpDownCounter"
|
|
43
|
-
ObservableGauge = "ObservableGauge"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class AggregationTemporalityEnum(Enum):
|
|
47
|
-
Cumulative = "Cumulative"
|
|
48
|
-
Delta = "Delta"
|
|
49
|
-
Unspecified = "Unspecified"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class ViewAggregationEnum(Enum):
|
|
53
|
-
DefaultAggregation = "DefaultAggregation"
|
|
54
|
-
DropAggregation = "DropAggregation"
|
|
55
|
-
ExplicitBucketHistogramAggregation = "ExplicitBucketHistogramAggregation"
|
|
56
|
-
ExponentialHistogramAggregation = "ExponentialHistogramAggregation"
|
|
57
|
-
LastValueAggregation = "LastValueAggregation"
|
|
58
|
-
SumAggregation = "SumAggregation"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
from opentelemetry._logs import LoggerProvider as APILoggerProvider
|
|
4
|
-
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler, LogRecordProcessor
|
|
5
|
-
from opentelemetry.sdk._logs.export import LogExporter
|
|
6
|
-
from opentelemetry.sdk.resources import Resource
|
|
7
|
-
|
|
8
|
-
from dagster_cloud.opentelemetry.enum import LoggingExporterEnum, LogRecordProcessorEnum
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def build_log_exporter(exporter_config: dict) -> LogExporter:
|
|
12
|
-
"""Build an OpenTelemetry log exporter.
|
|
13
|
-
params:
|
|
14
|
-
exporter_config: dict: The exporter configuration.
|
|
15
|
-
|
|
16
|
-
Returns:
|
|
17
|
-
LogExporter: The log exporter instance.
|
|
18
|
-
"""
|
|
19
|
-
exporter_type = exporter_config.get("type", LoggingExporterEnum.ConsoleLogExporter.value)
|
|
20
|
-
exporter_params = exporter_config.get("params", {})
|
|
21
|
-
|
|
22
|
-
if exporter_type == LoggingExporterEnum.HttpProtoOTLPExporter.value:
|
|
23
|
-
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
|
|
24
|
-
|
|
25
|
-
return OTLPLogExporter(**exporter_params)
|
|
26
|
-
elif exporter_type == LoggingExporterEnum.GrpcProtoOTLPExporter.value:
|
|
27
|
-
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
|
|
28
|
-
|
|
29
|
-
return OTLPLogExporter(**exporter_params)
|
|
30
|
-
elif exporter_type == LoggingExporterEnum.ConsoleLogExporter.value:
|
|
31
|
-
from opentelemetry.sdk._logs.export import ConsoleLogExporter
|
|
32
|
-
|
|
33
|
-
return ConsoleLogExporter(**exporter_params)
|
|
34
|
-
|
|
35
|
-
raise ValueError(f"Invalid exporter type: {exporter_type}")
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def build_log_record_processor(exporter: LogExporter, processor_config: dict) -> LogRecordProcessor:
|
|
39
|
-
"""Build an OpenTelemetry log record processor.
|
|
40
|
-
params:
|
|
41
|
-
processor_config: dict: The processor configuration.
|
|
42
|
-
|
|
43
|
-
Returns:
|
|
44
|
-
LogRecordProcessor: The log record processor instance.
|
|
45
|
-
"""
|
|
46
|
-
processor_type = processor_config.get(
|
|
47
|
-
"type", LogRecordProcessorEnum.SimpleLogRecordProcessor.value
|
|
48
|
-
)
|
|
49
|
-
processor_params = processor_config.get("params", {})
|
|
50
|
-
|
|
51
|
-
if processor_type == LogRecordProcessorEnum.BatchLogRecordProcessor.value:
|
|
52
|
-
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
|
|
53
|
-
|
|
54
|
-
return BatchLogRecordProcessor(exporter, **processor_params)
|
|
55
|
-
elif processor_type == LogRecordProcessorEnum.SimpleLogRecordProcessor.value:
|
|
56
|
-
from opentelemetry.sdk._logs.export import SimpleLogRecordProcessor
|
|
57
|
-
|
|
58
|
-
return SimpleLogRecordProcessor(exporter)
|
|
59
|
-
|
|
60
|
-
raise ValueError(f"Invalid log record processor type: {processor_type}")
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def build_logger_provider(
|
|
64
|
-
processor: LogRecordProcessor,
|
|
65
|
-
resource_attributes: Optional[dict[str, str]] = None,
|
|
66
|
-
) -> APILoggerProvider:
|
|
67
|
-
"""Build an OpenTelemetry logger provider.
|
|
68
|
-
params:
|
|
69
|
-
processor: LogRecordProcessor: The log record processor instance.
|
|
70
|
-
resource: Resource (optional): The resource instance.
|
|
71
|
-
|
|
72
|
-
Returns:
|
|
73
|
-
LoggerProvider: The logger provider instance.
|
|
74
|
-
"""
|
|
75
|
-
from opentelemetry.sdk._logs import LoggerProvider
|
|
76
|
-
|
|
77
|
-
resource = (
|
|
78
|
-
Resource.create(attributes=resource_attributes)
|
|
79
|
-
if resource_attributes
|
|
80
|
-
else Resource.create({})
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
logger_provider = LoggerProvider(
|
|
84
|
-
resource=resource,
|
|
85
|
-
shutdown_on_exit=False,
|
|
86
|
-
)
|
|
87
|
-
logger_provider.add_log_record_processor(processor)
|
|
88
|
-
return logger_provider
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def build_logging_handler(
|
|
92
|
-
logger_provider: LoggerProvider, handler_config: Optional[dict] = None
|
|
93
|
-
) -> LoggingHandler:
|
|
94
|
-
"""Build an OpenTelemetry logging handler.
|
|
95
|
-
Params:
|
|
96
|
-
logger_provider (LoggerProvider): The logger provider instance.
|
|
97
|
-
handler_config (Optional[dict]): The handler configuration.
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
LoggingHandler: The logging handler instance.
|
|
101
|
-
"""
|
|
102
|
-
from opentelemetry.sdk._logs import LoggingHandler
|
|
103
|
-
|
|
104
|
-
handler_config = handler_config or {}
|
|
105
|
-
|
|
106
|
-
return LoggingHandler(logger_provider=logger_provider, **handler_config)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def build_noop_logger_provider() -> APILoggerProvider:
|
|
110
|
-
"""Build a no-op OpenTelemetry meter provider."""
|
|
111
|
-
from opentelemetry._logs import NoOpLoggerProvider
|
|
112
|
-
|
|
113
|
-
return NoOpLoggerProvider()
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
from opentelemetry.metrics import MeterProvider as APIMeterProvider
|
|
4
|
-
from opentelemetry.sdk.metrics.export import MetricExporter, MetricReader
|
|
5
|
-
|
|
6
|
-
from dagster_cloud.opentelemetry.config.exporter import metrics_instrument_types_enum
|
|
7
|
-
from dagster_cloud.opentelemetry.enum import MetricsExporterEnum, MetricsReaderEnum
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def _validate_dict_keys_as_metric_instruments(src: dict, dict_name: str) -> None:
|
|
11
|
-
"""Validate that all keys in a dictionary are valid metric instrument types."""
|
|
12
|
-
for key in src:
|
|
13
|
-
if key not in metrics_instrument_types_enum.enum_values:
|
|
14
|
-
raise ValueError(
|
|
15
|
-
f"OpenTelemetry configuration error - Invalid instrument type '{key}' in {dict_name}."
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def build_metric_exporter(exporter_config: dict) -> MetricExporter:
|
|
20
|
-
"""Build an OpenTelemetry metric exporter.
|
|
21
|
-
params:
|
|
22
|
-
exporter: dict: The exporter configuration.
|
|
23
|
-
- type: str: The exporter type.
|
|
24
|
-
- params: dict: The exporter parameters (varies).
|
|
25
|
-
|
|
26
|
-
Returns:
|
|
27
|
-
MetricExporter: The metric exporter instance.
|
|
28
|
-
"""
|
|
29
|
-
exporter_type = exporter_config.get("type", MetricsExporterEnum.ConsoleMetricExporter.value)
|
|
30
|
-
exporter_params = exporter_config.get("params", {})
|
|
31
|
-
|
|
32
|
-
if "preferred_temporality" in exporter_params:
|
|
33
|
-
_validate_dict_keys_as_metric_instruments(
|
|
34
|
-
exporter_params["preferred_temporality"], "preferred_temporality"
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
if "preferred_aggregation" in exporter_params:
|
|
38
|
-
_validate_dict_keys_as_metric_instruments(
|
|
39
|
-
exporter_params["preferred_aggregation"], "preferred_aggregation"
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
if exporter_type == MetricsExporterEnum.HttpProtoOTLPExporter.value:
|
|
43
|
-
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
|
|
44
|
-
|
|
45
|
-
return OTLPMetricExporter(**exporter_params)
|
|
46
|
-
elif exporter_type == MetricsExporterEnum.GrpcProtoOTLPExporter.value:
|
|
47
|
-
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
|
|
48
|
-
|
|
49
|
-
return OTLPMetricExporter(**exporter_params)
|
|
50
|
-
elif exporter_type == MetricsExporterEnum.ConsoleMetricExporter.value:
|
|
51
|
-
from opentelemetry.sdk.metrics.export import ConsoleMetricExporter
|
|
52
|
-
|
|
53
|
-
return ConsoleMetricExporter(**exporter_params)
|
|
54
|
-
|
|
55
|
-
raise ValueError(f"Invalid exporter type: {exporter_type}")
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def build_metric_reader(
|
|
59
|
-
exporter: Optional[MetricExporter] = None, reader_config: Optional[dict] = None
|
|
60
|
-
) -> MetricReader:
|
|
61
|
-
"""Build an OpenTelemetry metric reader.
|
|
62
|
-
params:
|
|
63
|
-
reader: dict: The reader configuration.
|
|
64
|
-
|
|
65
|
-
Returns:
|
|
66
|
-
MetricReader: The metric reader instance.
|
|
67
|
-
"""
|
|
68
|
-
reader_config = reader_config or {}
|
|
69
|
-
reader_type = reader_config.get("type", MetricsReaderEnum.PeriodicExportingMetricReader.value)
|
|
70
|
-
reader_params = reader_config.get("params", {})
|
|
71
|
-
|
|
72
|
-
if reader_type == MetricsReaderEnum.PeriodicExportingMetricReader.value:
|
|
73
|
-
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
|
|
74
|
-
|
|
75
|
-
if exporter is None:
|
|
76
|
-
raise ValueError("Exporter is required for PeriodicExportingMetricReader.")
|
|
77
|
-
return PeriodicExportingMetricReader(exporter=exporter, **reader_params)
|
|
78
|
-
elif reader_type == MetricsReaderEnum.InMemoryMetricReader.value:
|
|
79
|
-
from opentelemetry.sdk.metrics.export import InMemoryMetricReader
|
|
80
|
-
|
|
81
|
-
return InMemoryMetricReader(**reader_params)
|
|
82
|
-
|
|
83
|
-
raise ValueError(f"Invalid metric reader type: {reader_type}")
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def build_meter_provider(
|
|
87
|
-
metric_readers: list[MetricReader],
|
|
88
|
-
resource_attributes: Optional[dict[str, str]] = None,
|
|
89
|
-
) -> APIMeterProvider:
|
|
90
|
-
"""Build an OpenTelemetry meter provider.
|
|
91
|
-
params:
|
|
92
|
-
metric_reader: MetricReader: The metric reader instance.
|
|
93
|
-
resource: Resource (optional): The resource instance.
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
MeterProvider: The meter provider instance.
|
|
97
|
-
"""
|
|
98
|
-
from opentelemetry.sdk.metrics import MeterProvider
|
|
99
|
-
from opentelemetry.sdk.resources import Resource
|
|
100
|
-
|
|
101
|
-
resource = (
|
|
102
|
-
Resource.create(attributes=resource_attributes)
|
|
103
|
-
if resource_attributes
|
|
104
|
-
else Resource.create({})
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
return MeterProvider(
|
|
108
|
-
metric_readers=metric_readers,
|
|
109
|
-
resource=resource,
|
|
110
|
-
shutdown_on_exit=False,
|
|
111
|
-
# TODO - implement support for views?
|
|
112
|
-
# https://opentelemetry-python.readthedocs.io/en/latest/_modules/opentelemetry/sdk/metrics/_internal/view.html#View
|
|
113
|
-
# views=views,
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def build_noop_meter_provider() -> APIMeterProvider:
|
|
118
|
-
"""Build a no-op OpenTelemetry meter provider."""
|
|
119
|
-
from opentelemetry.metrics import NoOpMeterProvider
|
|
120
|
-
|
|
121
|
-
return NoOpMeterProvider()
|
|
File without changes
|