dory-sdk 2.1.0__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.
- dory/__init__.py +70 -0
- dory/auto_instrument.py +142 -0
- dory/cli/__init__.py +5 -0
- dory/cli/main.py +290 -0
- dory/cli/templates.py +333 -0
- dory/config/__init__.py +23 -0
- dory/config/defaults.py +50 -0
- dory/config/loader.py +361 -0
- dory/config/presets.py +325 -0
- dory/config/schema.py +152 -0
- dory/core/__init__.py +27 -0
- dory/core/app.py +404 -0
- dory/core/context.py +209 -0
- dory/core/lifecycle.py +214 -0
- dory/core/meta.py +121 -0
- dory/core/modes.py +479 -0
- dory/core/processor.py +654 -0
- dory/core/signals.py +122 -0
- dory/decorators.py +142 -0
- dory/errors/__init__.py +117 -0
- dory/errors/classification.py +362 -0
- dory/errors/codes.py +495 -0
- dory/health/__init__.py +10 -0
- dory/health/probes.py +210 -0
- dory/health/server.py +306 -0
- dory/k8s/__init__.py +11 -0
- dory/k8s/annotation_watcher.py +184 -0
- dory/k8s/client.py +251 -0
- dory/k8s/pod_metadata.py +182 -0
- dory/logging/__init__.py +9 -0
- dory/logging/logger.py +175 -0
- dory/metrics/__init__.py +7 -0
- dory/metrics/collector.py +301 -0
- dory/middleware/__init__.py +36 -0
- dory/middleware/connection_tracker.py +608 -0
- dory/middleware/request_id.py +321 -0
- dory/middleware/request_tracker.py +501 -0
- dory/migration/__init__.py +11 -0
- dory/migration/configmap.py +260 -0
- dory/migration/serialization.py +167 -0
- dory/migration/state_manager.py +301 -0
- dory/monitoring/__init__.py +23 -0
- dory/monitoring/opentelemetry.py +462 -0
- dory/py.typed +2 -0
- dory/recovery/__init__.py +60 -0
- dory/recovery/golden_image.py +480 -0
- dory/recovery/golden_snapshot.py +561 -0
- dory/recovery/golden_validator.py +518 -0
- dory/recovery/partial_recovery.py +479 -0
- dory/recovery/recovery_decision.py +242 -0
- dory/recovery/restart_detector.py +142 -0
- dory/recovery/state_validator.py +187 -0
- dory/resilience/__init__.py +45 -0
- dory/resilience/circuit_breaker.py +454 -0
- dory/resilience/retry.py +389 -0
- dory/sidecar/__init__.py +6 -0
- dory/sidecar/main.py +75 -0
- dory/sidecar/server.py +329 -0
- dory/simple.py +342 -0
- dory/types.py +75 -0
- dory/utils/__init__.py +25 -0
- dory/utils/errors.py +59 -0
- dory/utils/retry.py +115 -0
- dory/utils/timeout.py +80 -0
- dory_sdk-2.1.0.dist-info/METADATA +663 -0
- dory_sdk-2.1.0.dist-info/RECORD +69 -0
- dory_sdk-2.1.0.dist-info/WHEEL +5 -0
- dory_sdk-2.1.0.dist-info/entry_points.txt +3 -0
- dory_sdk-2.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenTelemetry Integration
|
|
3
|
+
|
|
4
|
+
Provides full OpenTelemetry support for distributed tracing and metrics.
|
|
5
|
+
|
|
6
|
+
Features:
|
|
7
|
+
- Automatic span creation
|
|
8
|
+
- Trace propagation
|
|
9
|
+
- Metrics collection
|
|
10
|
+
- Context management
|
|
11
|
+
- Integration with request IDs
|
|
12
|
+
|
|
13
|
+
Note: Requires opentelemetry packages:
|
|
14
|
+
pip install opentelemetry-api opentelemetry-sdk
|
|
15
|
+
pip install opentelemetry-exporter-otlp
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
from contextlib import contextmanager
|
|
20
|
+
from functools import wraps
|
|
21
|
+
from typing import Any, Dict, Optional, Callable
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# Try to import OpenTelemetry (optional dependency)
|
|
26
|
+
try:
|
|
27
|
+
from opentelemetry import trace
|
|
28
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
29
|
+
from opentelemetry.sdk.trace.export import (
|
|
30
|
+
BatchSpanProcessor,
|
|
31
|
+
ConsoleSpanExporter,
|
|
32
|
+
)
|
|
33
|
+
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
|
|
34
|
+
from opentelemetry.trace import Status, StatusCode, SpanKind
|
|
35
|
+
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
|
36
|
+
|
|
37
|
+
OTEL_AVAILABLE = True
|
|
38
|
+
except ImportError:
|
|
39
|
+
OTEL_AVAILABLE = False
|
|
40
|
+
logger.warning(
|
|
41
|
+
"OpenTelemetry not available. Install with: "
|
|
42
|
+
"pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class OpenTelemetryManager:
|
|
47
|
+
"""
|
|
48
|
+
Manages OpenTelemetry tracing and metrics.
|
|
49
|
+
|
|
50
|
+
Features:
|
|
51
|
+
- Automatic tracer setup
|
|
52
|
+
- Span creation and management
|
|
53
|
+
- Context propagation
|
|
54
|
+
- Metrics collection
|
|
55
|
+
- Export to OTLP endpoints
|
|
56
|
+
|
|
57
|
+
Usage:
|
|
58
|
+
# Initialize
|
|
59
|
+
otel = OpenTelemetryManager(service_name="my-service")
|
|
60
|
+
otel.initialize()
|
|
61
|
+
|
|
62
|
+
# Use decorator
|
|
63
|
+
@otel.trace("process_item")
|
|
64
|
+
async def process_item(item):
|
|
65
|
+
# Automatically traced
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
# Or context manager
|
|
69
|
+
with otel.create_span("operation"):
|
|
70
|
+
# Operations here are traced
|
|
71
|
+
pass
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
service_name: str = "dory-processor",
|
|
77
|
+
service_version: str = "1.0.0",
|
|
78
|
+
environment: str = "production",
|
|
79
|
+
otlp_endpoint: Optional[str] = None,
|
|
80
|
+
console_export: bool = False,
|
|
81
|
+
enable_metrics: bool = True,
|
|
82
|
+
):
|
|
83
|
+
"""
|
|
84
|
+
Initialize OpenTelemetry manager.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
service_name: Name of the service
|
|
88
|
+
service_version: Version of the service
|
|
89
|
+
environment: Environment (production, staging, dev)
|
|
90
|
+
otlp_endpoint: Optional OTLP endpoint URL
|
|
91
|
+
console_export: Export spans to console (for debugging)
|
|
92
|
+
enable_metrics: Enable metrics collection
|
|
93
|
+
"""
|
|
94
|
+
if not OTEL_AVAILABLE:
|
|
95
|
+
raise ImportError(
|
|
96
|
+
"OpenTelemetry not available. Install with: "
|
|
97
|
+
"pip install opentelemetry-api opentelemetry-sdk"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
self.service_name = service_name
|
|
101
|
+
self.service_version = service_version
|
|
102
|
+
self.environment = environment
|
|
103
|
+
self.otlp_endpoint = otlp_endpoint
|
|
104
|
+
self.console_export = console_export
|
|
105
|
+
self.enable_metrics = enable_metrics
|
|
106
|
+
|
|
107
|
+
self._tracer_provider: Optional[TracerProvider] = None
|
|
108
|
+
self._tracer: Optional[trace.Tracer] = None
|
|
109
|
+
self._initialized = False
|
|
110
|
+
|
|
111
|
+
logger.info(
|
|
112
|
+
f"OpenTelemetryManager created: service={service_name}, "
|
|
113
|
+
f"version={service_version}, env={environment}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def initialize(self) -> None:
|
|
117
|
+
"""
|
|
118
|
+
Initialize OpenTelemetry.
|
|
119
|
+
|
|
120
|
+
Sets up tracer provider, exporters, and processors.
|
|
121
|
+
"""
|
|
122
|
+
if self._initialized:
|
|
123
|
+
logger.warning("OpenTelemetry already initialized")
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
# Create resource
|
|
127
|
+
resource = Resource.create({
|
|
128
|
+
SERVICE_NAME: self.service_name,
|
|
129
|
+
"service.version": self.service_version,
|
|
130
|
+
"deployment.environment": self.environment,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
# Create tracer provider
|
|
134
|
+
self._tracer_provider = TracerProvider(resource=resource)
|
|
135
|
+
|
|
136
|
+
# Add console exporter if enabled
|
|
137
|
+
if self.console_export:
|
|
138
|
+
console_exporter = ConsoleSpanExporter()
|
|
139
|
+
console_processor = BatchSpanProcessor(console_exporter)
|
|
140
|
+
self._tracer_provider.add_span_processor(console_processor)
|
|
141
|
+
logger.info("Console span exporter added")
|
|
142
|
+
|
|
143
|
+
# Add OTLP exporter if endpoint provided
|
|
144
|
+
if self.otlp_endpoint:
|
|
145
|
+
try:
|
|
146
|
+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
|
147
|
+
|
|
148
|
+
otlp_exporter = OTLPSpanExporter(endpoint=self.otlp_endpoint)
|
|
149
|
+
otlp_processor = BatchSpanProcessor(otlp_exporter)
|
|
150
|
+
self._tracer_provider.add_span_processor(otlp_processor)
|
|
151
|
+
logger.info(f"OTLP span exporter added: {self.otlp_endpoint}")
|
|
152
|
+
except ImportError:
|
|
153
|
+
logger.warning(
|
|
154
|
+
"OTLP exporter not available. Install with: "
|
|
155
|
+
"pip install opentelemetry-exporter-otlp"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Set global tracer provider
|
|
159
|
+
trace.set_tracer_provider(self._tracer_provider)
|
|
160
|
+
|
|
161
|
+
# Get tracer
|
|
162
|
+
self._tracer = trace.get_tracer(
|
|
163
|
+
instrumenting_module_name=__name__,
|
|
164
|
+
instrumenting_library_version=self.service_version,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
self._initialized = True
|
|
168
|
+
logger.info("OpenTelemetry initialized successfully")
|
|
169
|
+
|
|
170
|
+
def get_tracer(self) -> trace.Tracer:
|
|
171
|
+
"""
|
|
172
|
+
Get the tracer instance.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
OpenTelemetry tracer
|
|
176
|
+
"""
|
|
177
|
+
if not self._initialized:
|
|
178
|
+
self.initialize()
|
|
179
|
+
return self._tracer
|
|
180
|
+
|
|
181
|
+
@contextmanager
|
|
182
|
+
def create_span(
|
|
183
|
+
self,
|
|
184
|
+
name: str,
|
|
185
|
+
attributes: Optional[Dict[str, Any]] = None,
|
|
186
|
+
kind: SpanKind = SpanKind.INTERNAL,
|
|
187
|
+
):
|
|
188
|
+
"""
|
|
189
|
+
Create a span context manager.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
name: Span name
|
|
193
|
+
attributes: Optional span attributes
|
|
194
|
+
kind: Span kind (INTERNAL, SERVER, CLIENT, etc.)
|
|
195
|
+
|
|
196
|
+
Example:
|
|
197
|
+
with otel.create_span("database_query", {"query": "SELECT ...")):
|
|
198
|
+
result = await db.execute(query)
|
|
199
|
+
"""
|
|
200
|
+
if not self._initialized:
|
|
201
|
+
# If not initialized, just yield without tracing
|
|
202
|
+
yield None
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
tracer = self.get_tracer()
|
|
206
|
+
|
|
207
|
+
with tracer.start_as_current_span(name, kind=kind) as span:
|
|
208
|
+
# Add attributes
|
|
209
|
+
if attributes:
|
|
210
|
+
for key, value in attributes.items():
|
|
211
|
+
span.set_attribute(key, value)
|
|
212
|
+
|
|
213
|
+
try:
|
|
214
|
+
yield span
|
|
215
|
+
except Exception as e:
|
|
216
|
+
# Record exception
|
|
217
|
+
span.record_exception(e)
|
|
218
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
219
|
+
raise
|
|
220
|
+
else:
|
|
221
|
+
span.set_status(Status(StatusCode.OK))
|
|
222
|
+
|
|
223
|
+
def trace(
|
|
224
|
+
self,
|
|
225
|
+
name: Optional[str] = None,
|
|
226
|
+
attributes: Optional[Dict[str, Any]] = None,
|
|
227
|
+
kind: SpanKind = SpanKind.INTERNAL,
|
|
228
|
+
):
|
|
229
|
+
"""
|
|
230
|
+
Decorator to automatically trace a function.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
name: Span name (uses function name if None)
|
|
234
|
+
attributes: Optional span attributes
|
|
235
|
+
kind: Span kind
|
|
236
|
+
|
|
237
|
+
Example:
|
|
238
|
+
@otel.trace("process_item")
|
|
239
|
+
async def process_item(item):
|
|
240
|
+
# Automatically traced
|
|
241
|
+
pass
|
|
242
|
+
"""
|
|
243
|
+
def decorator(func):
|
|
244
|
+
span_name = name or func.__name__
|
|
245
|
+
|
|
246
|
+
@wraps(func)
|
|
247
|
+
async def async_wrapper(*args, **kwargs):
|
|
248
|
+
with self.create_span(span_name, attributes, kind):
|
|
249
|
+
return await func(*args, **kwargs)
|
|
250
|
+
|
|
251
|
+
@wraps(func)
|
|
252
|
+
def sync_wrapper(*args, **kwargs):
|
|
253
|
+
with self.create_span(span_name, attributes, kind):
|
|
254
|
+
return func(*args, **kwargs)
|
|
255
|
+
|
|
256
|
+
# Return appropriate wrapper
|
|
257
|
+
import asyncio
|
|
258
|
+
if asyncio.iscoroutinefunction(func):
|
|
259
|
+
return async_wrapper
|
|
260
|
+
else:
|
|
261
|
+
return sync_wrapper
|
|
262
|
+
|
|
263
|
+
return decorator
|
|
264
|
+
|
|
265
|
+
def add_span_attributes(self, attributes: Dict[str, Any]) -> None:
|
|
266
|
+
"""
|
|
267
|
+
Add attributes to current span.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
attributes: Attributes to add
|
|
271
|
+
"""
|
|
272
|
+
if not self._initialized:
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
span = trace.get_current_span()
|
|
276
|
+
if span:
|
|
277
|
+
for key, value in attributes.items():
|
|
278
|
+
span.set_attribute(key, value)
|
|
279
|
+
|
|
280
|
+
def record_exception(self, exception: Exception) -> None:
|
|
281
|
+
"""
|
|
282
|
+
Record an exception in current span.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
exception: Exception to record
|
|
286
|
+
"""
|
|
287
|
+
if not self._initialized:
|
|
288
|
+
return
|
|
289
|
+
|
|
290
|
+
span = trace.get_current_span()
|
|
291
|
+
if span:
|
|
292
|
+
span.record_exception(exception)
|
|
293
|
+
span.set_status(Status(StatusCode.ERROR, str(exception)))
|
|
294
|
+
|
|
295
|
+
def inject_context(self, headers: Dict[str, str]) -> Dict[str, str]:
|
|
296
|
+
"""
|
|
297
|
+
Inject trace context into headers for propagation.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
headers: HTTP headers or similar dict
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
Headers with trace context injected
|
|
304
|
+
"""
|
|
305
|
+
if not self._initialized:
|
|
306
|
+
return headers
|
|
307
|
+
|
|
308
|
+
propagator = TraceContextTextMapPropagator()
|
|
309
|
+
headers = dict(headers)
|
|
310
|
+
propagator.inject(headers)
|
|
311
|
+
return headers
|
|
312
|
+
|
|
313
|
+
def extract_context(self, headers: Dict[str, str]) -> None:
|
|
314
|
+
"""
|
|
315
|
+
Extract trace context from headers.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
headers: HTTP headers or similar dict
|
|
319
|
+
"""
|
|
320
|
+
if not self._initialized:
|
|
321
|
+
return
|
|
322
|
+
|
|
323
|
+
propagator = TraceContextTextMapPropagator()
|
|
324
|
+
context = propagator.extract(headers)
|
|
325
|
+
# Context is automatically set as current
|
|
326
|
+
|
|
327
|
+
def shutdown(self) -> None:
|
|
328
|
+
"""Shutdown OpenTelemetry and flush spans."""
|
|
329
|
+
if self._tracer_provider:
|
|
330
|
+
self._tracer_provider.shutdown()
|
|
331
|
+
logger.info("OpenTelemetry shut down")
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
# Global instance
|
|
335
|
+
_global_otel: Optional[OpenTelemetryManager] = None
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def get_global_otel() -> Optional[OpenTelemetryManager]:
|
|
339
|
+
"""Get global OpenTelemetry manager."""
|
|
340
|
+
return _global_otel
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def initialize_otel(
|
|
344
|
+
service_name: str = "dory-processor",
|
|
345
|
+
**kwargs
|
|
346
|
+
) -> OpenTelemetryManager:
|
|
347
|
+
"""
|
|
348
|
+
Initialize global OpenTelemetry manager.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
service_name: Service name
|
|
352
|
+
**kwargs: Additional arguments for OpenTelemetryManager
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
Initialized OpenTelemetryManager
|
|
356
|
+
"""
|
|
357
|
+
global _global_otel
|
|
358
|
+
|
|
359
|
+
if _global_otel:
|
|
360
|
+
logger.warning("Global OpenTelemetry already initialized")
|
|
361
|
+
return _global_otel
|
|
362
|
+
|
|
363
|
+
_global_otel = OpenTelemetryManager(service_name=service_name, **kwargs)
|
|
364
|
+
_global_otel.initialize()
|
|
365
|
+
|
|
366
|
+
logger.info(f"Global OpenTelemetry initialized for service: {service_name}")
|
|
367
|
+
return _global_otel
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
# Convenience functions using global instance
|
|
371
|
+
|
|
372
|
+
def get_tracer() -> Optional[trace.Tracer]:
|
|
373
|
+
"""Get tracer from global instance."""
|
|
374
|
+
otel = get_global_otel()
|
|
375
|
+
return otel.get_tracer() if otel else None
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def create_span(
|
|
379
|
+
name: str,
|
|
380
|
+
attributes: Optional[Dict[str, Any]] = None,
|
|
381
|
+
kind: SpanKind = SpanKind.INTERNAL,
|
|
382
|
+
):
|
|
383
|
+
"""Create span using global instance."""
|
|
384
|
+
otel = get_global_otel()
|
|
385
|
+
if otel:
|
|
386
|
+
return otel.create_span(name, attributes, kind)
|
|
387
|
+
else:
|
|
388
|
+
# Return no-op context manager
|
|
389
|
+
@contextmanager
|
|
390
|
+
def noop():
|
|
391
|
+
yield None
|
|
392
|
+
return noop()
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def trace_function(
|
|
396
|
+
name: Optional[str] = None,
|
|
397
|
+
attributes: Optional[Dict[str, Any]] = None,
|
|
398
|
+
kind: SpanKind = SpanKind.INTERNAL,
|
|
399
|
+
):
|
|
400
|
+
"""Trace function using global instance."""
|
|
401
|
+
otel = get_global_otel()
|
|
402
|
+
if otel:
|
|
403
|
+
return otel.trace(name, attributes, kind)
|
|
404
|
+
else:
|
|
405
|
+
# Return no-op decorator
|
|
406
|
+
def decorator(func):
|
|
407
|
+
return func
|
|
408
|
+
return decorator
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def add_span_attributes(attributes: Dict[str, Any]) -> None:
|
|
412
|
+
"""Add attributes to current span using global instance."""
|
|
413
|
+
otel = get_global_otel()
|
|
414
|
+
if otel:
|
|
415
|
+
otel.add_span_attributes(attributes)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def record_exception(exception: Exception) -> None:
|
|
419
|
+
"""Record exception in current span using global instance."""
|
|
420
|
+
otel = get_global_otel()
|
|
421
|
+
if otel:
|
|
422
|
+
otel.record_exception(exception)
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
# Integration with request IDs
|
|
426
|
+
|
|
427
|
+
def integrate_with_request_id():
|
|
428
|
+
"""
|
|
429
|
+
Integrate OpenTelemetry with request ID middleware.
|
|
430
|
+
|
|
431
|
+
Automatically adds request IDs as span attributes.
|
|
432
|
+
"""
|
|
433
|
+
try:
|
|
434
|
+
from dory.middleware.request_id import get_current_request_id
|
|
435
|
+
|
|
436
|
+
otel = get_global_otel()
|
|
437
|
+
if not otel:
|
|
438
|
+
logger.warning("OpenTelemetry not initialized")
|
|
439
|
+
return
|
|
440
|
+
|
|
441
|
+
# Monkey patch create_span to add request ID
|
|
442
|
+
original_create_span = otel.create_span
|
|
443
|
+
|
|
444
|
+
@contextmanager
|
|
445
|
+
def create_span_with_request_id(name, attributes=None, kind=SpanKind.INTERNAL):
|
|
446
|
+
# Get current request ID
|
|
447
|
+
request_id = get_current_request_id()
|
|
448
|
+
|
|
449
|
+
# Add to attributes
|
|
450
|
+
attrs = attributes or {}
|
|
451
|
+
if request_id:
|
|
452
|
+
attrs["request.id"] = request_id
|
|
453
|
+
|
|
454
|
+
with original_create_span(name, attrs, kind) as span:
|
|
455
|
+
yield span
|
|
456
|
+
|
|
457
|
+
otel.create_span = create_span_with_request_id
|
|
458
|
+
|
|
459
|
+
logger.info("OpenTelemetry integrated with request ID middleware")
|
|
460
|
+
|
|
461
|
+
except ImportError:
|
|
462
|
+
logger.warning("Request ID middleware not available for integration")
|
dory/py.typed
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Recovery and fault handling modules."""
|
|
2
|
+
|
|
3
|
+
from dory.recovery.restart_detector import RestartDetector, RestartInfo
|
|
4
|
+
from dory.recovery.state_validator import StateValidator
|
|
5
|
+
from dory.recovery.golden_image import GoldenImageManager, ResetLevel, ResetResult, CacheResetManager
|
|
6
|
+
from dory.recovery.recovery_decision import RecoveryDecisionMaker, RecoveryDecision
|
|
7
|
+
from dory.recovery.golden_snapshot import (
|
|
8
|
+
GoldenSnapshotManager,
|
|
9
|
+
Snapshot,
|
|
10
|
+
SnapshotMetadata,
|
|
11
|
+
SnapshotStorageError,
|
|
12
|
+
SnapshotValidationError,
|
|
13
|
+
SnapshotFormat,
|
|
14
|
+
)
|
|
15
|
+
from dory.recovery.golden_validator import (
|
|
16
|
+
GoldenValidator,
|
|
17
|
+
ValidationResult,
|
|
18
|
+
ValidationIssue,
|
|
19
|
+
ValidationSeverity,
|
|
20
|
+
)
|
|
21
|
+
from dory.recovery.partial_recovery import (
|
|
22
|
+
PartialRecoveryManager,
|
|
23
|
+
RecoveryResult as PartialRecoveryResult,
|
|
24
|
+
FieldRecovery,
|
|
25
|
+
FieldStatus,
|
|
26
|
+
numeric_recovery_strategy,
|
|
27
|
+
string_recovery_strategy,
|
|
28
|
+
list_recovery_strategy,
|
|
29
|
+
dict_recovery_strategy,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"RestartDetector",
|
|
34
|
+
"RestartInfo",
|
|
35
|
+
"StateValidator",
|
|
36
|
+
"GoldenImageManager",
|
|
37
|
+
"ResetLevel",
|
|
38
|
+
"ResetResult",
|
|
39
|
+
"CacheResetManager",
|
|
40
|
+
"RecoveryDecisionMaker",
|
|
41
|
+
"RecoveryDecision",
|
|
42
|
+
"GoldenSnapshotManager",
|
|
43
|
+
"Snapshot",
|
|
44
|
+
"SnapshotMetadata",
|
|
45
|
+
"SnapshotStorageError",
|
|
46
|
+
"SnapshotValidationError",
|
|
47
|
+
"SnapshotFormat",
|
|
48
|
+
"GoldenValidator",
|
|
49
|
+
"ValidationResult",
|
|
50
|
+
"ValidationIssue",
|
|
51
|
+
"ValidationSeverity",
|
|
52
|
+
"PartialRecoveryManager",
|
|
53
|
+
"PartialRecoveryResult",
|
|
54
|
+
"FieldRecovery",
|
|
55
|
+
"FieldStatus",
|
|
56
|
+
"numeric_recovery_strategy",
|
|
57
|
+
"string_recovery_strategy",
|
|
58
|
+
"list_recovery_strategy",
|
|
59
|
+
"dict_recovery_strategy",
|
|
60
|
+
]
|