From dce37d29cb6c2fa9fe408b89e907d19994d68716 Mon Sep 17 00:00:00 2001 From: adityamehra Date: Thu, 16 Jul 2026 13:41:06 -0700 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20rename=20GalileoSpan=20?= =?UTF-8?q?=E2=86=92=20SplunkAOSpan,=20galileo=5Fspan=20=E2=86=92=20splunk?= =?UTF-8?q?=5Fao=5Fspan,=20galileo-otel=20=E2=86=92=20splunk-ao-otel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove remaining Galileo branding from the OTel integration layer: - Import alias: `Span as GalileoSpan` → `Span as SplunkAOSpan` - Parameter/variable names: `galileo_span` → `splunk_ao_span` across otel.py, handler.py, and utils - gen_ai.system attribute value: `"galileo-otel"` → `"splunk-ao-otel"` - Test class/method names updated to match - Examples updated: start_galileo_span → start_splunk_ao_span, galileo_span_processor → splunk_ao_span_processor Co-authored-by: Cursor --- examples/agent/google-adk/my_agent/agent.py | 4 +- .../agent/langgraph-open-telemetry/main.py | 4 +- .../python-service/app.py | 4 +- .../handlers/openai_agents/handler.py | 4 +- src/splunk_ao/otel.py | 58 +++++++++---------- src/splunk_ao/utils/openai_agents.py | 4 +- tests/test_openai_agents_utils.py | 4 +- tests/test_otel.py | 8 +-- 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/examples/agent/google-adk/my_agent/agent.py b/examples/agent/google-adk/my_agent/agent.py index 438418cd..414cb38e 100644 --- a/examples/agent/google-adk/my_agent/agent.py +++ b/examples/agent/google-adk/my_agent/agent.py @@ -10,8 +10,8 @@ # Create tracer provider and register Splunk AO span processor tracer_provider = trace_sdk.TracerProvider() -galileo_span_processor = otel.SplunkAOSpanProcessor() -tracer_provider.add_span_processor(galileo_span_processor) +splunk_ao_span_processor = otel.SplunkAOSpanProcessor() +tracer_provider.add_span_processor(splunk_ao_span_processor) # Instrument Google ADK with OpenInference (this captures inputs/outputs) GoogleADKInstrumentor().instrument(tracer_provider=tracer_provider) diff --git a/examples/agent/langgraph-open-telemetry/main.py b/examples/agent/langgraph-open-telemetry/main.py index 6d006482..f5ccdfb3 100644 --- a/examples/agent/langgraph-open-telemetry/main.py +++ b/examples/agent/langgraph-open-telemetry/main.py @@ -26,7 +26,7 @@ client = openai.OpenAI(api_key=openai_api_key) print("✓ OpenAI client configured") -galileo_span_processor = otel.SplunkAOSpanProcessor() +splunk_ao_span_processor = otel.SplunkAOSpanProcessor() resource = Resource.create( @@ -40,7 +40,7 @@ # Add a span processor that sends traces to Splunk AO -otel.add_splunk_ao_span_processor(tracer_provider, galileo_span_processor) +otel.add_splunk_ao_span_processor(tracer_provider, splunk_ao_span_processor) # OPTIONAL: Console output disabled to reduce noise in Splunk AO # Uncomment the next 3 lines if you want local console debugging: diff --git a/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py b/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py index bad8a4ba..8e51fcff 100644 --- a/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py +++ b/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py @@ -6,7 +6,7 @@ import chromadb.utils.embedding_functions as ef import openai from fastapi import FastAPI -from splunk_ao.otel import start_galileo_span +from splunk_ao.otel import start_splunk_ao_span from splunk_ao_core.schemas.logging.span import RetrieverSpan from splunk_ao_core.schemas.shared.document import Document from langgraph.graph import END, START, StateGraph @@ -110,7 +110,7 @@ def retrieve_documents(state: GraphState) -> GraphState: query = state["question"] retriever_span = RetrieverSpan(name="chromadb_search", input=query) - with start_galileo_span(retriever_span) as span: + with start_splunk_ao_span(retriever_span) as span: try: collection = chroma.get_collection(CHROMA_COLLECTION, embedding_function=embedding_fn) results = collection.query(query_texts=[query], n_results=3) diff --git a/src/splunk_ao/handlers/openai_agents/handler.py b/src/splunk_ao/handlers/openai_agents/handler.py index e34a8032..e82b25ea 100644 --- a/src/splunk_ao/handlers/openai_agents/handler.py +++ b/src/splunk_ao/handlers/openai_agents/handler.py @@ -7,7 +7,7 @@ from agents.tracing import ResponseSpanData, get_current_span, get_trace_provider from galileo_core.schemas.logging.span import LlmMetrics, LlmSpan -from galileo_core.schemas.logging.span import Span as GalileoSpan +from galileo_core.schemas.logging.span import Span as SplunkAOSpan from splunk_ao import SplunkAOLogger, splunk_ao_context from splunk_ao.schema.handlers import Node from splunk_ao.utils import _get_timestamp @@ -492,7 +492,7 @@ def _extract_tool_output(self, item_dict: dict[str, Any], item_type: str) -> str return serialize_to_str(item_dict.get("output") or item_dict.get("results")) @staticmethod - def add_splunk_ao_custom_span(span: GalileoSpan) -> Span[SplunkAOCustomSpan]: + def add_splunk_ao_custom_span(span: SplunkAOSpan) -> Span[SplunkAOCustomSpan]: """Add a Galileo custom span to the trace.""" trace_provider = get_trace_provider() current_span = get_current_span() diff --git a/src/splunk_ao/otel.py b/src/splunk_ao/otel.py index f60f32ee..a462873b 100644 --- a/src/splunk_ao/otel.py +++ b/src/splunk_ao/otel.py @@ -10,7 +10,7 @@ from requests import Session from galileo_core.schemas.logging.span import RetrieverSpan, ToolSpan, WorkflowSpan -from galileo_core.schemas.logging.span import Span as GalileoSpan +from galileo_core.schemas.logging.span import Span as SplunkAOSpan from splunk_ao.config import SplunkAOConfig from splunk_ao.decorator import ( _dataset_input_context, @@ -318,32 +318,32 @@ def add_splunk_ao_span_processor(tracer_provider: TracerProvider, processor: Spl _TRACE_PROVIDER_CONTEXT_VAR.set(tracer_provider) -def _set_retriever_span_attributes(span: trace.Span, galileo_span: RetrieverSpan) -> None: +def _set_retriever_span_attributes(span: trace.Span, splunk_ao_span: RetrieverSpan) -> None: span.set_attribute("db.operation", "search") - span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "user", "content": galileo_span.input}])) + span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "user", "content": splunk_ao_span.input}])) span.set_attribute( "gen_ai.output.messages", json.dumps( [ { "role": "assistant", - "content": {"documents": document_adapter.dump_python(galileo_span.output, mode="json")}, + "content": {"documents": document_adapter.dump_python(splunk_ao_span.output, mode="json")}, } ] ), ) -def _set_tool_span_attributes(span: trace.Span, galileo_span: ToolSpan) -> None: +def _set_tool_span_attributes(span: trace.Span, splunk_ao_span: ToolSpan) -> None: span.set_attribute("gen_ai.operation.name", "execute_tool") - span.set_attribute("gen_ai.tool.name", galileo_span.name) - span.set_attribute("gen_ai.tool.call.arguments", galileo_span.input) - span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "tool", "content": galileo_span.input}])) - if galileo_span.output is not None: - span.set_attribute("gen_ai.tool.call.result", galileo_span.output) - span.set_attribute("gen_ai.output.messages", json.dumps([{"role": "tool", "content": galileo_span.output}])) - if galileo_span.tool_call_id is not None: - span.set_attribute("gen_ai.tool.call.id", galileo_span.tool_call_id) + span.set_attribute("gen_ai.tool.name", splunk_ao_span.name) + span.set_attribute("gen_ai.tool.call.arguments", splunk_ao_span.input) + span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "tool", "content": splunk_ao_span.input}])) + if splunk_ao_span.output is not None: + span.set_attribute("gen_ai.tool.call.result", splunk_ao_span.output) + span.set_attribute("gen_ai.output.messages", json.dumps([{"role": "tool", "content": splunk_ao_span.output}])) + if splunk_ao_span.tool_call_id is not None: + span.set_attribute("gen_ai.tool.call.id", splunk_ao_span.tool_call_id) def _apply_dataset_attributes( @@ -358,15 +358,15 @@ def _apply_dataset_attributes( span.set_attribute("splunk_ao.dataset.metadata", json.dumps(dataset_metadata)) -def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) -> None: +def _set_workflow_span_attributes(span: trace.Span, splunk_ao_span: WorkflowSpan) -> None: """Set OpenTelemetry attributes for WorkflowSpan.""" # Handle input - Union[str, Sequence[Message]] - if isinstance(galileo_span.input, str): - input_messages = [{"role": "user", "content": galileo_span.input}] + if isinstance(splunk_ao_span.input, str): + input_messages = [{"role": "user", "content": splunk_ao_span.input}] else: # Sequence[Message] - serialize each message input_messages = [] - for msg in list(galileo_span.input): + for msg in list(splunk_ao_span.input): if hasattr(msg, "model_dump"): input_messages.append(msg.model_dump(exclude_none=True)) else: @@ -374,10 +374,10 @@ def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) span.set_attribute("gen_ai.input.messages", json.dumps(input_messages)) # Handle output - Union[str, Message, Sequence[Document], None] - if galileo_span.output is None: + if splunk_ao_span.output is None: return - output_value = galileo_span.output + output_value = splunk_ao_span.output # Type annotation to handle flexible content types (string or dict) # Content can be: str (simple output), dict (documents), or dict (Message model_dump) output_messages: list[dict[str, Any]] = [] @@ -401,22 +401,22 @@ def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) @contextmanager -def start_splunk_ao_span(galileo_span: GalileoSpan) -> Generator[trace.Span, Any, None]: +def start_splunk_ao_span(splunk_ao_span: SplunkAOSpan) -> Generator[trace.Span, Any, None]: tracer_provider = _TRACE_PROVIDER_CONTEXT_VAR.get() if tracer_provider is None: tracer_provider = trace.get_tracer_provider() _TRACE_PROVIDER_CONTEXT_VAR.set(cast(TracerProvider, tracer_provider)) tracer = tracer_provider.get_tracer("galileo-tracer") - with tracer.start_as_current_span(galileo_span.name) as span: + with tracer.start_as_current_span(splunk_ao_span.name) as span: yield span - span.set_attribute("gen_ai.system", "galileo-otel") + span.set_attribute("gen_ai.system", "splunk-ao-otel") # Set dataset attributes for ground truth/reference output support _apply_dataset_attributes( - span, galileo_span.dataset_input, galileo_span.dataset_output, galileo_span.dataset_metadata + span, splunk_ao_span.dataset_input, splunk_ao_span.dataset_output, splunk_ao_span.dataset_metadata ) - if isinstance(galileo_span, RetrieverSpan): - _set_retriever_span_attributes(span, galileo_span) - elif isinstance(galileo_span, ToolSpan): - _set_tool_span_attributes(span, galileo_span) - elif isinstance(galileo_span, WorkflowSpan): - _set_workflow_span_attributes(span, galileo_span) + if isinstance(splunk_ao_span, RetrieverSpan): + _set_retriever_span_attributes(span, splunk_ao_span) + elif isinstance(splunk_ao_span, ToolSpan): + _set_tool_span_attributes(span, splunk_ao_span) + elif isinstance(splunk_ao_span, WorkflowSpan): + _set_workflow_span_attributes(span, splunk_ao_span) diff --git a/src/splunk_ao/utils/openai_agents.py b/src/splunk_ao/utils/openai_agents.py index be6d4c8e..32373aa8 100644 --- a/src/splunk_ao/utils/openai_agents.py +++ b/src/splunk_ao/utils/openai_agents.py @@ -13,7 +13,7 @@ ) from agents.tracing import ResponseSpanData -from galileo_core.schemas.logging.span import Span as GalileoSpan +from galileo_core.schemas.logging.span import Span as SplunkAOSpan from splunk_ao.schema.handlers import SPAN_TYPE from splunk_ao.utils.serialization import serialize_to_str @@ -21,7 +21,7 @@ class SplunkAOCustomSpan(CustomSpanData): - def __init__(self, span: GalileoSpan, data: dict[str, Any]): + def __init__(self, span: SplunkAOSpan, data: dict[str, Any]): self.span = span super().__init__(span.name, data) diff --git a/tests/test_openai_agents_utils.py b/tests/test_openai_agents_utils.py index 69b1bdc0..3e16b8b2 100644 --- a/tests/test_openai_agents_utils.py +++ b/tests/test_openai_agents_utils.py @@ -298,8 +298,8 @@ def test_span_data_types(self, span_data: Any, expected_type: str) -> None: def test_galileo_custom_span(self) -> None: """Test mapping SplunkAOCustomSpan.""" - galileo_span = WorkflowSpan(name="Test", input="input", output="output", status_code=200) - assert _map_span_type(SplunkAOCustomSpan(galileo_span, {})) == "splunk_ao_custom" + splunk_ao_span = WorkflowSpan(name="Test", input="input", output="output", status_code=200) + assert _map_span_type(SplunkAOCustomSpan(splunk_ao_span, {})) == "splunk_ao_custom" @pytest.mark.parametrize( "type_attr,expected_type", [("function", "tool"), ("generation", "llm"), ("agent", "workflow")] diff --git a/tests/test_otel.py b/tests/test_otel.py index a4cae49e..140bed51 100644 --- a/tests/test_otel.py +++ b/tests/test_otel.py @@ -254,7 +254,7 @@ class TestOTelUnavailable: """Test behavior when OpenTelemetry is not available.""" @patch("splunk_ao.otel.OTEL_AVAILABLE", False) - def test_galileo_span_processor_raises_import_error_when_otel_unavailable(self): + def test_splunk_ao_span_processor_raises_import_error_when_otel_unavailable(self): """Test that SplunkAOSpanProcessor raises ImportError when OpenTelemetry is not available.""" with pytest.raises(ImportError, match=re.escape(INSTALL_ERR_MSG)): SplunkAOSpanProcessor(project="test") @@ -569,7 +569,7 @@ def test_tool_span_with_output_no_tool_call_id(self): assert mock_otel_span.set_attribute.call_count == 6 -class TestStartGalileoSpan: +class TestStartSplunkAOSpan: """Test suite for start_splunk_ao_span context manager.""" @pytest.fixture(autouse=True) @@ -604,7 +604,7 @@ def test_start_splunk_ao_span_dispatches_tool_span(self): # Then: the span has gen_ai.system set and tool-specific attributes calls = {args[0]: args[1] for args, _ in mock_otel_span.set_attribute.call_args_list} - assert calls["gen_ai.system"] == "galileo-otel" + assert calls["gen_ai.system"] == "splunk-ao-otel" assert calls["gen_ai.operation.name"] == "execute_tool" assert calls["gen_ai.tool.name"] == "my-tool" assert calls["gen_ai.tool.call.arguments"] == "tool input data" @@ -632,7 +632,7 @@ def test_start_splunk_ao_span_tool_span_with_none_output(self): # Then: gen_ai.system, operation name, tool name, tool arguments, and input are set (no output or tool_call_id) calls = {args[0]: args[1] for args, _ in mock_otel_span.set_attribute.call_args_list} - assert calls["gen_ai.system"] == "galileo-otel" + assert calls["gen_ai.system"] == "splunk-ao-otel" assert calls["gen_ai.operation.name"] == "execute_tool" assert calls["gen_ai.tool.name"] == "minimal-tool" assert calls["gen_ai.tool.call.arguments"] == "just input" From aa42e084771fd877d92cc344f880c0d0821793c3 Mon Sep 17 00:00:00 2001 From: adityamehra Date: Thu, 16 Jul 2026 13:58:13 -0700 Subject: [PATCH 2/2] fix(security): upgrade google-adk minimum version to 1.28.1 (CVE-2026-4810) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the minimum required version of google-adk from 1.14.1 to 1.28.1 to remediate CVE-2026-4810 (CRITICAL) — a Code Injection and Missing Authentication vulnerability that allows unauthenticated remote code execution on servers hosting ADK instances. Resolves: VULN-88790 Co-authored-by: Cursor --- examples/agent/google-adk/requirements.txt | 4 ++-- splunk-ao-adk/pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/agent/google-adk/requirements.txt b/examples/agent/google-adk/requirements.txt index a8801ae6..8ba4dbaa 100644 --- a/examples/agent/google-adk/requirements.txt +++ b/examples/agent/google-adk/requirements.txt @@ -1,4 +1,4 @@ -google-adk +google-adk>=1.28.1 openinference-instrumentation-google-adk python-dotenv -splunk-ao \ No newline at end of file +splunk-ao diff --git a/splunk-ao-adk/pyproject.toml b/splunk-ao-adk/pyproject.toml index 96e46476..94723c49 100644 --- a/splunk-ao-adk/pyproject.toml +++ b/splunk-ao-adk/pyproject.toml @@ -15,7 +15,7 @@ classifiers = [ ] dependencies = [ "splunk-ao>=0.1.0,<1.0.0", - "google-adk>=1.14.1,<2.0.0", + "google-adk>=1.28.1,<2.0.0", ] [project.urls]