cloudbase-agent-observability 0.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.
- cloudbase_agent/observability/__init__.py +104 -0
- cloudbase_agent/observability/api.py +302 -0
- cloudbase_agent/observability/attributes.py +336 -0
- cloudbase_agent/observability/constants.py +78 -0
- cloudbase_agent/observability/coze/__init__.py +10 -0
- cloudbase_agent/observability/coze/event_handler.py +565 -0
- cloudbase_agent/observability/crewai/__init__.py +42 -0
- cloudbase_agent/observability/crewai/callback_handler.py +414 -0
- cloudbase_agent/observability/langchain/__init__.py +10 -0
- cloudbase_agent/observability/langchain/callback_handler.py +1158 -0
- cloudbase_agent/observability/server/__init__.py +31 -0
- cloudbase_agent/observability/server/config.py +101 -0
- cloudbase_agent/observability/server/setup.py +412 -0
- cloudbase_agent/observability/span_wrapper.py +374 -0
- cloudbase_agent/observability/tracer.py +116 -0
- cloudbase_agent/observability/types.py +152 -0
- cloudbase_agent_observability-0.1.0.data/data/share/doc/cloudbase_agent_py_observability/README.md +247 -0
- cloudbase_agent_observability-0.1.0.dist-info/METADATA +263 -0
- cloudbase_agent_observability-0.1.0.dist-info/RECORD +20 -0
- cloudbase_agent_observability-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Attribute creation utilities for Cloudbase Agent observability.
|
|
3
|
+
|
|
4
|
+
Maps observation attributes to OpenInference and OpenTelemetry semantic conventions.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
|
|
11
|
+
from opentelemetry import trace
|
|
12
|
+
from opentelemetry.util.types import AttributeValue
|
|
13
|
+
from openinference.semconv.trace import SpanAttributes, OpenInferenceSpanKindValues
|
|
14
|
+
|
|
15
|
+
from cloudbase_agent.observability.types import (
|
|
16
|
+
BaseSpanAttributes,
|
|
17
|
+
LLMAttributes,
|
|
18
|
+
ObservationType,
|
|
19
|
+
ObservationAttributes,
|
|
20
|
+
TraceAttributes,
|
|
21
|
+
)
|
|
22
|
+
from cloudbase_agent.observability.constants import (
|
|
23
|
+
OtelSpanAttributes,
|
|
24
|
+
OpenInferenceSpanKind,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
def _serialize(value: Any) -> Optional[str]:
|
|
30
|
+
"""Safely serialize a value to a JSON string.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
value: The value to serialize.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
JSON string representation, or None if value is None/empty.
|
|
37
|
+
"""
|
|
38
|
+
if value is None:
|
|
39
|
+
return None
|
|
40
|
+
if isinstance(value, str):
|
|
41
|
+
return value
|
|
42
|
+
try:
|
|
43
|
+
return json.dumps(value, default=str)
|
|
44
|
+
except Exception:
|
|
45
|
+
return "<failed to serialize>"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _flatten_metadata(
|
|
49
|
+
metadata: Optional[Dict[str, Any]], prefix: str
|
|
50
|
+
) -> Dict[str, str]:
|
|
51
|
+
"""Flatten and serialize metadata into OpenTelemetry attribute format.
|
|
52
|
+
|
|
53
|
+
Converts nested metadata objects into dot-notation attribute keys.
|
|
54
|
+
For example, `{ "database": { "host": "localhost" } }` becomes
|
|
55
|
+
`{ "metadata.database.host": "localhost" }`.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
metadata: Metadata object to flatten.
|
|
59
|
+
prefix: Attribute prefix (e.g., 'metadata' or 'agkit.observation.metadata').
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Flattened metadata attributes with string values.
|
|
63
|
+
"""
|
|
64
|
+
metadata_attributes: Dict[str, str] = {}
|
|
65
|
+
|
|
66
|
+
if metadata is None:
|
|
67
|
+
return metadata_attributes
|
|
68
|
+
|
|
69
|
+
if not isinstance(metadata, dict):
|
|
70
|
+
serialized = _serialize(metadata)
|
|
71
|
+
if serialized:
|
|
72
|
+
metadata_attributes[prefix] = serialized
|
|
73
|
+
return metadata_attributes
|
|
74
|
+
|
|
75
|
+
for key, value in metadata.items():
|
|
76
|
+
serialized = value if isinstance(value, str) else _serialize(value)
|
|
77
|
+
if serialized:
|
|
78
|
+
metadata_attributes[f"{prefix}.{key}"] = serialized
|
|
79
|
+
|
|
80
|
+
return metadata_attributes
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def create_trace_attributes(attributes: TraceAttributes) -> Dict[str, AttributeValue]:
|
|
84
|
+
"""Create OpenTelemetry trace attributes from TraceAttributes.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
attributes: Trace attributes to convert.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
OpenTelemetry-compatible trace attributes.
|
|
91
|
+
"""
|
|
92
|
+
result = {
|
|
93
|
+
OtelSpanAttributes.TRACE_NAME: attributes.name,
|
|
94
|
+
OtelSpanAttributes.USER_ID: attributes.user_id,
|
|
95
|
+
OtelSpanAttributes.SESSION_ID: attributes.session_id,
|
|
96
|
+
OtelSpanAttributes.VERSION: attributes.version,
|
|
97
|
+
OtelSpanAttributes.RELEASE: attributes.release,
|
|
98
|
+
OtelSpanAttributes.TRACE_INPUT: _serialize(attributes.input),
|
|
99
|
+
OtelSpanAttributes.TRACE_OUTPUT: _serialize(attributes.output),
|
|
100
|
+
OtelSpanAttributes.TRACE_TAGS: (
|
|
101
|
+
",".join(attributes.tags) if attributes.tags else None
|
|
102
|
+
),
|
|
103
|
+
OtelSpanAttributes.ENVIRONMENT: attributes.environment,
|
|
104
|
+
OtelSpanAttributes.TRACE_PUBLIC: attributes.public,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Add flattened metadata
|
|
108
|
+
metadata_attrs = _flatten_and_serialize_metadata(
|
|
109
|
+
attributes.metadata, OtelSpanAttributes.TRACE_METADATA.value
|
|
110
|
+
)
|
|
111
|
+
result.update(metadata_attrs)
|
|
112
|
+
|
|
113
|
+
# Filter out None values
|
|
114
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def create_observation_attributes(
|
|
118
|
+
observation_type: ObservationType, attributes: ObservationAttributes
|
|
119
|
+
) -> Dict[str, AttributeValue]:
|
|
120
|
+
"""Create OpenTelemetry span attributes from observation attributes.
|
|
121
|
+
|
|
122
|
+
Maps observation attributes to OpenInference semantic conventions:
|
|
123
|
+
- Uses `openinference.span.kind` for span type
|
|
124
|
+
- Uses `llm.*` for LLM-specific attributes
|
|
125
|
+
- Uses `tool.*` for tool-specific attributes
|
|
126
|
+
- Falls back to `agkit.observation.*` for non-standard attributes
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
observation_type: The type of observation (llm, tool, chain, etc.)
|
|
130
|
+
attributes: Observation attributes to convert.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
OpenTelemetry-compatible span attributes.
|
|
134
|
+
"""
|
|
135
|
+
# Base attributes for all observation types
|
|
136
|
+
# Handle both dataclass instances and dict input
|
|
137
|
+
level = None
|
|
138
|
+
status_message = None
|
|
139
|
+
version = None
|
|
140
|
+
|
|
141
|
+
if isinstance(attributes, dict):
|
|
142
|
+
level = attributes.get("level")
|
|
143
|
+
status_message = attributes.get("status_message")
|
|
144
|
+
version = attributes.get("version")
|
|
145
|
+
input_value = attributes.get("input")
|
|
146
|
+
output_value = attributes.get("output")
|
|
147
|
+
metadata = attributes.get("metadata")
|
|
148
|
+
else:
|
|
149
|
+
level = attributes.level
|
|
150
|
+
status_message = attributes.status_message
|
|
151
|
+
version = attributes.version
|
|
152
|
+
input_value = attributes.input
|
|
153
|
+
output_value = attributes.output
|
|
154
|
+
metadata = attributes.metadata
|
|
155
|
+
|
|
156
|
+
# Get OpenInference span kind with fallback to UNKNOWN
|
|
157
|
+
try:
|
|
158
|
+
span_kind = OpenInferenceSpanKind[observation_type.upper()].value
|
|
159
|
+
except KeyError:
|
|
160
|
+
logger.warning(
|
|
161
|
+
f"Unknown observation type '{observation_type}', using UNKNOWN span kind"
|
|
162
|
+
)
|
|
163
|
+
span_kind = OpenInferenceSpanKindValues.UNKNOWN.value
|
|
164
|
+
|
|
165
|
+
otel_attributes: Dict[str, AttributeValue] = {
|
|
166
|
+
SpanAttributes.OPENINFERENCE_SPAN_KIND: span_kind,
|
|
167
|
+
OtelSpanAttributes.OBSERVATION_TYPE.value: observation_type,
|
|
168
|
+
OtelSpanAttributes.OBSERVATION_LEVEL.value: (
|
|
169
|
+
level.value if level and hasattr(level, "value") else level
|
|
170
|
+
),
|
|
171
|
+
OtelSpanAttributes.OBSERVATION_STATUS_MESSAGE.value: status_message,
|
|
172
|
+
OtelSpanAttributes.VERSION.value: version,
|
|
173
|
+
# Use OpenInference input.value convention
|
|
174
|
+
SpanAttributes.INPUT_VALUE: _serialize(input_value),
|
|
175
|
+
# Also set legacy observation.input for compatibility
|
|
176
|
+
OtelSpanAttributes.OBSERVATION_INPUT.value: _serialize(input_value),
|
|
177
|
+
# Use OpenInference output.value convention
|
|
178
|
+
SpanAttributes.OUTPUT_VALUE: _serialize(output_value),
|
|
179
|
+
# Also set legacy observation.output for compatibility
|
|
180
|
+
OtelSpanAttributes.OBSERVATION_OUTPUT.value: _serialize(output_value),
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# LLM-specific attributes
|
|
184
|
+
if observation_type == ObservationType.LLM:
|
|
185
|
+
# Handle both dict and dataclass for LLM attributes
|
|
186
|
+
model = None
|
|
187
|
+
model_parameters = None
|
|
188
|
+
usage_details = None
|
|
189
|
+
completion_start_time = None
|
|
190
|
+
|
|
191
|
+
if isinstance(attributes, dict):
|
|
192
|
+
model = attributes.get("model")
|
|
193
|
+
model_parameters = attributes.get("model_parameters")
|
|
194
|
+
usage_details = attributes.get("usage_details")
|
|
195
|
+
completion_start_time = attributes.get("completion_start_time")
|
|
196
|
+
elif hasattr(attributes, "model"):
|
|
197
|
+
model = attributes.model
|
|
198
|
+
model_parameters = attributes.model_parameters
|
|
199
|
+
usage_details = attributes.usage_details
|
|
200
|
+
completion_start_time = attributes.completion_start_time
|
|
201
|
+
|
|
202
|
+
if model:
|
|
203
|
+
otel_attributes[
|
|
204
|
+
SpanAttributes.LLM_MODEL_NAME
|
|
205
|
+
] = model
|
|
206
|
+
if model_parameters:
|
|
207
|
+
otel_attributes[
|
|
208
|
+
SpanAttributes.LLM_INVOCATION_PARAMETERS
|
|
209
|
+
] = _serialize(model_parameters)
|
|
210
|
+
# Also set legacy llm.model_parameters for compatibility
|
|
211
|
+
otel_attributes[
|
|
212
|
+
OtelSpanAttributes.LLM_MODEL_PARAMETERS.value
|
|
213
|
+
] = _serialize(model_parameters)
|
|
214
|
+
if usage_details:
|
|
215
|
+
usage = usage_details
|
|
216
|
+
if isinstance(usage, dict):
|
|
217
|
+
if usage.get("input") is not None:
|
|
218
|
+
otel_attributes[
|
|
219
|
+
SpanAttributes.LLM_TOKEN_COUNT_PROMPT
|
|
220
|
+
] = usage["input"]
|
|
221
|
+
if usage.get("output") is not None:
|
|
222
|
+
otel_attributes[
|
|
223
|
+
SpanAttributes.LLM_TOKEN_COUNT_COMPLETION
|
|
224
|
+
] = usage["output"]
|
|
225
|
+
if usage.get("total") is not None:
|
|
226
|
+
otel_attributes[
|
|
227
|
+
SpanAttributes.LLM_TOKEN_COUNT_TOTAL
|
|
228
|
+
] = usage["total"]
|
|
229
|
+
# Also set legacy llm.usage_details for compatibility
|
|
230
|
+
otel_attributes[
|
|
231
|
+
OtelSpanAttributes.LLM_USAGE_DETAILS.value
|
|
232
|
+
] = _serialize(usage_details)
|
|
233
|
+
if completion_start_time:
|
|
234
|
+
otel_attributes[
|
|
235
|
+
OtelSpanAttributes.LLM_COMPLETION_START_TIME.value
|
|
236
|
+
] = _serialize(completion_start_time)
|
|
237
|
+
|
|
238
|
+
# Embedding-specific attributes
|
|
239
|
+
if observation_type == ObservationType.EMBEDDING:
|
|
240
|
+
# Handle both dict and dataclass for embedding attributes
|
|
241
|
+
model = None
|
|
242
|
+
model_parameters = None
|
|
243
|
+
|
|
244
|
+
if isinstance(attributes, dict):
|
|
245
|
+
model = attributes.get("model")
|
|
246
|
+
model_parameters = attributes.get("model_parameters")
|
|
247
|
+
elif hasattr(attributes, "model"):
|
|
248
|
+
model = attributes.model
|
|
249
|
+
model_parameters = attributes.model_parameters
|
|
250
|
+
|
|
251
|
+
if model:
|
|
252
|
+
otel_attributes[
|
|
253
|
+
SpanAttributes.EMBEDDING_MODEL_NAME
|
|
254
|
+
] = model
|
|
255
|
+
if model_parameters:
|
|
256
|
+
otel_attributes[
|
|
257
|
+
SpanAttributes.LLM_INVOCATION_PARAMETERS
|
|
258
|
+
] = _serialize(model_parameters)
|
|
259
|
+
|
|
260
|
+
# Tool-specific attributes
|
|
261
|
+
if observation_type == ObservationType.TOOL:
|
|
262
|
+
tool_name = None
|
|
263
|
+
if isinstance(attributes, dict):
|
|
264
|
+
tool_name = attributes.get("tool_name")
|
|
265
|
+
elif hasattr(attributes, "tool_name"):
|
|
266
|
+
tool_name = attributes.tool_name
|
|
267
|
+
if tool_name:
|
|
268
|
+
otel_attributes[SpanAttributes.TOOL_NAME] = tool_name
|
|
269
|
+
|
|
270
|
+
# Add metadata (use OpenInference metadata convention)
|
|
271
|
+
metadata_attrs = _flatten_and_serialize_metadata(
|
|
272
|
+
metadata, SpanAttributes.METADATA
|
|
273
|
+
)
|
|
274
|
+
otel_attributes.update(metadata_attrs)
|
|
275
|
+
|
|
276
|
+
# Also add observation.metadata for compatibility
|
|
277
|
+
obsetvability_metadata_attrs = _flatten_and_serialize_metadata(
|
|
278
|
+
metadata, OtelSpanAttributes.OBSERVATION_METADATA.value
|
|
279
|
+
)
|
|
280
|
+
otel_attributes.update(obsetvability_metadata_attrs)
|
|
281
|
+
|
|
282
|
+
# Filter out None values
|
|
283
|
+
return {k: v for k, v in otel_attributes.items() if v is not None}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _flatten_and_serialize_metadata(
|
|
287
|
+
metadata: Optional[Dict[str, Any]], prefix: str
|
|
288
|
+
) -> Dict[str, str]:
|
|
289
|
+
"""Flatten and serialize metadata into OpenTelemetry attribute format.
|
|
290
|
+
|
|
291
|
+
This is an alias for _flatten_metadata for backward compatibility.
|
|
292
|
+
"""
|
|
293
|
+
return _flatten_metadata(metadata, prefix)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def update_active_trace(attributes: TraceAttributes) -> None:
|
|
297
|
+
"""Update the currently active trace with new attributes.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
attributes: Trace attributes to set.
|
|
301
|
+
"""
|
|
302
|
+
current_span = trace.get_current_span()
|
|
303
|
+
if not current_span or not current_span.is_recording():
|
|
304
|
+
logger.debug(
|
|
305
|
+
"No active OTEL span in context. Skipping trace update."
|
|
306
|
+
)
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
trace_attrs = create_trace_attributes(attributes)
|
|
310
|
+
current_span.set_attributes(trace_attrs)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def get_active_trace_id() -> Optional[str]:
|
|
314
|
+
"""Get the current active trace ID.
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
The trace ID as a hex string, or undefined if no active span.
|
|
318
|
+
"""
|
|
319
|
+
current_span = trace.get_current_span()
|
|
320
|
+
if not current_span or not current_span.is_recording():
|
|
321
|
+
return None
|
|
322
|
+
span_context = current_span.get_span_context()
|
|
323
|
+
return format(span_context.trace_id, "032x")
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def get_active_span_id() -> Optional[str]:
|
|
327
|
+
"""Get the current active observation ID.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
The span ID as a hex string, or undefined if no active span.
|
|
331
|
+
"""
|
|
332
|
+
current_span = trace.get_current_span()
|
|
333
|
+
if not current_span or not current_span.is_recording():
|
|
334
|
+
return None
|
|
335
|
+
span_context = current_span.get_span_context()
|
|
336
|
+
return format(span_context.span_id, "016x")
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OTEL attribute constants for Cloudbase Agent observability.
|
|
3
|
+
|
|
4
|
+
Uses OpenInference semantic conventions where applicable:
|
|
5
|
+
https://github.com/Arize-ai/openinference/tree/main/spec
|
|
6
|
+
|
|
7
|
+
Falls back to Cloudbase Agent specific attributes where OpenInference doesn't define a standard.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from openinference.semconv.trace import SpanAttributes, OpenInferenceSpanKindValues
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Re-export OpenInference SpanAttributes for standard attributes
|
|
15
|
+
# Use this for all OpenInference standard conventions (input.value, llm.model_name, etc.)
|
|
16
|
+
OpenInferenceAttributes = SpanAttributes
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Re-export OpenInference span kind values
|
|
20
|
+
class OpenInferenceSpanKind(str, Enum):
|
|
21
|
+
"""OpenInference span kind values."""
|
|
22
|
+
|
|
23
|
+
AGENT = OpenInferenceSpanKindValues.AGENT.value
|
|
24
|
+
CHAIN = OpenInferenceSpanKindValues.CHAIN.value
|
|
25
|
+
LLM = OpenInferenceSpanKindValues.LLM.value
|
|
26
|
+
TOOL = OpenInferenceSpanKindValues.TOOL.value
|
|
27
|
+
RETRIEVER = OpenInferenceSpanKindValues.RETRIEVER.value
|
|
28
|
+
EMBEDDING = OpenInferenceSpanKindValues.EMBEDDING.value
|
|
29
|
+
RERANKER = OpenInferenceSpanKindValues.RERANKER.value
|
|
30
|
+
EVALUATOR = OpenInferenceSpanKindValues.EVALUATOR.value
|
|
31
|
+
GUARDRAIL = OpenInferenceSpanKindValues.GUARDRAIL.value
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# SDK information
|
|
35
|
+
OBSERVABILITY_TRACER_NAME = "agkit-tracer"
|
|
36
|
+
OBSERVABILITY_SDK_NAME = "agkit-observability"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class OtelSpanAttributes(str, Enum):
|
|
40
|
+
"""
|
|
41
|
+
Cloudbase Agent specific (non-standard) OTEL attributes.
|
|
42
|
+
|
|
43
|
+
For standard OpenInference attributes (input.value, llm.model_name, etc.),
|
|
44
|
+
use OpenInferenceAttributes (SpanAttributes) instead.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
# Cloudbase Agent Trace attributes (non-standard)
|
|
48
|
+
TRACE_NAME = "trace.name"
|
|
49
|
+
TRACE_TAGS = "trace.tags"
|
|
50
|
+
TRACE_PUBLIC = "trace.public"
|
|
51
|
+
TRACE_METADATA = "trace.metadata"
|
|
52
|
+
TRACE_INPUT = "trace.input"
|
|
53
|
+
TRACE_OUTPUT = "trace.output"
|
|
54
|
+
|
|
55
|
+
# Cloudbase Agent Observation attributes (non-standard)
|
|
56
|
+
OBSERVATION_TYPE = "observation.type"
|
|
57
|
+
OBSERVATION_LEVEL = "observation.level"
|
|
58
|
+
OBSERVATION_STATUS_MESSAGE = "observation.status_message"
|
|
59
|
+
OBSERVATION_INPUT = "observation.input"
|
|
60
|
+
OBSERVATION_OUTPUT = "observation.output"
|
|
61
|
+
OBSERVATION_METADATA = "observation.metadata"
|
|
62
|
+
|
|
63
|
+
# Cloudbase Agent LLM-specific (non-standard)
|
|
64
|
+
LLM_COMPLETION_START_TIME = "llm.completion_start_time"
|
|
65
|
+
LLM_MODEL_PARAMETERS = "llm.model_parameters"
|
|
66
|
+
LLM_USAGE_DETAILS = "llm.usage_details"
|
|
67
|
+
LLM_COST_DETAILS = "llm.cost_details"
|
|
68
|
+
|
|
69
|
+
# Cloudbase Agent Retriever-specific (non-standard)
|
|
70
|
+
RETRIEVER_NAME = "retriever.name"
|
|
71
|
+
RETRIEVER_QUERY = "retriever.query"
|
|
72
|
+
RETRIEVER_INDEX_ID = "retriever.index_id"
|
|
73
|
+
RETRIEVER_TOP_K = "retriever.top_k"
|
|
74
|
+
|
|
75
|
+
# Cloudbase Agent General (non-standard)
|
|
76
|
+
ENVIRONMENT = "environment"
|
|
77
|
+
RELEASE = "release"
|
|
78
|
+
VERSION = "version"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Coze integration for Cloudbase Agent observability.
|
|
3
|
+
|
|
4
|
+
This module provides a CozeEventHandler that automatically traces Coze
|
|
5
|
+
bot workflows using OpenTelemetry with OpenInference semantic conventions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from cloudbase_agent.observability.coze.event_handler import CozeEventHandler
|
|
9
|
+
|
|
10
|
+
__all__ = ["CozeEventHandler"]
|