progress-observability 1.5.0__tar.gz → 1.5.3__tar.gz
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.
- {progress_observability-1.5.0 → progress_observability-1.5.3}/PKG-INFO +6 -3
- {progress_observability-1.5.0 → progress_observability-1.5.3}/README.md +3 -1
- {progress_observability-1.5.0 → progress_observability-1.5.3}/pyproject.toml +3 -2
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/genkit_span_processor.py +70 -15
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/sdk.py +130 -9
- {progress_observability-1.5.0 → progress_observability-1.5.3}/uv.lock +4 -2
- {progress_observability-1.5.0 → progress_observability-1.5.3}/.gitignore +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/.python-version +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/LICENSE +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/notices.txt +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/__init__.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/constants.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/decorators.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/enums.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/exceptions.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/genai_message_processor.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/helpers.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/model_fix_processor.py +0 -0
- {progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/tags.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: progress-observability
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.3
|
|
4
4
|
Summary: Progress Observability instrumentation for Python agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/telerik/agentclarity
|
|
6
6
|
Project-URL: Repository, https://github.com/telerik/agentclarity
|
|
@@ -10,7 +10,8 @@ License: MIT
|
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
License-File: notices.txt
|
|
12
12
|
Requires-Python: <4.0.0,>=3.10.0
|
|
13
|
-
Requires-Dist: httpx
|
|
13
|
+
Requires-Dist: httpx==0.28.1
|
|
14
|
+
Requires-Dist: requests==2.34.2
|
|
14
15
|
Requires-Dist: traceloop-sdk==0.62.3
|
|
15
16
|
Description-Content-Type: text/markdown
|
|
16
17
|
|
|
@@ -50,7 +51,7 @@ Common options (for `Observability.instrument`):
|
|
|
50
51
|
- `app_name` - Application name for telemetry
|
|
51
52
|
- `endpoint` - OpenTelemetry collector endpoint
|
|
52
53
|
- `api_key` - Authentication key
|
|
53
|
-
- `debug` -
|
|
54
|
+
- `debug` - Show sanitized OTLP trace-delivery failures on standard error (default: `False`)
|
|
54
55
|
- `instruments` / `block_instruments` - Control what gets traced via `ObservabilityInstruments`
|
|
55
56
|
- `trace_content` - when set to `False` will stop sending LLM prompt/responses as part of the telemetry data
|
|
56
57
|
- `additional_tags` - custom tags (see below)
|
|
@@ -61,8 +62,10 @@ Environment overrides (optional):
|
|
|
61
62
|
- `OBSERVABILITY_ENDPOINT` sets a custom endpoint for collecting data (e.g. "https://collector.observability.progress.com:443")
|
|
62
63
|
- `OBSERVABILITY_API_KEY` sets the authentication key to use when sending data
|
|
63
64
|
- `OBSERVABILITY_TRACE_CONTENT` when set to `false` will stop sending LLM prompt/responses as part of the telemetry data
|
|
65
|
+
- `OBSERVABILITY_DEBUG` enables sanitized trace-delivery errors when set to `1`, `true`, or `yes`
|
|
64
66
|
|
|
65
67
|
Auth headers are added automatically for HTTP(S) endpoints when api_key is provided.
|
|
68
|
+
Invalid endpoints and missing or empty API keys raise during initialization. Delivery failures do not terminate the application and remain silent unless debug logging is enabled. Debug messages never include API keys, authorization headers, or telemetry payloads.
|
|
66
69
|
|
|
67
70
|
## Custom Tags
|
|
68
71
|
|
|
@@ -34,7 +34,7 @@ Common options (for `Observability.instrument`):
|
|
|
34
34
|
- `app_name` - Application name for telemetry
|
|
35
35
|
- `endpoint` - OpenTelemetry collector endpoint
|
|
36
36
|
- `api_key` - Authentication key
|
|
37
|
-
- `debug` -
|
|
37
|
+
- `debug` - Show sanitized OTLP trace-delivery failures on standard error (default: `False`)
|
|
38
38
|
- `instruments` / `block_instruments` - Control what gets traced via `ObservabilityInstruments`
|
|
39
39
|
- `trace_content` - when set to `False` will stop sending LLM prompt/responses as part of the telemetry data
|
|
40
40
|
- `additional_tags` - custom tags (see below)
|
|
@@ -45,8 +45,10 @@ Environment overrides (optional):
|
|
|
45
45
|
- `OBSERVABILITY_ENDPOINT` sets a custom endpoint for collecting data (e.g. "https://collector.observability.progress.com:443")
|
|
46
46
|
- `OBSERVABILITY_API_KEY` sets the authentication key to use when sending data
|
|
47
47
|
- `OBSERVABILITY_TRACE_CONTENT` when set to `false` will stop sending LLM prompt/responses as part of the telemetry data
|
|
48
|
+
- `OBSERVABILITY_DEBUG` enables sanitized trace-delivery errors when set to `1`, `true`, or `yes`
|
|
48
49
|
|
|
49
50
|
Auth headers are added automatically for HTTP(S) endpoints when api_key is provided.
|
|
51
|
+
Invalid endpoints and missing or empty API keys raise during initialization. Delivery failures do not terminate the application and remain silent unless debug logging is enabled. Debug messages never include API keys, authorization headers, or telemetry payloads.
|
|
50
52
|
|
|
51
53
|
## Custom Tags
|
|
52
54
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "progress-observability"
|
|
7
|
-
version = "1.5.
|
|
7
|
+
version = "1.5.3"
|
|
8
8
|
description = "Progress Observability instrumentation for Python agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -12,7 +12,8 @@ license-files = ["LICENSE", "notices.txt"]
|
|
|
12
12
|
requires-python = ">=3.10.0,<4.0.0"
|
|
13
13
|
dependencies = [
|
|
14
14
|
"traceloop-sdk==0.62.3",
|
|
15
|
-
"httpx
|
|
15
|
+
"httpx==0.28.1",
|
|
16
|
+
"requests==2.34.2",
|
|
16
17
|
]
|
|
17
18
|
[project.urls]
|
|
18
19
|
Homepage = "https://github.com/telerik/agentclarity"
|
|
@@ -37,6 +37,20 @@ def _normalize_role(role: Any) -> str:
|
|
|
37
37
|
return role if isinstance(role, str) else "unknown"
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
def _merge_consecutive_text_parts(parts: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
41
|
+
# Streaming responses (e.g. Genkit's generate_stream) record the final message content
|
|
42
|
+
# as a sequence of raw text deltas rather than one coalesced string. Merge adjacent
|
|
43
|
+
# text parts so consumers see the reassembled text instead of fragmented chunks.
|
|
44
|
+
merged: list[dict[str, Any]] = []
|
|
45
|
+
for part in parts:
|
|
46
|
+
previous = merged[-1] if merged else None
|
|
47
|
+
if part.get("type") == "text" and previous is not None and previous.get("type") == "text":
|
|
48
|
+
previous["content"] = f"{previous.get('content', '')}{part.get('content', '')}"
|
|
49
|
+
continue
|
|
50
|
+
merged.append(dict(part))
|
|
51
|
+
return merged
|
|
52
|
+
|
|
53
|
+
|
|
40
54
|
def _normalize_parts(content: Any) -> list[dict[str, Any]]:
|
|
41
55
|
if not isinstance(content, list):
|
|
42
56
|
return [{"type": "text", "content": content}] if isinstance(content, str) else []
|
|
@@ -65,7 +79,7 @@ def _normalize_parts(content: Any) -> list[dict[str, Any]]:
|
|
|
65
79
|
parts.append(part)
|
|
66
80
|
else:
|
|
67
81
|
parts.append({"type": item.get("type", "unknown"), **item})
|
|
68
|
-
return parts
|
|
82
|
+
return _merge_consecutive_text_parts(parts)
|
|
69
83
|
|
|
70
84
|
|
|
71
85
|
def _normalize_messages(value: Any) -> list[dict[str, Any]]:
|
|
@@ -81,6 +95,9 @@ def _normalize_messages(value: Any) -> list[dict[str, Any]]:
|
|
|
81
95
|
class GenkitSpanProcessor:
|
|
82
96
|
"""Post-process native Genkit action spans before export."""
|
|
83
97
|
|
|
98
|
+
def __init__(self, trace_content: bool = True) -> None:
|
|
99
|
+
self._trace_content = trace_content
|
|
100
|
+
|
|
84
101
|
def on_end(self, span: Any) -> None:
|
|
85
102
|
attributes = get_writable_attributes(span)
|
|
86
103
|
if not attributes or "genkit:type" not in attributes:
|
|
@@ -92,8 +109,44 @@ class GenkitSpanProcessor:
|
|
|
92
109
|
return
|
|
93
110
|
if subtype == "tool":
|
|
94
111
|
attributes.setdefault("traceloop.span.kind", "tool")
|
|
112
|
+
attributes.setdefault("gen_ai.operation.name", "execute_tool")
|
|
113
|
+
tool_name = attributes.get("genkit:name")
|
|
114
|
+
if isinstance(tool_name, str) and tool_name:
|
|
115
|
+
attributes.setdefault("gen_ai.tool.name", tool_name)
|
|
116
|
+
if self._trace_content:
|
|
117
|
+
tool_input = attributes.get("genkit:input")
|
|
118
|
+
if isinstance(tool_input, str):
|
|
119
|
+
attributes.setdefault("gen_ai.tool.call.arguments", tool_input)
|
|
120
|
+
tool_output = attributes.get("genkit:output")
|
|
121
|
+
if isinstance(tool_output, str):
|
|
122
|
+
attributes.setdefault("gen_ai.tool.call.result", tool_output)
|
|
95
123
|
return
|
|
96
124
|
if subtype != "model":
|
|
125
|
+
# The root span of ai.generate()/ai.generate_stream() calls made outside of an
|
|
126
|
+
# explicit flow isn't tagged with a subtype (it's registered as a "util"
|
|
127
|
+
# action), so it falls through every branch above and is left without a span
|
|
128
|
+
# kind or provider. Since genkit:input carries the requested model name, derive
|
|
129
|
+
# both from it the same way the model span does. Genkit's built-in generate
|
|
130
|
+
# action always reports subtype "util" (or omits it for nested turns); guard
|
|
131
|
+
# on that so a user-defined action merely named "generate" with a different
|
|
132
|
+
# subtype (e.g. "prompt") isn't misclassified.
|
|
133
|
+
if attributes.get("genkit:name") == "generate" and subtype in (None, "util"):
|
|
134
|
+
attributes.setdefault("traceloop.span.kind", "agent")
|
|
135
|
+
input_data = _parse_json(attributes.get("genkit:input"))
|
|
136
|
+
model_name = input_data.get("model") if input_data else None
|
|
137
|
+
if isinstance(model_name, str) and model_name:
|
|
138
|
+
separator = model_name.find("/")
|
|
139
|
+
if separator >= 0:
|
|
140
|
+
plugin = model_name[:separator].lower()
|
|
141
|
+
model = model_name[separator + 1 :]
|
|
142
|
+
if "gen_ai.provider.name" not in attributes and plugin:
|
|
143
|
+
attributes["gen_ai.provider.name"] = _PROVIDERS.get(
|
|
144
|
+
plugin, plugin[:1].upper() + plugin[1:]
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
model = model_name
|
|
148
|
+
attributes.setdefault("gen_ai.request.model", model)
|
|
149
|
+
attributes.setdefault("gen_ai.response.model", model)
|
|
97
150
|
return
|
|
98
151
|
|
|
99
152
|
name = attributes.get("genkit:name")
|
|
@@ -111,24 +164,26 @@ class GenkitSpanProcessor:
|
|
|
111
164
|
attributes.setdefault("gen_ai.request.model", model)
|
|
112
165
|
attributes.setdefault("gen_ai.response.model", model)
|
|
113
166
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
167
|
+
if self._trace_content:
|
|
168
|
+
input_data = _parse_json(attributes.get("genkit:input"))
|
|
169
|
+
if input_data and "gen_ai.input.messages" not in attributes:
|
|
170
|
+
messages = _normalize_messages(input_data.get("messages"))
|
|
171
|
+
if messages:
|
|
172
|
+
attributes["gen_ai.input.messages"] = json.dumps(messages)
|
|
119
173
|
|
|
120
174
|
output_data = _parse_json(attributes.get("genkit:output"))
|
|
121
175
|
if not output_data:
|
|
122
176
|
return
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
177
|
+
if self._trace_content:
|
|
178
|
+
output_message = output_data.get("message")
|
|
179
|
+
if output_message is None and isinstance(output_data.get("candidates"), list):
|
|
180
|
+
candidates = output_data["candidates"]
|
|
181
|
+
if candidates and isinstance(candidates[0], dict):
|
|
182
|
+
output_message = candidates[0].get("message")
|
|
183
|
+
if isinstance(output_message, dict) and "gen_ai.output.messages" not in attributes:
|
|
184
|
+
messages = _normalize_messages([output_message])
|
|
185
|
+
if messages:
|
|
186
|
+
attributes["gen_ai.output.messages"] = json.dumps(messages)
|
|
132
187
|
|
|
133
188
|
usage = output_data.get("usage")
|
|
134
189
|
if isinstance(usage, dict):
|
{progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/sdk.py
RENAMED
|
@@ -19,6 +19,7 @@ Quick Start:
|
|
|
19
19
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
+
import re
|
|
22
23
|
import sys
|
|
23
24
|
import os
|
|
24
25
|
from contextlib import redirect_stdout, redirect_stderr
|
|
@@ -63,6 +64,88 @@ class Observability:
|
|
|
63
64
|
_tags_processor = None # TagsSpanProcessor instance for tag propagation
|
|
64
65
|
SDK = Traceloop
|
|
65
66
|
|
|
67
|
+
_EXPORTER_LOGGER_NAME = "opentelemetry.exporter.otlp.proto.http.trace_exporter"
|
|
68
|
+
_EXPORTER_HANDLER_MARKER = "_progress_observability_handler"
|
|
69
|
+
_EXPORTER_FILTER_MARKER = "_progress_observability_filter"
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def _sanitize_exporter_message(message: str) -> str:
|
|
73
|
+
"""Map exporter failures to useful messages without exposing request data."""
|
|
74
|
+
normalized = message.lower()
|
|
75
|
+
|
|
76
|
+
status_match = re.search(r"\b(401|403)\b", normalized)
|
|
77
|
+
if status_match:
|
|
78
|
+
status_messages = {
|
|
79
|
+
"401": "HTTP 401 Unauthorized.",
|
|
80
|
+
"403": "HTTP 403 Forbidden.",
|
|
81
|
+
}
|
|
82
|
+
return status_messages[status_match.group(1)]
|
|
83
|
+
if "timed out" in normalized or "timeout" in normalized:
|
|
84
|
+
return "request timed out."
|
|
85
|
+
if any(
|
|
86
|
+
term in normalized for term in ("name resolution", "resolve host", "dns")
|
|
87
|
+
):
|
|
88
|
+
return "collector host could not be resolved."
|
|
89
|
+
if any(
|
|
90
|
+
term in normalized
|
|
91
|
+
for term in (
|
|
92
|
+
"connection refused",
|
|
93
|
+
"unreachable",
|
|
94
|
+
"failed to establish a new connection",
|
|
95
|
+
)
|
|
96
|
+
):
|
|
97
|
+
return "collector is unreachable."
|
|
98
|
+
return "failed to export traces."
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def _configure_exporter_logging(cls, debug_enabled: bool) -> None:
|
|
102
|
+
exporter_logger = logging.getLogger(cls._EXPORTER_LOGGER_NAME)
|
|
103
|
+
|
|
104
|
+
for handler in list(exporter_logger.handlers):
|
|
105
|
+
if getattr(handler, cls._EXPORTER_HANDLER_MARKER, False):
|
|
106
|
+
exporter_logger.removeHandler(handler)
|
|
107
|
+
handler.close()
|
|
108
|
+
for logger_filter in list(exporter_logger.filters):
|
|
109
|
+
if getattr(logger_filter, cls._EXPORTER_FILTER_MARKER, False):
|
|
110
|
+
exporter_logger.removeFilter(logger_filter)
|
|
111
|
+
|
|
112
|
+
exporter_logger.propagate = False
|
|
113
|
+
exporter_logger.disabled = not debug_enabled
|
|
114
|
+
|
|
115
|
+
if not debug_enabled:
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
class SanitizingFilter(logging.Filter):
|
|
119
|
+
_progress_observability_filter = True
|
|
120
|
+
|
|
121
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
122
|
+
record.msg = cls._sanitize_exporter_message(record.getMessage())
|
|
123
|
+
record.args = ()
|
|
124
|
+
record.exc_info = None
|
|
125
|
+
record.exc_text = None
|
|
126
|
+
record.stack_info = None
|
|
127
|
+
return True
|
|
128
|
+
|
|
129
|
+
exporter_logger.setLevel(logging.ERROR)
|
|
130
|
+
handler = logging.StreamHandler(sys.stderr)
|
|
131
|
+
handler.setLevel(logging.ERROR)
|
|
132
|
+
handler.setFormatter(
|
|
133
|
+
logging.Formatter(
|
|
134
|
+
"[Observability] Failed to export traces: %(message)s"
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
setattr(handler, cls._EXPORTER_HANDLER_MARKER, True)
|
|
138
|
+
exporter_logger.addFilter(SanitizingFilter())
|
|
139
|
+
exporter_logger.addHandler(handler)
|
|
140
|
+
|
|
141
|
+
@staticmethod
|
|
142
|
+
def _report_configuration_failure(debug_enabled: bool, message: str) -> None:
|
|
143
|
+
if debug_enabled:
|
|
144
|
+
print(
|
|
145
|
+
f"[Observability] Configuration error: {message}",
|
|
146
|
+
file=sys.stderr,
|
|
147
|
+
)
|
|
148
|
+
|
|
66
149
|
@staticmethod
|
|
67
150
|
def _validate_endpoint(endpoint: Optional[str]) -> str:
|
|
68
151
|
"""
|
|
@@ -131,7 +214,7 @@ class Observability:
|
|
|
131
214
|
return endpoint
|
|
132
215
|
|
|
133
216
|
@staticmethod
|
|
134
|
-
def _validate_api_key(api_key: Optional[str]) ->
|
|
217
|
+
def _validate_api_key(api_key: Optional[str]) -> str:
|
|
135
218
|
"""Validate the API key is provided via parameter or environment variable.
|
|
136
219
|
Args:
|
|
137
220
|
api_key: The API key parameter value to validate
|
|
@@ -258,17 +341,49 @@ class Observability:
|
|
|
258
341
|
# Always allow re-initialization to support different instrument configurations
|
|
259
342
|
# The underlying traceloop SDK will handle duplicate initialization safely
|
|
260
343
|
|
|
261
|
-
# Validate and resolve endpoint and API key before processing
|
|
262
|
-
endpoint = cls._validate_endpoint(endpoint)
|
|
263
|
-
api_key = cls._validate_api_key(api_key)
|
|
264
|
-
|
|
265
|
-
app_name = init_environment(app_name, trace_content)
|
|
266
|
-
|
|
267
344
|
# Ensure debug logs are visible when explicitly requested.
|
|
268
345
|
# Honor both the debug parameter and the OBSERVABILITY_DEBUG env var.
|
|
269
346
|
# Only raise the progress.observability logger - not the root logger,
|
|
270
347
|
# which would make every third-party library verbose.
|
|
271
|
-
debug_enabled = debug or os.getenv("OBSERVABILITY_DEBUG", "").lower() in (
|
|
348
|
+
debug_enabled = debug or os.getenv("OBSERVABILITY_DEBUG", "").lower() in (
|
|
349
|
+
"1",
|
|
350
|
+
"true",
|
|
351
|
+
"yes",
|
|
352
|
+
)
|
|
353
|
+
cls._configure_exporter_logging(debug_enabled)
|
|
354
|
+
|
|
355
|
+
endpoint_error: Optional[Exception] = None
|
|
356
|
+
api_key_error: Optional[Exception] = None
|
|
357
|
+
|
|
358
|
+
try:
|
|
359
|
+
endpoint = cls._validate_endpoint(endpoint)
|
|
360
|
+
except EndpointValidationError as exc:
|
|
361
|
+
endpoint_error = exc
|
|
362
|
+
cls._report_configuration_failure(
|
|
363
|
+
debug_enabled,
|
|
364
|
+
"endpoint is invalid. Use a valid http/https URL with host and port.",
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
try:
|
|
368
|
+
api_key = cls._validate_api_key(api_key)
|
|
369
|
+
except (TypeError, ValueError) as exc:
|
|
370
|
+
api_key_error = exc
|
|
371
|
+
cls._report_configuration_failure(
|
|
372
|
+
debug_enabled,
|
|
373
|
+
"API key is missing or empty.",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
if endpoint_error and api_key_error:
|
|
377
|
+
raise ValueError(
|
|
378
|
+
"Invalid configuration: endpoint is invalid and API key is missing or empty."
|
|
379
|
+
) from api_key_error
|
|
380
|
+
if endpoint_error:
|
|
381
|
+
raise endpoint_error
|
|
382
|
+
if api_key_error:
|
|
383
|
+
raise api_key_error
|
|
384
|
+
|
|
385
|
+
app_name = init_environment(app_name, trace_content)
|
|
386
|
+
|
|
272
387
|
if debug_enabled:
|
|
273
388
|
pkg_logger = logging.getLogger("progress.observability")
|
|
274
389
|
pkg_logger.setLevel(logging.DEBUG)
|
|
@@ -280,9 +395,13 @@ class Observability:
|
|
|
280
395
|
handler.addFilter(lambda record: record.levelno == logging.DEBUG)
|
|
281
396
|
pkg_logger.addHandler(handler)
|
|
282
397
|
|
|
398
|
+
# Resolve the effective trace_content setting (init_environment() already
|
|
399
|
+
# applied env var precedence and may have set TRACELOOP_TRACE_CONTENT).
|
|
400
|
+
trace_content_enabled = os.getenv("TRACELOOP_TRACE_CONTENT", "true").lower() == "true"
|
|
401
|
+
|
|
283
402
|
# Create processors with debug mode
|
|
284
403
|
genai_message_processor = GenAIMessageProcessor(debug=debug_enabled)
|
|
285
|
-
genkit_span_processor = GenkitSpanProcessor()
|
|
404
|
+
genkit_span_processor = GenkitSpanProcessor(trace_content=trace_content_enabled)
|
|
286
405
|
model_fix_processor = ModelFixProcessor(debug=debug_enabled)
|
|
287
406
|
cls._model_fix_processor = model_fix_processor
|
|
288
407
|
|
|
@@ -376,6 +495,8 @@ class Observability:
|
|
|
376
495
|
After shutdown, subsequent calls to instrument() will reinitialize
|
|
377
496
|
the instrumentation.
|
|
378
497
|
"""
|
|
498
|
+
cls._configure_exporter_logging(False)
|
|
499
|
+
|
|
379
500
|
if not cls._initialized:
|
|
380
501
|
return True
|
|
381
502
|
|
|
@@ -1544,16 +1544,18 @@ wheels = [
|
|
|
1544
1544
|
|
|
1545
1545
|
[[package]]
|
|
1546
1546
|
name = "progress-observability"
|
|
1547
|
-
version = "1.5.
|
|
1547
|
+
version = "1.5.3"
|
|
1548
1548
|
source = { editable = "." }
|
|
1549
1549
|
dependencies = [
|
|
1550
1550
|
{ name = "httpx" },
|
|
1551
|
+
{ name = "requests" },
|
|
1551
1552
|
{ name = "traceloop-sdk" },
|
|
1552
1553
|
]
|
|
1553
1554
|
|
|
1554
1555
|
[package.metadata]
|
|
1555
1556
|
requires-dist = [
|
|
1556
|
-
{ name = "httpx", specifier = "
|
|
1557
|
+
{ name = "httpx", specifier = "==0.28.1" },
|
|
1558
|
+
{ name = "requests", specifier = "==2.34.2" },
|
|
1557
1559
|
{ name = "traceloop-sdk", specifier = "==0.62.3" },
|
|
1558
1560
|
]
|
|
1559
1561
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/enums.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{progress_observability-1.5.0 → progress_observability-1.5.3}/src/progress/observability/tags.py
RENAMED
|
File without changes
|