Skip to content

Commit 5dfd96f

Browse files
committed
Clearer separation between OTELConfig and Configuration
Signed-off-by: Teo <[email protected]>
1 parent 39b8350 commit 5dfd96f

File tree

5 files changed

+74
-52
lines changed

5 files changed

+74
-52
lines changed

agentops/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import sys
33
from typing import Optional, List, Union
44

5+
from agentops.telemetry.config import OTELConfig
6+
57
from .client import Client
68
from .event import Event, ActionEvent, LLMEvent, ToolEvent, ErrorEvent
79
from .decorators import record_action, track_agent, record_tool, record_function
@@ -48,6 +50,7 @@ def init(
4850
auto_start_session: Optional[bool] = None,
4951
inherited_session_id: Optional[str] = None,
5052
skip_auto_end_session: Optional[bool] = None,
53+
telemetry: Optional[OTELConfig] = None, # OTEL configuration
5154
) -> Union[Session, None]:
5255
"""
5356
Initializes the AgentOps singleton pattern.
@@ -69,6 +72,8 @@ def init(
6972
inherited_session_id (optional, str): Init Agentops with an existing Session
7073
skip_auto_end_session (optional, bool): Don't automatically end session based on your framework's decision-making
7174
(i.e. Crew determining when tasks are complete and ending the session)
75+
exporters (List[SpanExporter], optional): Additional OpenTelemetry exporters for sending
76+
telemetry data to external systems.
7277
Attributes:
7378
"""
7479
Client().unsuppress_logs()
@@ -84,6 +89,7 @@ def init(
8489
if default_tags is None:
8590
default_tags = tags
8691

92+
# Create OTEL config if exporters provided
8793
Client().configure(
8894
api_key=api_key,
8995
parent_key=parent_key,
@@ -94,6 +100,7 @@ def init(
94100
instrument_llm_calls=instrument_llm_calls,
95101
auto_start_session=auto_start_session,
96102
skip_auto_end_session=skip_auto_end_session,
103+
otel=telemetry, # Pass OTEL config through
97104
)
98105

99106
if inherited_session_id is not None:

agentops/client.py

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def __init__(self):
4848
self._config = Configuration()
4949
self._pre_init_queue = {"agents": []}
5050
self._host_env = None # Cache host env data
51-
self._telemetry = ClientTelemetry()
51+
self.telemetry = ClientTelemetry()
5252

5353
self.configure(
5454
api_key=os.environ.get("AGENTOPS_API_KEY"),
@@ -89,37 +89,31 @@ def configure(
8989
env_data_opt_out=env_data_opt_out,
9090
)
9191

92-
def initialize(self, otel_config: Optional[OTELConfig] = None) -> Union[Session, None]:
93-
if self.is_initialized:
94-
return
92+
def initialize(self) -> Union[Session, None]:
93+
"""Initialize the client"""
94+
if not self.is_initialized:
95+
self.unsuppress_logs()
96+
if self._config.api_key is None:
97+
return logger.error(
98+
"Could not initialize AgentOps client - API Key is missing."
99+
+ "\n\t Find your API key at https://app.agentops.ai/settings/projects"
100+
)
95101

96-
self.unsuppress_logs()
97-
if self._config.api_key is None:
98-
return logger.error(
99-
"Could not initialize AgentOps client - API Key is missing."
100-
+ "\n\t Find your API key at https://app.agentops.ai/settings/projects"
101-
)
102+
self._handle_unclean_exits()
103+
self._initialized = True
102104

103-
self._handle_unclean_exits()
104-
self._initialized = True
105+
if self._config.instrument_llm_calls:
106+
self._llm_tracker = LlmTracker(self)
107+
self._llm_tracker.override_api()
105108

106-
if self._config.instrument_llm_calls:
107-
self._llm_tracker = LlmTracker(self)
108-
self._llm_tracker.override_api()
109+
# Initialize telemetry with configuration
110+
self.telemetry.initialize(self._config.otel)
109111

110-
session = None
111-
if self._config.auto_start_session:
112-
session = self.start_session()
112+
session = None
113+
if self._config.auto_start_session:
114+
session = self.start_session()
113115

114-
if session:
115-
for agent_args in self._pre_init_queue["agents"]:
116-
session.create_agent(name=agent_args["name"], agent_id=agent_args["agent_id"])
117-
self._pre_init_queue["agents"] = []
118-
119-
# Initialize telemetry
120-
self._telemetry.initialize(self._config, otel_config)
121-
122-
return session
116+
return session
123117

124118
def _initialize_autogen_logger(self) -> None:
125119
try:
@@ -236,7 +230,7 @@ def start_session(
236230
session_tags.update(tags)
237231

238232
session = Session(
239-
client=self._telemetry,
233+
client=self.telemetry,
240234
session_id=session_id,
241235
tags=list(session_tags),
242236
host_env=self.host_env,

agentops/config.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from uuid import UUID
33

44
from .log_config import logger
5+
from .telemetry.config import OTELConfig
56

67

78
class Configuration:
@@ -16,6 +17,7 @@ def __init__(self):
1617
self.auto_start_session: bool = True
1718
self.skip_auto_end_session: bool = False
1819
self.env_data_opt_out: bool = False
20+
self.otel: OTELConfig = OTELConfig() # Default OTEL configuration
1921

2022
def configure(
2123
self,
@@ -30,6 +32,7 @@ def configure(
3032
auto_start_session: Optional[bool] = None,
3133
skip_auto_end_session: Optional[bool] = None,
3234
env_data_opt_out: Optional[bool] = None,
35+
otel: Optional[OTELConfig] = None, # New parameter
3336
):
3437
if api_key is not None:
3538
try:
@@ -72,3 +75,7 @@ def configure(
7275

7376
if env_data_opt_out is not None:
7477
self.env_data_opt_out = env_data_opt_out
78+
79+
# OTEL configuration
80+
if otel is not None:
81+
self.otel = otel

agentops/session.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,11 @@ def __init__(
195195

196196
# Get session-specific tracer from client telemetry
197197
from agentops.client import Client
198-
self._telemetry_client = client or Client()._telemetry
198+
self._telemetry_client = client or Client().telemetry
199199

200200
# Get tracer from client
201201
self._otel_tracer = self._telemetry_client.get_session_tracer(
202202
session_id=self.session_id,
203-
config=self.config,
204203
jwt=self.jwt or ""
205204
)
206205

agentops/telemetry/client.py

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from typing import TYPE_CHECKING, Dict, Optional, Union
22
from uuid import UUID
3+
import os
34

45
from opentelemetry.sdk.trace import TracerProvider
5-
from opentelemetry.sdk.trace.export import BatchSpanProcessor
6+
from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter
67

78
from agentops.config import Configuration
89
from agentops.log_config import logger
@@ -23,40 +24,54 @@ def __init__(self):
2324
self._otel_manager: Optional[OTELManager] = None
2425
self._tracer_provider: Optional[TracerProvider] = None
2526
self._session_exporters: Dict[UUID, ExportManager] = {}
26-
self._otel_config: Optional[OTELConfig] = None
27+
self.config: Optional[OTELConfig] = None
2728

28-
def initialize(self, config: Configuration, otel_config: Optional[OTELConfig] = None) -> None:
29+
def initialize(self, config: Configuration) -> None:
2930
"""Initialize telemetry components"""
30-
# Create OTEL config from Configuration if needed
31-
if otel_config is None:
32-
logger.warning("OTEL config is not provided, using default EMPTY config")
33-
otel_config = OTELConfig()
34-
31+
# Check for environment variables if no exporters configured
32+
if not config.otel.additional_exporters:
33+
endpoint = os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
34+
service_name = os.environ.get("OTEL_SERVICE_NAME")
35+
36+
if service_name and not config.otel.resource_attributes:
37+
config.otel.resource_attributes = {"service.name": service_name}
38+
39+
if endpoint:
40+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
41+
config.otel.additional_exporters = [OTLPSpanExporter(endpoint=endpoint)]
42+
logger.info("Using OTEL configuration from environment variables")
43+
44+
# Validate exporters
45+
if config.otel.additional_exporters:
46+
for exporter in config.otel.additional_exporters:
47+
if not isinstance(exporter, SpanExporter):
48+
raise ValueError(f"Invalid exporter type: {type(exporter)}. Must be a SpanExporter")
49+
3550
# Create the OTEL manager instance
3651
self._otel_manager = OTELManager(
37-
config=otel_config,
38-
exporters=otel_config.additional_exporters,
39-
resource_attributes=otel_config.resource_attributes,
40-
sampler=otel_config.sampler
52+
config=config.otel,
53+
exporters=config.otel.additional_exporters,
54+
resource_attributes=config.otel.resource_attributes,
55+
sampler=config.otel.sampler
4156
)
42-
self._otel_config = otel_config
57+
self.config = config
4358

4459
# Initialize the tracer provider with global service info
4560
self._tracer_provider = self._otel_manager.initialize(
4661
service_name="agentops",
47-
session_id="global" # Use a global session ID for client-level telemetry
62+
session_id="global"
4863
)
4964

50-
def get_session_tracer(self, session_id: UUID, config, jwt: str):
65+
def get_session_tracer(self, session_id: UUID, jwt: str):
5166
"""Get or create a tracer for a specific session"""
5267
# Create session-specific exporter
5368
exporter = ExportManager(
5469
session_id=session_id,
55-
endpoint=config.endpoint,
70+
endpoint=self.config.endpoint,
5671
jwt=jwt,
57-
api_key=config.api_key,
58-
retry_config=self._otel_config.retry_config if self._otel_config else None,
59-
custom_formatters=self._otel_config.custom_formatters if self._otel_config else None,
72+
api_key=self.config.api_key,
73+
retry_config=self.config.retry_config if self.config else None,
74+
custom_formatters=self.config.custom_formatters if self.config else None,
6075
)
6176

6277
# Store exporter reference
@@ -65,11 +80,11 @@ def get_session_tracer(self, session_id: UUID, config, jwt: str):
6580
# Add both batch and in-flight processors
6681
batch_processor = BatchSpanProcessor(
6782
exporter,
68-
max_queue_size=config.max_queue_size,
83+
max_queue_size=self.config.max_queue_size,
6984
schedule_delay_millis=config.max_wait_time,
7085
max_export_batch_size=min(
71-
max(config.max_queue_size // 20, 1),
72-
min(config.max_queue_size, 32),
86+
max(self.config.max_queue_size // 20, 1),
87+
min(self.config.max_queue_size, 32),
7388
),
7489
export_timeout_millis=20000,
7590
)

0 commit comments

Comments
 (0)