microsoft-agents-a365-observability-core 0.2.0.dev5__py3-none-any.whl → 0.2.1.dev0__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.
Files changed (29) hide show
  1. microsoft_agents_a365/observability/core/__init__.py +2 -1
  2. microsoft_agents_a365/observability/core/config.py +34 -20
  3. microsoft_agents_a365/observability/core/constants.py +2 -1
  4. microsoft_agents_a365/observability/core/execute_tool_scope.py +15 -1
  5. microsoft_agents_a365/observability/core/execution_type.py +2 -1
  6. microsoft_agents_a365/observability/core/exporters/__init__.py +8 -0
  7. microsoft_agents_a365/observability/core/exporters/agent365_exporter.py +50 -6
  8. microsoft_agents_a365/observability/core/exporters/utils.py +56 -1
  9. microsoft_agents_a365/observability/core/inference_call_details.py +2 -1
  10. microsoft_agents_a365/observability/core/inference_operation_type.py +2 -1
  11. microsoft_agents_a365/observability/core/inference_scope.py +9 -0
  12. microsoft_agents_a365/observability/core/invoke_agent_details.py +2 -1
  13. microsoft_agents_a365/observability/core/middleware/__init__.py +2 -1
  14. microsoft_agents_a365/observability/core/middleware/baggage_builder.py +13 -18
  15. microsoft_agents_a365/observability/core/opentelemetry_scope.py +2 -1
  16. microsoft_agents_a365/observability/core/request.py +2 -1
  17. microsoft_agents_a365/observability/core/source_metadata.py +2 -1
  18. microsoft_agents_a365/observability/core/tenant_details.py +2 -1
  19. microsoft_agents_a365/observability/core/tool_call_details.py +2 -1
  20. microsoft_agents_a365/observability/core/tool_type.py +2 -1
  21. microsoft_agents_a365/observability/core/trace_processor/__init__.py +2 -1
  22. microsoft_agents_a365/observability/core/trace_processor/span_processor.py +3 -2
  23. microsoft_agents_a365/observability/core/trace_processor/util.py +3 -1
  24. {microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info → microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info}/METADATA +1 -1
  25. microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info/RECORD +35 -0
  26. {microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info → microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info}/WHEEL +1 -1
  27. {microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info → microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info}/top_level.txt +1 -0
  28. microsoft_agents_a365/observability/core/middleware/turn_context_baggage.py +0 -192
  29. microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info/RECORD +0 -35
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Microsoft Agent 365 Python SDK for OpenTelemetry tracing.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  import logging
4
5
  import threading
@@ -10,7 +11,7 @@ from opentelemetry.sdk.resources import SERVICE_NAME, SERVICE_NAMESPACE, Resourc
10
11
  from opentelemetry.sdk.trace import TracerProvider
11
12
  from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
12
13
 
13
- from .exporters.agent365_exporter import Agent365Exporter
14
+ from .exporters.agent365_exporter import _Agent365Exporter
14
15
  from .exporters.agent365_exporter_options import Agent365ExporterOptions
15
16
  from .exporters.utils import is_agent365_exporter_enabled
16
17
  from .trace_processor.span_processor import SpanProcessor
@@ -53,6 +54,7 @@ class TelemetryManager:
53
54
  token_resolver: Callable[[str, str], str | None] | None = None,
54
55
  cluster_category: str = "prod",
55
56
  exporter_options: Optional[Agent365ExporterOptions] = None,
57
+ suppress_invoke_agent_input: bool = False,
56
58
  **kwargs: Any,
57
59
  ) -> bool:
58
60
  """
@@ -67,6 +69,7 @@ class TelemetryManager:
67
69
  Use exporter_options instead.
68
70
  :param exporter_options: Agent365ExporterOptions instance for configuring the exporter.
69
71
  If provided, exporter_options takes precedence. If exporter_options is None, the token_resolver and cluster_category parameters are used as fallback/legacy support to construct a default Agent365ExporterOptions instance.
72
+ :param suppress_invoke_agent_input: If True, suppress input messages for spans that are children of InvokeAgent spans.
70
73
  :return: True if configuration succeeded, False otherwise.
71
74
  """
72
75
  try:
@@ -78,6 +81,7 @@ class TelemetryManager:
78
81
  token_resolver,
79
82
  cluster_category,
80
83
  exporter_options,
84
+ suppress_invoke_agent_input,
81
85
  **kwargs,
82
86
  )
83
87
  except Exception as e:
@@ -92,10 +96,18 @@ class TelemetryManager:
92
96
  token_resolver: Callable[[str, str], str | None] | None = None,
93
97
  cluster_category: str = "prod",
94
98
  exporter_options: Optional[Agent365ExporterOptions] = None,
99
+ suppress_invoke_agent_input: bool = False,
95
100
  **kwargs: Any,
96
101
  ) -> bool:
97
102
  """Internal configuration method - not thread-safe, must be called with lock."""
98
103
 
104
+ # Check if a365 observability is already configured
105
+ if self._tracer_provider is not None:
106
+ self._logger.warning(
107
+ "a365 observability already configured. Ignoring repeated configure() call."
108
+ )
109
+ return True
110
+
99
111
  # Create resource with service information
100
112
  resource = Resource.create(
101
113
  {
@@ -104,23 +116,24 @@ class TelemetryManager:
104
116
  }
105
117
  )
106
118
 
107
- # Get existing tracer provider or create new one
108
- try:
109
- tracer_provider = trace.get_tracer_provider()
110
- # Check if it's already configured
111
- if hasattr(tracer_provider, "resource") and tracer_provider.resource:
112
- # Already configured, just add our span processor
113
- agent_processor = SpanProcessor()
114
- tracer_provider.add_span_processor(agent_processor)
115
- self._tracer_provider = tracer_provider
116
- self._span_processors["agent"] = agent_processor
117
- return True
118
- except Exception:
119
- pass
120
-
121
- # Configure tracer provider
122
- tracer_provider = TracerProvider(resource=resource)
123
- trace.set_tracer_provider(tracer_provider)
119
+ # Check if there's an existing TracerProvider (from app's OTEL setup)
120
+ tracer_provider = trace.get_tracer_provider()
121
+
122
+ # Determine if we should use existing provider or create new one
123
+ # Check if it's a real TracerProvider with a resource (not a proxy/no-op)
124
+ if getattr(tracer_provider, "resource", None):
125
+ # Use existing provider from application's OTEL setup
126
+ self._logger.info(
127
+ "Detected existing TracerProvider with resource. "
128
+ "Adding a365 observability processors to it."
129
+ )
130
+ else:
131
+ # Create new TracerProvider with our resource
132
+ self._logger.info("Creating new TracerProvider for a365 observability.")
133
+ tracer_provider = TracerProvider(resource=resource)
134
+ trace.set_tracer_provider(tracer_provider)
135
+
136
+ # Store reference
124
137
  self._tracer_provider = tracer_provider
125
138
 
126
139
  # Use exporter_options if provided, otherwise create default options with legacy parameters
@@ -139,10 +152,11 @@ class TelemetryManager:
139
152
  }
140
153
 
141
154
  if is_agent365_exporter_enabled() and exporter_options.token_resolver is not None:
142
- exporter = Agent365Exporter(
155
+ exporter = _Agent365Exporter(
143
156
  token_resolver=exporter_options.token_resolver,
144
157
  cluster_category=exporter_options.cluster_category,
145
158
  use_s2s_endpoint=exporter_options.use_s2s_endpoint,
159
+ suppress_invoke_agent_input=suppress_invoke_agent_input,
146
160
  )
147
161
  else:
148
162
  exporter = ConsoleSpanExporter()
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Constants for SDK OpenTelemetry implementation.
4
5
 
@@ -5,6 +5,8 @@ from .agent_details import AgentDetails
5
5
  from .constants import (
6
6
  EXECUTE_TOOL_OPERATION_NAME,
7
7
  GEN_AI_EVENT_CONTENT,
8
+ GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY,
9
+ GEN_AI_EXECUTION_SOURCE_NAME_KEY,
8
10
  GEN_AI_TOOL_ARGS_KEY,
9
11
  GEN_AI_TOOL_CALL_ID_KEY,
10
12
  GEN_AI_TOOL_DESCRIPTION_KEY,
@@ -14,6 +16,7 @@ from .constants import (
14
16
  SERVER_PORT_KEY,
15
17
  )
16
18
  from .opentelemetry_scope import OpenTelemetryScope
19
+ from .request import Request
17
20
  from .tenant_details import TenantDetails
18
21
  from .tool_call_details import ToolCallDetails
19
22
 
@@ -26,6 +29,7 @@ class ExecuteToolScope(OpenTelemetryScope):
26
29
  details: ToolCallDetails,
27
30
  agent_details: AgentDetails,
28
31
  tenant_details: TenantDetails,
32
+ request: Request | None = None,
29
33
  ) -> "ExecuteToolScope":
30
34
  """Creates and starts a new scope for tool execution tracing.
31
35
 
@@ -33,17 +37,19 @@ class ExecuteToolScope(OpenTelemetryScope):
33
37
  details: The details of the tool call
34
38
  agent_details: The details of the agent making the call
35
39
  tenant_details: The details of the tenant
40
+ request: Optional request details for additional context
36
41
 
37
42
  Returns:
38
43
  A new ExecuteToolScope instance
39
44
  """
40
- return ExecuteToolScope(details, agent_details, tenant_details)
45
+ return ExecuteToolScope(details, agent_details, tenant_details, request)
41
46
 
42
47
  def __init__(
43
48
  self,
44
49
  details: ToolCallDetails,
45
50
  agent_details: AgentDetails,
46
51
  tenant_details: TenantDetails,
52
+ request: Request | None = None,
47
53
  ):
48
54
  """Initialize the tool execution scope.
49
55
 
@@ -51,6 +57,7 @@ class ExecuteToolScope(OpenTelemetryScope):
51
57
  details: The details of the tool call
52
58
  agent_details: The details of the agent making the call
53
59
  tenant_details: The details of the tenant
60
+ request: Optional request details for additional context
54
61
  """
55
62
  super().__init__(
56
63
  kind="Internal",
@@ -79,6 +86,13 @@ class ExecuteToolScope(OpenTelemetryScope):
79
86
  if endpoint.port and endpoint.port != 443:
80
87
  self.set_tag_maybe(SERVER_PORT_KEY, endpoint.port)
81
88
 
89
+ # Set request metadata if provided
90
+ if request and request.source_metadata:
91
+ self.set_tag_maybe(GEN_AI_EXECUTION_SOURCE_NAME_KEY, request.source_metadata.name)
92
+ self.set_tag_maybe(
93
+ GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, request.source_metadata.description
94
+ )
95
+
82
96
  def record_response(self, response: str) -> None:
83
97
  """Records response information for telemetry tracking.
84
98
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Execution type enum.
4
5
 
@@ -0,0 +1,8 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+
4
+ from .agent365_exporter_options import Agent365ExporterOptions
5
+
6
+ # Agent365Exporter is not exported intentionally.
7
+ # It should only be used internally by the observability core module.
8
+ __all__ = ["Agent365ExporterOptions"]
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # pip install opentelemetry-sdk opentelemetry-api requests
4
5
 
@@ -9,7 +10,8 @@ import logging
9
10
  import threading
10
11
  import time
11
12
  from collections.abc import Callable, Sequence
12
- from typing import Any
13
+ from typing import Any, final
14
+ from urllib.parse import urlparse
13
15
 
14
16
  import requests
15
17
  from microsoft_agents_a365.runtime.power_platform_api_discovery import PowerPlatformApiDiscovery
@@ -17,7 +19,13 @@ from opentelemetry.sdk.trace import ReadableSpan
17
19
  from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
18
20
  from opentelemetry.trace import StatusCode
19
21
 
22
+ from ..constants import (
23
+ GEN_AI_INPUT_MESSAGES_KEY,
24
+ GEN_AI_OPERATION_NAME_KEY,
25
+ INVOKE_AGENT_OPERATION_NAME,
26
+ )
20
27
  from .utils import (
28
+ get_validated_domain_override,
21
29
  hex_span_id,
22
30
  hex_trace_id,
23
31
  kind_name,
@@ -36,7 +44,8 @@ DEFAULT_MAX_RETRIES = 3
36
44
  logger = logging.getLogger(__name__)
37
45
 
38
46
 
39
- class Agent365Exporter(SpanExporter):
47
+ @final
48
+ class _Agent365Exporter(SpanExporter):
40
49
  """
41
50
  Agent 365 span exporter for Agent 365:
42
51
  * Partitions spans by (tenantId, agentId)
@@ -50,6 +59,7 @@ class Agent365Exporter(SpanExporter):
50
59
  token_resolver: Callable[[str, str], str | None],
51
60
  cluster_category: str = "prod",
52
61
  use_s2s_endpoint: bool = False,
62
+ suppress_invoke_agent_input: bool = False,
53
63
  ):
54
64
  if token_resolver is None:
55
65
  raise ValueError("token_resolver must be provided.")
@@ -59,6 +69,9 @@ class Agent365Exporter(SpanExporter):
59
69
  self._token_resolver = token_resolver
60
70
  self._cluster_category = cluster_category
61
71
  self._use_s2s_endpoint = use_s2s_endpoint
72
+ self._suppress_invoke_agent_input = suppress_invoke_agent_input
73
+ # Read domain override once at initialization
74
+ self._domain_override = get_validated_domain_override()
62
75
 
63
76
  # ------------- SpanExporter API -----------------
64
77
 
@@ -85,14 +98,29 @@ class Agent365Exporter(SpanExporter):
85
98
  body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
86
99
 
87
100
  # Resolve endpoint + token
88
- discovery = PowerPlatformApiDiscovery(self._cluster_category)
89
- endpoint = discovery.get_tenant_island_cluster_endpoint(tenant_id)
101
+ if self._domain_override:
102
+ endpoint = self._domain_override
103
+ else:
104
+ discovery = PowerPlatformApiDiscovery(self._cluster_category)
105
+ endpoint = discovery.get_tenant_island_cluster_endpoint(tenant_id)
106
+
90
107
  endpoint_path = (
91
108
  f"/maven/agent365/service/agents/{agent_id}/traces"
92
109
  if self._use_s2s_endpoint
93
110
  else f"/maven/agent365/agents/{agent_id}/traces"
94
111
  )
95
- url = f"https://{endpoint}{endpoint_path}?api-version=1"
112
+
113
+ # Construct URL - if endpoint has a scheme (http:// or https://), use it as-is
114
+ # Otherwise, prepend https://
115
+ # Note: Check for "://" to distinguish between real protocols and domain:port format
116
+ # (urlparse treats "example.com:8080" as having scheme="example.com")
117
+ parsed = urlparse(endpoint)
118
+ if parsed.scheme and "://" in endpoint:
119
+ # Endpoint is a full URL, append path
120
+ url = f"{endpoint}{endpoint_path}?api-version=1"
121
+ else:
122
+ # Endpoint is just a domain (possibly with port), prepend https://
123
+ url = f"https://{endpoint}{endpoint_path}?api-version=1"
96
124
 
97
125
  # Debug: Log endpoint being used
98
126
  logger.info(
@@ -141,6 +169,8 @@ class Agent365Exporter(SpanExporter):
141
169
  def force_flush(self, timeout_millis: int = 30000) -> bool:
142
170
  return True
143
171
 
172
+ # ------------- Helper methods -------------------
173
+
144
174
  # ------------- HTTP helper ----------------------
145
175
 
146
176
  @staticmethod
@@ -257,6 +287,20 @@ class Agent365Exporter(SpanExporter):
257
287
 
258
288
  # attributes
259
289
  attrs = dict(sp.attributes or {})
290
+
291
+ # Suppress input messages if configured and current span is an InvokeAgent span
292
+ if self._suppress_invoke_agent_input:
293
+ # Check if current span is an InvokeAgent span by:
294
+ # 1. Span name starts with "invoke_agent"
295
+ # 2. Has attribute gen_ai.operation.name set to INVOKE_AGENT_OPERATION_NAME
296
+ operation_name = attrs.get(GEN_AI_OPERATION_NAME_KEY)
297
+ if (
298
+ sp.name.startswith(INVOKE_AGENT_OPERATION_NAME)
299
+ and operation_name == INVOKE_AGENT_OPERATION_NAME
300
+ ):
301
+ # Remove input messages attribute
302
+ attrs.pop(GEN_AI_INPUT_MESSAGES_KEY, None)
303
+
260
304
  # events
261
305
  events = []
262
306
  for ev in sp.events:
@@ -1,10 +1,12 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  import json
4
5
  import logging
5
6
  import os
6
7
  from collections.abc import Sequence
7
8
  from typing import Any
9
+ from urllib.parse import urlparse
8
10
 
9
11
  from opentelemetry.sdk.trace import ReadableSpan
10
12
  from opentelemetry.trace import SpanKind, StatusCode
@@ -142,6 +144,59 @@ def partition_by_identity(
142
144
  return groups
143
145
 
144
146
 
147
+ def get_validated_domain_override() -> str | None:
148
+ """
149
+ Get and validate the domain override from environment variable.
150
+
151
+ Returns:
152
+ The validated domain override, or None if not set or invalid.
153
+ """
154
+ domain_override = os.getenv("A365_OBSERVABILITY_DOMAIN_OVERRIDE", "").strip()
155
+ if not domain_override:
156
+ return None
157
+
158
+ # Validate that it's a valid URL
159
+ try:
160
+ parsed = urlparse(domain_override)
161
+
162
+ # If scheme is present and looks like a protocol (contains //)
163
+ # Note: We check for "://" because urlparse treats "example.com:8080" as having
164
+ # scheme="example.com", but this is actually a domain with port, not a protocol.
165
+ if parsed.scheme and "://" in domain_override:
166
+ # Validate it's http or https
167
+ if parsed.scheme not in ("http", "https"):
168
+ logger.warning(
169
+ f"Invalid domain override '{domain_override}': "
170
+ f"scheme must be http or https, got '{parsed.scheme}'"
171
+ )
172
+ return None
173
+ # Must have a netloc (hostname) when scheme is present
174
+ if not parsed.netloc:
175
+ logger.warning(f"Invalid domain override '{domain_override}': missing hostname")
176
+ return None
177
+ else:
178
+ # If no scheme with ://, it should be a domain with optional port (no path)
179
+ # Note: domain can contain : for port (e.g., example.com:8080)
180
+ # Reject malformed URLs like "http:8080" that look like protocols but aren't
181
+ if domain_override.startswith(("http:", "https:")) and "://" not in domain_override:
182
+ logger.warning(
183
+ f"Invalid domain override '{domain_override}': "
184
+ "malformed URL - protocol requires '://'"
185
+ )
186
+ return None
187
+ if "/" in domain_override:
188
+ logger.warning(
189
+ f"Invalid domain override '{domain_override}': "
190
+ "domain without protocol should not contain path separators (/)"
191
+ )
192
+ return None
193
+ except Exception as e:
194
+ logger.warning(f"Invalid domain override '{domain_override}': {e}")
195
+ return None
196
+
197
+ return domain_override
198
+
199
+
145
200
  def is_agent365_exporter_enabled() -> bool:
146
201
  """Check if Agent 365 exporter is enabled."""
147
202
  # Check environment variable
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  from dataclasses import dataclass
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  from enum import Enum
4
5
 
@@ -5,6 +5,8 @@ from typing import List
5
5
 
6
6
  from .agent_details import AgentDetails
7
7
  from .constants import (
8
+ GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY,
9
+ GEN_AI_EXECUTION_SOURCE_NAME_KEY,
8
10
  GEN_AI_INPUT_MESSAGES_KEY,
9
11
  GEN_AI_OPERATION_NAME_KEY,
10
12
  GEN_AI_OUTPUT_MESSAGES_KEY,
@@ -90,6 +92,13 @@ class InferenceScope(OpenTelemetryScope):
90
92
  )
91
93
  self.set_tag_maybe(GEN_AI_RESPONSE_ID_KEY, details.responseId)
92
94
 
95
+ # Set request metadata if provided
96
+ if request and request.source_metadata:
97
+ self.set_tag_maybe(GEN_AI_EXECUTION_SOURCE_NAME_KEY, request.source_metadata.name)
98
+ self.set_tag_maybe(
99
+ GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, request.source_metadata.description
100
+ )
101
+
93
102
  def record_input_messages(self, messages: List[str]) -> None:
94
103
  """Records the input messages for telemetry tracking.
95
104
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Data class for invoke agent details.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Middleware components for Microsoft Agent 365 SDK.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Per request baggage builder for OpenTelemetry context propagation.
4
5
 
@@ -31,7 +32,6 @@ from ..constants import (
31
32
  )
32
33
  from ..models.operation_source import OperationSource
33
34
  from ..utils import deprecated, validate_and_normalize_ip
34
- from .turn_context_baggage import from_turn_context
35
35
 
36
36
  logger = logging.getLogger(__name__)
37
37
 
@@ -43,14 +43,17 @@ class BaggageBuilder:
43
43
  propagated in the OpenTelemetry context.
44
44
 
45
45
  Example:
46
- >>> with BaggageBuilder() \
47
- ... .tenant_id("tenant-123") \
48
- ... .agent_id("agent-456") \
49
- ... .correlation_id("corr-789") \
50
- ... .build():
51
- ... # Baggage is set in this context
52
- ... pass
53
- >>> # Baggage is restored after exiting the context
46
+ .. code-block:: python
47
+
48
+ builder = (BaggageBuilder()
49
+ .tenant_id("tenant-123")
50
+ .agent_id("agent-456")
51
+ .correlation_id("corr-789"))
52
+
53
+ with builder.build():
54
+ # Baggage is set in this context
55
+ pass
56
+ # Baggage is restored after exiting the context
54
57
  """
55
58
 
56
59
  def __init__(self):
@@ -232,14 +235,6 @@ class BaggageBuilder:
232
235
  self._set(GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, value)
233
236
  return self
234
237
 
235
- def from_turn_context(self, turn_context: Any) -> "BaggageBuilder":
236
- """
237
- Populate baggage from a turn_context (duck-typed).
238
- Delegates to baggage_turn_context.from_turn_context.
239
- """
240
-
241
- return self.set_pairs(from_turn_context(turn_context))
242
-
243
238
  def set_pairs(self, pairs: Any) -> "BaggageBuilder":
244
239
  """
245
240
  Accept dict or iterable of (k,v).
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Base class for OpenTelemetry tracing scopes.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Request class.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Source metadata class.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Tenant details class.
4
5
  from dataclasses import dataclass
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Data class for tool call details.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  # Tool type enum.
4
5
 
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  """
4
5
  Trace Processors
@@ -1,6 +1,7 @@
1
- """Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
- Span processor for copying OpenTelemetry baggage entries onto spans.
4
+ """Span processor for copying OpenTelemetry baggage entries onto spans.
4
5
 
5
6
  This implementation assumes `opentelemetry.baggage.get_all` is available with the
6
7
  signature `get_all(context: Context | None) -> Mapping[str, object]`.
@@ -1,4 +1,5 @@
1
- # Copyright (c) Microsoft. All rights reserved.
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
2
3
 
3
4
  from .. import constants as consts
4
5
 
@@ -23,6 +24,7 @@ COMMON_ATTRIBUTES = [
23
24
  consts.SESSION_ID_KEY,
24
25
  consts.SESSION_DESCRIPTION_KEY,
25
26
  consts.HIRING_MANAGER_ID_KEY,
27
+ consts.GEN_AI_CALLER_CLIENT_IP_KEY, # gen_ai.caller.client.ip
26
28
  # Execution context
27
29
  consts.GEN_AI_EXECUTION_SOURCE_NAME_KEY, # gen_ai.channel.name
28
30
  consts.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, # gen_ai.channel.link
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microsoft-agents-a365-observability-core
3
- Version: 0.2.0.dev5
3
+ Version: 0.2.1.dev0
4
4
  Summary: Telemetry, tracing, and monitoring components for AI agents
5
5
  Author-email: Microsoft <support@microsoft.com>
6
6
  License: MIT
@@ -0,0 +1,35 @@
1
+ microsoft_agents_a365/observability/core/__init__.py,sha256=r613vGLepo9ttTRmq3_EQz3hfDd4Ukp3v8AVS-6Uf_o,1762
2
+ microsoft_agents_a365/observability/core/agent_details.py,sha256=7x4tqcocig1hz4T6eCRZy7fSF2gOCpM0pvE6Q3Txww0,1210
3
+ microsoft_agents_a365/observability/core/config.py,sha256=YhnQaJr-SVNJLGM_HvYvaAfwXn-h9KinbNNZeXG9w90,11751
4
+ microsoft_agents_a365/observability/core/constants.py,sha256=suvJc4JgB9o3eeDVyiJDk0kjFVkjeDrl6u43XsvPWBc,4747
5
+ microsoft_agents_a365/observability/core/execute_tool_scope.py,sha256=XgramOBLhpilR5VjFsigdDCqYkDkG0D6CIrwN5xgeJw,3654
6
+ microsoft_agents_a365/observability/core/execution_type.py,sha256=qnNGmo9-Tlb3PBTK3pen2QIAm2hlQiKl8vRuMPWHtk8,328
7
+ microsoft_agents_a365/observability/core/inference_call_details.py,sha256=VZGB7ybr3BT7YZbjRU92YCpsDyvoicILoWPejKiI1rM,508
8
+ microsoft_agents_a365/observability/core/inference_operation_type.py,sha256=6FKl9lxSBgPptwD7TZ4znrd8t6R9nD1rq1QPACfVsqY,298
9
+ microsoft_agents_a365/observability/core/inference_scope.py,sha256=fca5AdPw5PvHSNkLgUpJGsZWxG5c-BDUFLnRKjpAEuo,5382
10
+ microsoft_agents_a365/observability/core/invoke_agent_details.py,sha256=ED0pjtlQAl-wCO9vJqXv-xghCwVFn_c8FCSz_vpEa_s,414
11
+ microsoft_agents_a365/observability/core/invoke_agent_scope.py,sha256=A2syvvT9lUE1x7M1Ns7DuXY0J4STMiOBe7kGmPpyLmQ,6917
12
+ microsoft_agents_a365/observability/core/opentelemetry_scope.py,sha256=J2vetCZnVRgVgc7wlKzmL5FbGf5LdbWaf1ryxt8rBC0,9759
13
+ microsoft_agents_a365/observability/core/request.py,sha256=FVO8cjNSAp_5NnOmz4XuXkKJNl5NOYBHZAIDRo6mjcc,424
14
+ microsoft_agents_a365/observability/core/source_metadata.py,sha256=BgAyyA17sZtHSDH1aPQAm1BEtQ3G5zpbKZinjew_leo,346
15
+ microsoft_agents_a365/observability/core/tenant_details.py,sha256=VoJIUeEIIHRvr2trzRz5BE8QWkLTt6Z4NVVI2MbyBeQ,243
16
+ microsoft_agents_a365/observability/core/tool_call_details.py,sha256=D7wrDYjr2-65Ddx2LwK2P5bSghqq7ehdhUUToUiW-SI,480
17
+ microsoft_agents_a365/observability/core/tool_type.py,sha256=Jg021SlX-Vwz2WdHffcgJFm9Ys3zr1LRJNf4KYaZ6S4,296
18
+ microsoft_agents_a365/observability/core/utils.py,sha256=fnZBCEsD-1FlxpJ5hcbwovrEK4baeSKOyKJADSD3n3Q,6063
19
+ microsoft_agents_a365/observability/core/exporters/__init__.py,sha256=UEaMJYkbTViVAUVQTFSf1BUvni1pNTcDwriKzOzvGFU,296
20
+ microsoft_agents_a365/observability/core/exporters/agent365_exporter.py,sha256=Q8ylOrgBF2gNB_KAn8QdtJu8E3aiC6kUUomCgNLqgb4,13490
21
+ microsoft_agents_a365/observability/core/exporters/agent365_exporter_options.py,sha256=f-p11ZQfxtDIiK-kVPDfebBgT83onxdE29IQryYoAPk,1648
22
+ microsoft_agents_a365/observability/core/exporters/utils.py,sha256=tICuOuWfgUKL1dHoGuyG5_xNOrREPTXFE-RJZehpVT4,6989
23
+ microsoft_agents_a365/observability/core/middleware/__init__.py,sha256=KNH2QjJBIGhn1xf_r3HdOVYUw9ngKEcy0HV9eHuTaqk,202
24
+ microsoft_agents_a365/observability/core/middleware/baggage_builder.py,sha256=KaTb8n0D8dbjS-qph3o160VUEn4kYy8YdaFvGMd5Vck,10505
25
+ microsoft_agents_a365/observability/core/models/__init__.py,sha256=aCOr6sEsQpv9z4cJgWFA4qOs4xJqclqYYnxOVcxiK2Q,75
26
+ microsoft_agents_a365/observability/core/models/agent_type.py,sha256=ZazwwMAQRrYzzN3Ytz69F6thV4R6nemA6JrK-70fyt0,560
27
+ microsoft_agents_a365/observability/core/models/caller_details.py,sha256=8oaRKeGNteZq_RAQShhfUBs0iO-Sr9yjfk13Mv-xSjA,674
28
+ microsoft_agents_a365/observability/core/models/operation_source.py,sha256=HJp-SNR-lNSPIgoLlF6DMMlijtu4ZGhnqSyu58lIgnk,448
29
+ microsoft_agents_a365/observability/core/trace_processor/__init__.py,sha256=0QDkZgvgGekJVcZXjubSqipYhCGMZaAAxLSanyR76pg,219
30
+ microsoft_agents_a365/observability/core/trace_processor/span_processor.py,sha256=O_DLuLR-6sV9VmkYfMzUF3s6n1OLrtK5qkD6csen73g,2980
31
+ microsoft_agents_a365/observability/core/trace_processor/util.py,sha256=h5oOFAGIY6x9WtgfErPetblSkWZsQZjOgbwoR_tL-7k,2364
32
+ microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info/METADATA,sha256=mCXs-XGApLHUEkD7f17jKeJSHwXC4Um4U6eeV5Hnbyw,3871
33
+ microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
34
+ microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info/top_level.txt,sha256=m90AvzRnjbL6fpi20mzOj6HUVkR2LWuf2JuXm4LL9LU,27
35
+ microsoft_agents_a365_observability_core-0.2.1.dev0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,192 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from typing import Any, Iterator, Mapping
5
-
6
- from ..constants import (
7
- GEN_AI_AGENT_AUID_KEY,
8
- GEN_AI_AGENT_DESCRIPTION_KEY,
9
- GEN_AI_AGENT_ID_KEY,
10
- GEN_AI_AGENT_NAME_KEY,
11
- GEN_AI_AGENT_UPN_KEY,
12
- GEN_AI_CALLER_ID_KEY,
13
- GEN_AI_CALLER_NAME_KEY,
14
- GEN_AI_CALLER_TENANT_ID_KEY,
15
- GEN_AI_CALLER_UPN_KEY,
16
- GEN_AI_CALLER_USER_ID_KEY,
17
- GEN_AI_CONVERSATION_ID_KEY,
18
- GEN_AI_CONVERSATION_ITEM_LINK_KEY,
19
- GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY,
20
- GEN_AI_EXECUTION_SOURCE_NAME_KEY,
21
- GEN_AI_EXECUTION_TYPE_KEY,
22
- TENANT_ID_KEY,
23
- )
24
- from ..execution_type import ExecutionType
25
-
26
- AGENT_ROLE = "agenticUser"
27
- CHANNEL_ID_AGENTS = "agents"
28
-
29
-
30
- def _safe_get(obj: Any, *names: str) -> Any:
31
- """Attempt multiple attribute/dict keys; return first non-None."""
32
- for n in names:
33
- if obj is None:
34
- continue
35
- # dict-like
36
- if isinstance(obj, Mapping) and n in obj:
37
- return obj[n]
38
- # attribute-like (support both camelCase and snake_case lookups)
39
- if hasattr(obj, n):
40
- return getattr(obj, n)
41
- return None
42
-
43
-
44
- def _extract_channel_data(activity: Any) -> Mapping[str, Any] | None:
45
- cd = _safe_get(activity, "channel_data")
46
- if cd is None:
47
- return None
48
- if isinstance(cd, Mapping):
49
- return cd
50
- if isinstance(cd, str):
51
- try:
52
- return json.loads(cd)
53
- except Exception:
54
- return None
55
- return None
56
-
57
-
58
- def _iter_caller_pairs(activity: Any) -> Iterator[tuple[str, Any]]:
59
- frm = _safe_get(activity, "from")
60
- if not frm:
61
- return
62
- yield GEN_AI_CALLER_ID_KEY, _safe_get(frm, "id")
63
- name = _safe_get(frm, "name")
64
- yield GEN_AI_CALLER_NAME_KEY, name
65
- # Reuse 'name' as UPN if no separate field
66
- upn = _safe_get(frm, "upn") or name
67
- yield GEN_AI_CALLER_UPN_KEY, upn
68
- user_id = _safe_get(frm, "agentic_user_id", "aad_object_id")
69
- yield GEN_AI_CALLER_USER_ID_KEY, user_id
70
- tenant_id = _safe_get(frm, "tenant_id")
71
- yield GEN_AI_CALLER_TENANT_ID_KEY, tenant_id
72
-
73
-
74
- def _is_agentic(entity: Any) -> bool:
75
- return bool(
76
- _safe_get(
77
- entity,
78
- "agentic_user_id",
79
- )
80
- or (
81
- (role := _safe_get(entity, "role", "Role"))
82
- and isinstance(role, str)
83
- and role.lower() == AGENT_ROLE.lower()
84
- )
85
- )
86
-
87
-
88
- def _iter_execution_type_pair(activity: Any) -> Iterator[tuple[str, Any]]:
89
- frm = _safe_get(activity, "from")
90
- rec = _safe_get(activity, "recipient")
91
- is_agentic_caller = _is_agentic(frm)
92
- is_agentic_recipient = _is_agentic(rec)
93
- exec_type = (
94
- ExecutionType.AGENT_TO_AGENT.value
95
- if (is_agentic_caller and is_agentic_recipient)
96
- else ExecutionType.HUMAN_TO_AGENT.value
97
- )
98
- yield GEN_AI_EXECUTION_TYPE_KEY, exec_type
99
-
100
-
101
- def _iter_target_agent_pairs(activity: Any) -> Iterator[tuple[str, Any]]:
102
- rec = _safe_get(activity, "recipient")
103
- if not rec:
104
- return
105
- yield GEN_AI_AGENT_ID_KEY, _safe_get(rec, "agentic_app_id")
106
- yield GEN_AI_AGENT_NAME_KEY, _safe_get(rec, "name")
107
- auid = _safe_get(rec, "agentic_user_id", "aad_object_id")
108
- yield GEN_AI_AGENT_AUID_KEY, auid
109
- yield GEN_AI_AGENT_UPN_KEY, _safe_get(rec, "upn", "name")
110
- yield (
111
- GEN_AI_AGENT_DESCRIPTION_KEY,
112
- _safe_get(rec, "role"),
113
- )
114
-
115
-
116
- def _iter_tenant_id_pair(activity: Any) -> Iterator[tuple[str, Any]]:
117
- rec = _safe_get(activity, "recipient")
118
- tenant_id = _safe_get(rec, "tenant_id")
119
- if not tenant_id:
120
- cd_dict = _extract_channel_data(activity)
121
- # channelData.tenant.id
122
- try:
123
- tenant_id = (
124
- cd_dict
125
- and isinstance(cd_dict.get("tenant"), Mapping)
126
- and cd_dict["tenant"].get("id")
127
- )
128
- except Exception:
129
- tenant_id = None
130
- yield TENANT_ID_KEY, tenant_id
131
-
132
-
133
- def _iter_source_metadata_pairs(activity: Any) -> Iterator[tuple[str, Any]]:
134
- """
135
- Generate source metadata pairs from activity, handling both string and ChannelId object cases.
136
-
137
- :param activity: The activity object (Activity instance or dict)
138
- :return: Iterator of (key, value) tuples for source metadata
139
- """
140
- # Handle channel_id (can be string or ChannelId object)
141
- channel_id = _safe_get(activity, "channel_id")
142
-
143
- # Extract channel name from either string or ChannelId object
144
- channel_name = None
145
- sub_channel = None
146
-
147
- if channel_id is not None:
148
- if isinstance(channel_id, str):
149
- # Direct string value
150
- channel_name = channel_id
151
- elif hasattr(channel_id, "channel"):
152
- # ChannelId object
153
- channel_name = channel_id.channel
154
- sub_channel = getattr(channel_id, "sub_channel", None)
155
- elif isinstance(channel_id, dict):
156
- # Serialized ChannelId as dict
157
- channel_name = channel_id.get("channel")
158
- sub_channel = channel_id.get("sub_channel")
159
-
160
- # Yield channel name as source name
161
- yield GEN_AI_EXECUTION_SOURCE_NAME_KEY, channel_name
162
- yield GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, sub_channel
163
-
164
-
165
- def _iter_conversation_pairs(activity: Any) -> Iterator[tuple[str, Any]]:
166
- conv = _safe_get(activity, "conversation")
167
- conversation_id = _safe_get(conv, "id")
168
-
169
- item_link = _safe_get(activity, "service_url")
170
-
171
- yield GEN_AI_CONVERSATION_ID_KEY, conversation_id
172
- yield GEN_AI_CONVERSATION_ITEM_LINK_KEY, item_link
173
-
174
-
175
- def _iter_all_pairs(turn_context: Any) -> Iterator[tuple[str, Any]]:
176
- activity = _safe_get(
177
- turn_context,
178
- "activity",
179
- )
180
- if not activity:
181
- return
182
- yield from _iter_caller_pairs(activity)
183
- yield from _iter_execution_type_pair(activity)
184
- yield from _iter_target_agent_pairs(activity)
185
- yield from _iter_tenant_id_pair(activity)
186
- yield from _iter_source_metadata_pairs(activity)
187
- yield from _iter_conversation_pairs(activity)
188
-
189
-
190
- def from_turn_context(turn_context: Any) -> dict:
191
- """Populate builder with baggage values extracted from a turn context."""
192
- return dict(_iter_all_pairs(turn_context))
@@ -1,35 +0,0 @@
1
- microsoft_agents_a365/observability/core/__init__.py,sha256=1-Jmokc2cQv7p_RB7W22ZEdqQ0Doq8yDENx_Yews2p8,1737
2
- microsoft_agents_a365/observability/core/agent_details.py,sha256=7x4tqcocig1hz4T6eCRZy7fSF2gOCpM0pvE6Q3Txww0,1210
3
- microsoft_agents_a365/observability/core/config.py,sha256=BK1Yg2ykt5yYUBmA-z_wKy2H4k8UB6InF4C5Xh8ZM-g,10996
4
- microsoft_agents_a365/observability/core/constants.py,sha256=sypi1CXrTX5lX-19qQTq6VL6CZ691w5-gFVh5W6OpbY,4722
5
- microsoft_agents_a365/observability/core/execute_tool_scope.py,sha256=RcibM_Q-lEhSOpAoRioDao-HiC72W741-SCbcPDWqyI,2989
6
- microsoft_agents_a365/observability/core/execution_type.py,sha256=Qsf-7_7DzZnRQZ5NHYU31ggfxAjPwneNnda1hOodmG0,303
7
- microsoft_agents_a365/observability/core/inference_call_details.py,sha256=V1-KQPNq0V36J91ptX96UNRcOW6cy-AV5eIlwbzsrSg,483
8
- microsoft_agents_a365/observability/core/inference_operation_type.py,sha256=ZLdDdYC0V_0Sff_aTSaiIRVB4a9wEduS7EXpYlme6_M,273
9
- microsoft_agents_a365/observability/core/inference_scope.py,sha256=87r367uQ4qVp8NpR0na-uQScRR5ID1FlP6c3cmIxvMc,4973
10
- microsoft_agents_a365/observability/core/invoke_agent_details.py,sha256=PEwkJq-nUz8sxLsbz44hIydGHiO2tHj-sVBkMpZXC1A,389
11
- microsoft_agents_a365/observability/core/invoke_agent_scope.py,sha256=A2syvvT9lUE1x7M1Ns7DuXY0J4STMiOBe7kGmPpyLmQ,6917
12
- microsoft_agents_a365/observability/core/opentelemetry_scope.py,sha256=I8WQoQkCygC7jZRrP2aHsJScGqQKDVktLlRGxApfiZo,9734
13
- microsoft_agents_a365/observability/core/request.py,sha256=x9kRlUbbaK0btsJ8Ym-Ctp5jgsiy54b3eMPst7Olirk,399
14
- microsoft_agents_a365/observability/core/source_metadata.py,sha256=ijMIiJGvfepDnBqSuZbGsjvrTivz3f_Ub1azyZsCeMA,321
15
- microsoft_agents_a365/observability/core/tenant_details.py,sha256=eC5S9Zq5sJrpGFWJLKBXVlj-OipysPSoLKSl-8I5YY0,218
16
- microsoft_agents_a365/observability/core/tool_call_details.py,sha256=sPDW5yvey9_itpKxoo76pwoncOZyhONt9fy3cDdSYyY,455
17
- microsoft_agents_a365/observability/core/tool_type.py,sha256=O9snmopwdhBjK5eqwyQU3aSdLZzX88c1UMi7oW7lFHg,271
18
- microsoft_agents_a365/observability/core/utils.py,sha256=fnZBCEsD-1FlxpJ5hcbwovrEK4baeSKOyKJADSD3n3Q,6063
19
- microsoft_agents_a365/observability/core/exporters/agent365_exporter.py,sha256=lhicYBnuoDL9RrvGOADEefKV8JCoJd9ChcFn5XS8YjM,11488
20
- microsoft_agents_a365/observability/core/exporters/agent365_exporter_options.py,sha256=f-p11ZQfxtDIiK-kVPDfebBgT83onxdE29IQryYoAPk,1648
21
- microsoft_agents_a365/observability/core/exporters/utils.py,sha256=VHhZOELtZtsNEFYcCA-rb7JNX9_aDcJ9XC6OhVIBjl8,4646
22
- microsoft_agents_a365/observability/core/middleware/__init__.py,sha256=v_vLyv0BQOW9pAvuUeL6Q0ZQ3Ji4MdYYcFDfP7CqvMk,177
23
- microsoft_agents_a365/observability/core/middleware/baggage_builder.py,sha256=F1HcLKEA4-h1tjfp0AgXMqIsEn58waP6nvyChvo-cAI,10752
24
- microsoft_agents_a365/observability/core/middleware/turn_context_baggage.py,sha256=teDtlB38zKKdTynYaV9egI3G8wShgCw4KSPxzukSrmQ,6326
25
- microsoft_agents_a365/observability/core/models/__init__.py,sha256=aCOr6sEsQpv9z4cJgWFA4qOs4xJqclqYYnxOVcxiK2Q,75
26
- microsoft_agents_a365/observability/core/models/agent_type.py,sha256=ZazwwMAQRrYzzN3Ytz69F6thV4R6nemA6JrK-70fyt0,560
27
- microsoft_agents_a365/observability/core/models/caller_details.py,sha256=8oaRKeGNteZq_RAQShhfUBs0iO-Sr9yjfk13Mv-xSjA,674
28
- microsoft_agents_a365/observability/core/models/operation_source.py,sha256=HJp-SNR-lNSPIgoLlF6DMMlijtu4ZGhnqSyu58lIgnk,448
29
- microsoft_agents_a365/observability/core/trace_processor/__init__.py,sha256=GML9CA7ssJPngxpGFPdVlp-0NmhgS4Ke9IGW5vm5Gys,194
30
- microsoft_agents_a365/observability/core/trace_processor/span_processor.py,sha256=4gEvm8gcf7_A-Fty-InBc2wJG80WCvn8Sh7GKBuFYzU,2953
31
- microsoft_agents_a365/observability/core/trace_processor/util.py,sha256=xoBZ7qbucZGYJCKgKylaUrl0tP34bcd34fgmh8sXZ_E,2270
32
- microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info/METADATA,sha256=OGU05eHdSN_0kiUd9CM2xJqE6iI9XOZqBe5mMcNln3k,3871
33
- microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
- microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info/top_level.txt,sha256=G3c2_4sy5_EM_BWO67SbK2tKj4G8XFn-QXRbh8g9Lgk,22
35
- microsoft_agents_a365_observability_core-0.2.0.dev5.dist-info/RECORD,,