clue-python-sdk-core 0.0.1__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.
- clue_python_sdk_core/__init__.py +135 -0
- clue_python_sdk_core/adapters.py +2177 -0
- clue_python_sdk_core/bootstrap.py +166 -0
- clue_python_sdk_core/celery.py +734 -0
- clue_python_sdk_core/client.py +335 -0
- clue_python_sdk_core/contracts.py +224 -0
- clue_python_sdk_core/event_size.py +96 -0
- clue_python_sdk_core/http_extraction.py +146 -0
- clue_python_sdk_core/orm.py +534 -0
- clue_python_sdk_core/otel_bridge.py +164 -0
- clue_python_sdk_core/parameter_snapshot.py +152 -0
- clue_python_sdk_core/privacy.py +124 -0
- clue_python_sdk_core/requests_instrumentation.py +341 -0
- clue_python_sdk_core/resources.py +44 -0
- clue_python_sdk_core/runtime.py +894 -0
- clue_python_sdk_core-0.0.1.dist-info/METADATA +11 -0
- clue_python_sdk_core-0.0.1.dist-info/RECORD +19 -0
- clue_python_sdk_core-0.0.1.dist-info/WHEEL +5 -0
- clue_python_sdk_core-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Mapping
|
|
6
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
7
|
+
|
|
8
|
+
from .resources import CluePythonResourceConfig, build_resource_attributes, serialize_resource_attributes
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class CluePythonBootstrapConfig:
|
|
13
|
+
service_name: str
|
|
14
|
+
project_key: str
|
|
15
|
+
environment: str
|
|
16
|
+
deployment_environment: str
|
|
17
|
+
service_type: str
|
|
18
|
+
traces_endpoint: str
|
|
19
|
+
producer_id: str = "python-service"
|
|
20
|
+
api_key: str | None = None
|
|
21
|
+
service_version: str | None = None
|
|
22
|
+
service_namespace: str | None = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def load_bootstrap_config(
|
|
26
|
+
environ: Mapping[str, str] | None = None,
|
|
27
|
+
) -> CluePythonBootstrapConfig:
|
|
28
|
+
env = environ or os.environ
|
|
29
|
+
return CluePythonBootstrapConfig(
|
|
30
|
+
service_name=env.get(
|
|
31
|
+
"OTEL_SERVICE_NAME",
|
|
32
|
+
env.get("CLUE_SERVICE_NAME", "python-service"),
|
|
33
|
+
),
|
|
34
|
+
producer_id=env.get(
|
|
35
|
+
"CLUE_PRODUCER_ID",
|
|
36
|
+
env.get("OTEL_SERVICE_NAME", env.get("CLUE_SERVICE_NAME", "python-service")),
|
|
37
|
+
),
|
|
38
|
+
project_key=env.get("CLUE_PROJECT_KEY", ""),
|
|
39
|
+
environment=env.get("CLUE_ENVIRONMENT", env.get("ENVIRONMENT", "")),
|
|
40
|
+
deployment_environment=env.get(
|
|
41
|
+
"OTEL_DEPLOYMENT_ENVIRONMENT",
|
|
42
|
+
env.get("DEPLOYMENT_ENVIRONMENT", env.get("ENVIRONMENT", "")),
|
|
43
|
+
),
|
|
44
|
+
service_type=env.get("CLUE_SERVICE_TYPE", "api"),
|
|
45
|
+
traces_endpoint=env.get(
|
|
46
|
+
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
|
|
47
|
+
env.get("CLUE_OTLP_TRACES_ENDPOINT", ""),
|
|
48
|
+
),
|
|
49
|
+
api_key=env.get("CLUE_API_KEY"),
|
|
50
|
+
service_version=env.get("OTEL_SERVICE_VERSION", env.get("CLUE_SERVICE_VERSION")),
|
|
51
|
+
service_namespace=env.get(
|
|
52
|
+
"OTEL_SERVICE_NAMESPACE",
|
|
53
|
+
env.get("CLUE_SERVICE_NAMESPACE"),
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def build_otel_environment(
|
|
59
|
+
config: CluePythonBootstrapConfig,
|
|
60
|
+
) -> dict[str, str]:
|
|
61
|
+
resource_attributes = build_resource_attributes(
|
|
62
|
+
CluePythonResourceConfig(
|
|
63
|
+
service_name=config.service_name,
|
|
64
|
+
producer_id=config.producer_id,
|
|
65
|
+
project_key=config.project_key,
|
|
66
|
+
environment=config.environment,
|
|
67
|
+
deployment_environment=config.deployment_environment,
|
|
68
|
+
service_type=config.service_type,
|
|
69
|
+
service_version=config.service_version,
|
|
70
|
+
service_namespace=config.service_namespace,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
env = {
|
|
74
|
+
"OTEL_SERVICE_NAME": config.service_name,
|
|
75
|
+
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": config.traces_endpoint,
|
|
76
|
+
"OTEL_RESOURCE_ATTRIBUTES": serialize_resource_attributes(resource_attributes),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if config.api_key:
|
|
80
|
+
env["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = f"x-clue-api-key={config.api_key}"
|
|
81
|
+
|
|
82
|
+
return env
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def default_traces_endpoint_from_ingest_endpoint(ingest_endpoint: str) -> str:
|
|
86
|
+
trimmed = ingest_endpoint.strip()
|
|
87
|
+
if not trimmed:
|
|
88
|
+
return ""
|
|
89
|
+
|
|
90
|
+
parsed = urlsplit(trimmed)
|
|
91
|
+
if not parsed.scheme or not parsed.netloc:
|
|
92
|
+
return ""
|
|
93
|
+
|
|
94
|
+
path = parsed.path.rstrip("/")
|
|
95
|
+
if path.endswith("/ingest/backend"):
|
|
96
|
+
traces_path = path
|
|
97
|
+
elif path.endswith("/api/v1") or path.endswith("/v1"):
|
|
98
|
+
traces_path = f"{path}/ingest/backend"
|
|
99
|
+
else:
|
|
100
|
+
traces_path = f"{path}/api/v1/ingest/backend"
|
|
101
|
+
|
|
102
|
+
return urlunsplit(
|
|
103
|
+
(
|
|
104
|
+
parsed.scheme,
|
|
105
|
+
parsed.netloc,
|
|
106
|
+
traces_path,
|
|
107
|
+
"",
|
|
108
|
+
"",
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def configure_opentelemetry_environment(
|
|
114
|
+
config: CluePythonBootstrapConfig,
|
|
115
|
+
target: dict[str, str] | None = None,
|
|
116
|
+
) -> dict[str, str]:
|
|
117
|
+
env = target if target is not None else os.environ
|
|
118
|
+
for key, value in build_otel_environment(config).items():
|
|
119
|
+
env[key] = value
|
|
120
|
+
return env
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def initialize_opentelemetry(config: CluePythonBootstrapConfig) -> bool:
|
|
124
|
+
configure_opentelemetry_environment(config)
|
|
125
|
+
if not config.traces_endpoint.strip():
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
from opentelemetry import trace
|
|
130
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
131
|
+
from opentelemetry.sdk.resources import Resource
|
|
132
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
133
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
134
|
+
except ImportError:
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
resource_attributes = build_resource_attributes(
|
|
139
|
+
CluePythonResourceConfig(
|
|
140
|
+
service_name=config.service_name,
|
|
141
|
+
producer_id=config.producer_id,
|
|
142
|
+
project_key=config.project_key,
|
|
143
|
+
environment=config.environment,
|
|
144
|
+
deployment_environment=config.deployment_environment,
|
|
145
|
+
service_type=config.service_type,
|
|
146
|
+
service_version=config.service_version,
|
|
147
|
+
service_namespace=config.service_namespace,
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
headers = {"x-clue-api-key": config.api_key} if config.api_key else None
|
|
151
|
+
provider = TracerProvider(
|
|
152
|
+
resource=Resource.create(resource_attributes),
|
|
153
|
+
)
|
|
154
|
+
provider.add_span_processor(
|
|
155
|
+
BatchSpanProcessor(
|
|
156
|
+
OTLPSpanExporter(
|
|
157
|
+
endpoint=config.traces_endpoint,
|
|
158
|
+
headers=headers,
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
trace.set_tracer_provider(provider)
|
|
163
|
+
except Exception:
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
return True
|