diff --git a/.github/workflows/ci-tests-splunk-ao-a2a.yaml b/.github/workflows/ci-tests-splunk-ao-a2a.yaml new file mode 100644 index 00000000..88498159 --- /dev/null +++ b/.github/workflows/ci-tests-splunk-ao-a2a.yaml @@ -0,0 +1,61 @@ +name: Test splunk-ao-a2a + +on: + push: + branches: [main] + paths: + - 'splunk-ao-a2a/**' + - '.github/workflows/ci-tests-splunk-ao-a2a.yaml' + pull_request: + paths: + - 'splunk-ao-a2a/**' + - '.github/workflows/ci-tests-splunk-ao-a2a.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + test: + name: Python ${{ matrix.python-version }} + strategy: + fail-fast: false + matrix: + python-version: ["3.11", "3.12", "3.13", "3.14"] + + runs-on: ubuntu-latest + # Hard cap per matrix job to bail out fast on real hangs. + timeout-minutes: 30 + + defaults: + run: + working-directory: splunk-ao-a2a + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Install uv + uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6 + with: + enable-cache: true + cache-dependency-glob: "**/splunk-ao-a2a/pyproject.toml" + + # uv sources in pyproject.toml pins splunk-ao to the local monorepo root + # as an editable install, so this always tests against the latest local code. + - name: Install dependencies + run: uv sync --dev + + - name: Show installed versions + run: uv pip list | grep -E "^(galileo|a2a-sdk|splunk-ao)" + + - name: Run type check + run: uv run mypy src/ + + - name: Run tests + run: uv run pytest --cov=splunk_ao_a2a --cov-report=xml diff --git a/galileo-a2a/examples/.env.example b/galileo-a2a/examples/.env.example deleted file mode 100644 index c3dfd4d9..00000000 --- a/galileo-a2a/examples/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -GALILEO_API_KEY=your-galileo-key -GALILEO_CONSOLE_URL=http://localhost:8088 -GALILEO_PROJECT=a2a-distributed-tracing-demo -GALILEO_LOG_STREAM=dev -OPENAI_API_KEY=your-openai-key diff --git a/galileo-a2a/src/galileo_a2a/__init__.py b/galileo-a2a/src/galileo_a2a/__init__.py deleted file mode 100644 index 447fa717..00000000 --- a/galileo-a2a/src/galileo_a2a/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from galileo_a2a._version import __version__ -from galileo_a2a.instrumentor import A2AInstrumentor - -__all__ = ["A2AInstrumentor", "__version__"] diff --git a/galileo-a2a/src/galileo_a2a/_version.py b/galileo-a2a/src/galileo_a2a/_version.py deleted file mode 100644 index 53138230..00000000 --- a/galileo-a2a/src/galileo_a2a/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.0.0b1" diff --git a/galileo-a2a/CHANGELOG.md b/splunk-ao-a2a/CHANGELOG.md similarity index 100% rename from galileo-a2a/CHANGELOG.md rename to splunk-ao-a2a/CHANGELOG.md diff --git a/galileo-a2a/README.md b/splunk-ao-a2a/README.md similarity index 82% rename from galileo-a2a/README.md rename to splunk-ao-a2a/README.md index ae955416..60453fb9 100644 --- a/galileo-a2a/README.md +++ b/splunk-ao-a2a/README.md @@ -1,10 +1,10 @@ -# galileo-a2a +# splunk-ao-a2a -[![PyPI version](https://img.shields.io/pypi/v/galileo-a2a.svg)](https://pypi.org/project/galileo-a2a/) -[![Python versions](https://img.shields.io/pypi/pyversions/galileo-a2a.svg)](https://pypi.org/project/galileo-a2a/) -[![License](https://img.shields.io/pypi/l/galileo-a2a.svg)](https://github.com/rungalileo/galileo-python/blob/main/LICENSE) +[![PyPI version](https://img.shields.io/pypi/v/splunk-ao-a2a.svg)](https://pypi.org/project/splunk-ao-a2a/) +[![Python versions](https://img.shields.io/pypi/pyversions/splunk-ao-a2a.svg)](https://pypi.org/project/splunk-ao-a2a/) +[![License](https://img.shields.io/pypi/l/splunk-ao-a2a.svg)](https://github.com/splunk/splunk-ao-python/blob/main/LICENSE) -Galileo observability for [A2A (Agent-to-Agent)](https://github.com/google/A2A) protocol interactions. Automatic tracing of agent-to-agent calls, task lifecycle, and cross-agent distributed trace correlation. +Splunk AO observability for [A2A (Agent-to-Agent)](https://github.com/google/A2A) protocol interactions. Automatic tracing of agent-to-agent calls, task lifecycle, and cross-agent distributed trace correlation. ## How It Works @@ -25,31 +25,31 @@ Galileo observability for [A2A (Agent-to-Agent)](https://github.com/google/A2A) │ └─────────────────┬────────────────────────┘ │ │ │ │ │ ┌──────────▼──────────┐ │ -│ │ Galileo │ │ +│ │ Splunk AO │ │ │ │ (Trace Explorer) │ │ │ └─────────────────────┘ │ └──────────────────────────────────────────────────────────────────────┘ ``` -`galileo-a2a` instruments both the **client** (outbound calls) and **server** (inbound requests) sides of the A2A protocol. Trace context is propagated through A2A message metadata so all agents appear in a single distributed trace in Galileo. +`splunk-ao-a2a` instruments both the **client** (outbound calls) and **server** (inbound requests) sides of the A2A protocol. Trace context is propagated through A2A message metadata so all agents appear in a single distributed trace in Splunk AO. ## Installation ```bash -pip install galileo-a2a +pip install splunk-ao-a2a ``` -**Requirements:** Python 3.10+, a [Galileo API key](https://www.rungalileo.io/), and [a2a-sdk](https://pypi.org/project/a2a-sdk/) 0.3+ +**Requirements:** Python 3.11+, a [Splunk AO API key](https://www.splunk.com/), and [a2a-sdk](https://pypi.org/project/a2a-sdk/) 0.3+ ## Quick Start ```python -from galileo.otel import GalileoSpanProcessor, add_splunk_ao_span_processor -from galileo_a2a import A2AInstrumentor +from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor +from splunk_ao_a2a import A2AInstrumentor from opentelemetry.sdk.trace import TracerProvider provider = TracerProvider() -add_splunk_ao_span_processor(provider, GalileoSpanProcessor()) +add_splunk_ao_span_processor(provider, SplunkAOSpanProcessor()) A2AInstrumentor().instrument(tracer_provider=provider, agent_name="orchestrator") ``` @@ -63,13 +63,14 @@ Once instrumented, all `a2a-sdk` client and server interactions produce OTel spa | `agent_name` | Name of this agent, set on spans as `gen_ai.agent.name`. | | `capture_content` | Set to `False` to disable capturing message content (e.g. for PII compliance). | -Environment variables for the Galileo exporter: +Environment variables for the Splunk AO exporter: | Environment Variable | Description | |---------------------|-------------| -| `GALILEO_API_KEY` | Galileo API key (required) | -| `GALILEO_PROJECT` | Project name (alternative to `GalileoSpanProcessor(project=...)`) | -| `GALILEO_LOG_STREAM` | Log stream name (alternative to `GalileoSpanProcessor(logstream=...)`) | +| `SPLUNK_AO_API_KEY` | Splunk AO API key (required) | +| `SPLUNK_AO_CONSOLE_URL` | Splunk AO console URL (required for self-hosted deployments, e.g. `http://localhost:8088`) | +| `SPLUNK_AO_PROJECT` | Project name (alternative to `SplunkAOSpanProcessor(project=...)`) | +| `SPLUNK_AO_LOG_STREAM` | Log stream name (alternative to `SplunkAOSpanProcessor(logstream=...)`) | ## Features @@ -83,11 +84,11 @@ The instrumentor patches both sides of the A2A protocol: ### Cross-Agent Distributed Tracing -When Agent A calls Agent B, trace context is propagated through A2A message metadata. The receiving agent joins the caller's trace, so both agents appear in a single distributed trace in Galileo. +When Agent A calls Agent B, trace context is propagated through A2A message metadata. The receiving agent joins the caller's trace, so both agents appear in a single distributed trace in Splunk AO. ### Session Tracking -A2A's `context_id` is mapped to `session.id`, grouping all interactions within the same conversation into a Galileo session. +A2A's `context_id` is mapped to `session.id`, grouping all interactions within the same conversation into a Splunk AO session. ### Disabling Instrumentation @@ -119,8 +120,8 @@ from a2a.types import ( AgentCapabilities, AgentCard, AgentSkill, Message, Role, TaskState, TaskStatus, TaskStatusUpdateEvent, TextPart, ) -from splunk_ao.otel import GalileoSpanProcessor, add_splunk_ao_span_processor -from galileo_a2a import A2AInstrumentor +from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor +from splunk_ao_a2a import A2AInstrumentor from langchain.agents import create_agent from langchain_core.tools import tool from langchain_openai import ChatOpenAI @@ -132,7 +133,7 @@ from typing_extensions import TypedDict # ---- Only 4 lines needed for full distributed tracing ---- provider = TracerProvider() -add_splunk_ao_span_processor(provider, GalileoSpanProcessor()) +add_splunk_ao_span_processor(provider, SplunkAOSpanProcessor()) A2AInstrumentor().instrument(tracer_provider=provider, agent_name="orchestrator") LangchainInstrumentor().instrument(tracer_provider=provider) @@ -255,13 +256,13 @@ async def main(): provider.shutdown() if __name__ == "__main__": - # Set environment variables: GALILEO_API_KEY, OPENAI_API_KEY + # Set environment variables: SPLUNK_AO_API_KEY, OPENAI_API_KEY asyncio.run(main()) ``` ## Resources -- [Galileo Documentation](https://v2docs.galileo.ai) +- [Splunk AO Documentation](https://docs.galileo.ai) - [A2A Protocol Specification](https://a2a-protocol.org) - [a2a-sdk Documentation](https://pypi.org/project/a2a-sdk) diff --git a/splunk-ao-a2a/examples/.env.example b/splunk-ao-a2a/examples/.env.example new file mode 100644 index 00000000..c3eaf9fb --- /dev/null +++ b/splunk-ao-a2a/examples/.env.example @@ -0,0 +1,5 @@ +SPLUNK_AO_API_KEY=your-splunk-ao-key +SPLUNK_AO_CONSOLE_URL=https:// +SPLUNK_AO_PROJECT=a2a-distributed-tracing-demo +SPLUNK_AO_LOG_STREAM=dev +OPENAI_API_KEY=your-openai-key diff --git a/galileo-a2a/examples/two_agent_demo.py b/splunk-ao-a2a/examples/two_agent_demo.py similarity index 97% rename from galileo-a2a/examples/two_agent_demo.py rename to splunk-ao-a2a/examples/two_agent_demo.py index b9477c39..3d5c5e2f 100644 --- a/galileo-a2a/examples/two_agent_demo.py +++ b/splunk-ao-a2a/examples/two_agent_demo.py @@ -1,9 +1,9 @@ -"""Two-agent A2A demo with LangGraph orchestrator and Galileo distributed tracing. +"""Two-agent A2A demo with LangGraph orchestrator and Splunk AO distributed tracing. Architecture: Orchestrator (LangGraph) ──A2A──> Researcher (LangChain agent + search tool) -Both agents appear in a single distributed trace in Galileo. +Both agents appear in a single distributed trace in Splunk AO. Usage: # Copy and fill in the .env file: @@ -52,12 +52,12 @@ from starlette.applications import Starlette from typing_extensions import TypedDict -from galileo_a2a import A2AInstrumentor +from splunk_ao_a2a import A2AInstrumentor load_dotenv(Path(__file__).parent / ".env") # --------------------------------------------------------------------------- -# Galileo tracing setup +# Splunk AO tracing setup # --------------------------------------------------------------------------- provider = TracerProvider() diff --git a/galileo-a2a/pyproject.toml b/splunk-ao-a2a/pyproject.toml similarity index 74% rename from galileo-a2a/pyproject.toml rename to splunk-ao-a2a/pyproject.toml index 9131d8a5..f80934bc 100644 --- a/galileo-a2a/pyproject.toml +++ b/splunk-ao-a2a/pyproject.toml @@ -1,11 +1,11 @@ [project] -name = "galileo-a2a" -version = "1.0.0" -description = "Galileo observability auto-instrumentation for A2A (Agent-to-Agent) protocol" +name = "splunk-ao-a2a" +version = "0.1.0" +description = "Splunk AO observability auto-instrumentation for A2A (Agent-to-Agent) protocol" readme = "README.md" requires-python = ">=3.11,<3.15" license = { text = "Apache-2.0" } -authors = [{ name = "Galileo Technologies Inc.", email = "team@galileo.ai" }] +authors = [{ name = "Splunk Inc.", email = "team@splunk.com" }] classifiers = [ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", @@ -14,18 +14,18 @@ classifiers = [ "Programming Language :: Python :: 3.13", ] dependencies = [ - "galileo>=1.47.0,<2.0.0", + "splunk-ao>=0.1.0,<1.0.0", "a2a-sdk>=0.3.0,<1.0.0", "opentelemetry-api>=1.38.0", "opentelemetry-sdk>=1.38.0", ] [project.urls] -Repository = "https://github.com/rungalileo/galileo-python" +Repository = "https://github.com/splunk/splunk-ao-python" # UV-specific configuration (path for dev, ignored when installed from PyPI) [tool.uv] -sources = { galileo = { path = "../", editable = true } } +sources = { "splunk-ao" = { path = "../", editable = true } } [dependency-groups] dev = [ @@ -37,7 +37,7 @@ dev = [ "ruff>=0.12.3", "mypy>=1.16.0", "opentelemetry-instrumentation>=0.61b0", - "galileo[otel]>=1.47.0", + "splunk-ao[otel]>=0.1.0,<1.0.0", ] examples = [ "uvicorn>=0.42.0", @@ -57,7 +57,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] -packages = ["src/galileo_a2a"] +packages = ["src/splunk_ao_a2a"] [tool.pytest.ini_options] testpaths = ["tests"] @@ -68,10 +68,10 @@ python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] env = [ - "GALILEO_CONSOLE_URL=http://fake.test:8088", - "GALILEO_API_KEY=api-1234567890", - "GALILEO_PROJECT=test-project", - "GALILEO_LOG_STREAM=test-log-stream", + "SPLUNK_AO_CONSOLE_URL=http://fake.test:8088", + "SPLUNK_AO_API_KEY=api-1234567890", + "SPLUNK_AO_PROJECT=test-project", + "SPLUNK_AO_LOG_STREAM=test-log-stream", ] addopts = [ "-v", @@ -94,7 +94,7 @@ ignore = ["ARG001", "ARG002", "D"] "tests/**/*.py" = ["ARG", "D"] [tool.ruff.lint.isort] -known-first-party = ["galileo_a2a", "galileo"] +known-first-party = ["splunk_ao_a2a", "splunk_ao"] [tool.mypy] python_version = "3.11" @@ -105,7 +105,7 @@ ignore_missing_imports = true follow_imports = "skip" [tool.coverage.run] -source = ["src/galileo_a2a"] +source = ["src/splunk_ao_a2a"] omit = ["tests/*"] [tool.coverage.report] @@ -119,11 +119,11 @@ exclude_lines = [ ] [tool.semantic_release] -version_variables = ["src/galileo_a2a/_version.py:__version__"] +version_variables = ["src/splunk_ao_a2a/_version.py:__version__"] version_toml = ["pyproject.toml:project.version"] -tag_format = "galileo-a2a-v{version}" +tag_format = "splunk-ao-a2a-v{version}" version_source = "tag" -commit_message = "chore(release): galileo-a2a v{version}\n\nAutomatically generated by python-semantic-release" +commit_message = "chore(release): splunk-ao-a2a v{version}\n\nAutomatically generated by python-semantic-release" [tool.semantic_release.commit_parser_options] patch_tags = ["fix", "perf", "chore", "docs", "style", "refactor"] diff --git a/splunk-ao-a2a/src/splunk_ao_a2a/__init__.py b/splunk-ao-a2a/src/splunk_ao_a2a/__init__.py new file mode 100644 index 00000000..df09343c --- /dev/null +++ b/splunk-ao-a2a/src/splunk_ao_a2a/__init__.py @@ -0,0 +1,4 @@ +from splunk_ao_a2a._version import __version__ +from splunk_ao_a2a.instrumentor import A2AInstrumentor + +__all__ = ["A2AInstrumentor", "__version__"] diff --git a/galileo-a2a/src/galileo_a2a/_client_patches.py b/splunk-ao-a2a/src/splunk_ao_a2a/_client_patches.py similarity index 95% rename from galileo-a2a/src/galileo_a2a/_client_patches.py rename to splunk-ao-a2a/src/splunk_ao_a2a/_client_patches.py index 8e3f0ae0..1c839218 100644 --- a/galileo-a2a/src/galileo_a2a/_client_patches.py +++ b/splunk-ao-a2a/src/splunk_ao_a2a/_client_patches.py @@ -11,9 +11,9 @@ from opentelemetry import trace from opentelemetry.trace import StatusCode, Tracer -from galileo_a2a._constants import GALILEO_OBSERVE_KEY -from galileo_a2a._context import inject_trace_context, iter_with_context -from galileo_a2a._spans import ( +from splunk_ao_a2a._constants import SPLUNK_AO_OBSERVE_KEY +from splunk_ao_a2a._context import inject_trace_context, iter_with_context +from splunk_ao_a2a._spans import ( set_client_attributes, set_input, set_simple_input, @@ -107,7 +107,7 @@ async def wrapper( otel_context.detach(token) request_metadata = dict(request_metadata) if request_metadata else {} - request_metadata[GALILEO_OBSERVE_KEY] = observe_ctx + request_metadata[SPLUNK_AO_OBSERVE_KEY] = observe_ctx result = original( self, diff --git a/galileo-a2a/src/galileo_a2a/_constants.py b/splunk-ao-a2a/src/splunk_ao_a2a/_constants.py similarity index 88% rename from galileo-a2a/src/galileo_a2a/_constants.py rename to splunk-ao-a2a/src/splunk_ao_a2a/_constants.py index edc10a89..6dade0cb 100644 --- a/galileo-a2a/src/galileo_a2a/_constants.py +++ b/splunk-ao-a2a/src/splunk_ao_a2a/_constants.py @@ -1,13 +1,13 @@ -"""Constants for galileo-a2a instrumentation.""" +"""Constants for splunk-ao-a2a instrumentation.""" # Instrumentor identity -from galileo_a2a._version import __version__ +from splunk_ao_a2a._version import __version__ -INSTRUMENTOR_NAME = "galileo-a2a" +INSTRUMENTOR_NAME = "splunk-ao-a2a" INSTRUMENTOR_VERSION = __version__ # Metadata keys for in-band trace context propagation -GALILEO_OBSERVE_KEY = "galileo_observe" +SPLUNK_AO_OBSERVE_KEY = "splunk_ao_observe" AGNTCY_OBSERVE_KEY = "observe" # compatibility with AGNTCY Observe SDK # A2A span attribute keys (match API-side A2A extension expectations) diff --git a/galileo-a2a/src/galileo_a2a/_context.py b/splunk-ao-a2a/src/splunk_ao_a2a/_context.py similarity index 96% rename from galileo-a2a/src/galileo_a2a/_context.py rename to splunk-ao-a2a/src/splunk_ao_a2a/_context.py index e1fd4ab3..12b9a1de 100644 --- a/galileo-a2a/src/galileo_a2a/_context.py +++ b/splunk-ao-a2a/src/splunk_ao_a2a/_context.py @@ -10,9 +10,9 @@ from opentelemetry.propagate import inject as otel_inject from opentelemetry.trace import Link, NonRecordingSpan, SpanContext, TraceFlags -from galileo_a2a._constants import ( +from splunk_ao_a2a._constants import ( AGNTCY_OBSERVE_KEY, - GALILEO_OBSERVE_KEY, + SPLUNK_AO_OBSERVE_KEY, LINK_FROM_AGENT, LINK_TYPE, LINK_TYPE_AGENT_HANDOFF, @@ -46,14 +46,14 @@ def inject_trace_context(agent_name: str | None = None) -> dict[str, str]: def extract_trace_context(metadata: dict[str, Any] | None) -> dict[str, str] | None: """Extract trace context from A2A request metadata. - Checks the Galileo key first, then falls back to the AGNTCY key for + Checks the Splunk AO key first, then falls back to the AGNTCY key for interoperability with the AGNTCY Observe SDK. Returns ``None`` when no trace context is present. """ if not metadata or not isinstance(metadata, dict): return None - ctx = metadata.get(GALILEO_OBSERVE_KEY) + ctx = metadata.get(SPLUNK_AO_OBSERVE_KEY) if ctx and isinstance(ctx, dict): return {str(k): str(v) for k, v in ctx.items()} diff --git a/galileo-a2a/src/galileo_a2a/_server_patches.py b/splunk-ao-a2a/src/splunk_ao_a2a/_server_patches.py similarity index 97% rename from galileo-a2a/src/galileo_a2a/_server_patches.py rename to splunk-ao-a2a/src/splunk_ao_a2a/_server_patches.py index 50a103fc..46ea20bb 100644 --- a/galileo-a2a/src/galileo_a2a/_server_patches.py +++ b/splunk-ao-a2a/src/splunk_ao_a2a/_server_patches.py @@ -10,13 +10,13 @@ from opentelemetry import trace from opentelemetry.trace import StatusCode, Tracer -from galileo_a2a._context import ( +from splunk_ao_a2a._context import ( create_parent_context_from_trace, create_span_link_from_context, extract_trace_context, iter_with_context, ) -from galileo_a2a._spans import set_input, set_output, set_server_attributes, track_task_state +from splunk_ao_a2a._spans import set_input, set_output, set_server_attributes, track_task_state _logger = logging.getLogger(__name__) diff --git a/galileo-a2a/src/galileo_a2a/_spans.py b/splunk-ao-a2a/src/splunk_ao_a2a/_spans.py similarity index 99% rename from galileo-a2a/src/galileo_a2a/_spans.py rename to splunk-ao-a2a/src/splunk_ao_a2a/_spans.py index a6ea1bd1..2e37f88c 100644 --- a/galileo-a2a/src/galileo_a2a/_spans.py +++ b/splunk-ao-a2a/src/splunk_ao_a2a/_spans.py @@ -9,7 +9,7 @@ from opentelemetry import trace from opentelemetry.trace import StatusCode -from galileo_a2a._constants import ( +from splunk_ao_a2a._constants import ( A2A_CONTEXT_ID, A2A_RPC_METHOD, A2A_TASK_ID, diff --git a/splunk-ao-a2a/src/splunk_ao_a2a/_version.py b/splunk-ao-a2a/src/splunk_ao_a2a/_version.py new file mode 100644 index 00000000..3dc1f76b --- /dev/null +++ b/splunk-ao-a2a/src/splunk_ao_a2a/_version.py @@ -0,0 +1 @@ +__version__ = "0.1.0" diff --git a/galileo-a2a/src/galileo_a2a/instrumentor.py b/splunk-ao-a2a/src/splunk_ao_a2a/instrumentor.py similarity index 87% rename from galileo-a2a/src/galileo_a2a/instrumentor.py rename to splunk-ao-a2a/src/splunk_ao_a2a/instrumentor.py index 1d7e9eaf..3db3bc62 100644 --- a/galileo-a2a/src/galileo_a2a/instrumentor.py +++ b/splunk-ao-a2a/src/splunk_ao_a2a/instrumentor.py @@ -9,10 +9,10 @@ from opentelemetry import trace from opentelemetry.instrumentation.instrumentor import BaseInstrumentor # type: ignore[import-untyped] -from galileo_a2a import _spans -from galileo_a2a._client_patches import _patch_client, _unpatch_client -from galileo_a2a._constants import INSTRUMENTOR_NAME, INSTRUMENTOR_VERSION -from galileo_a2a._server_patches import _patch_server, _unpatch_server +from splunk_ao_a2a import _spans +from splunk_ao_a2a._client_patches import _patch_client, _unpatch_client +from splunk_ao_a2a._constants import INSTRUMENTOR_NAME, INSTRUMENTOR_VERSION +from splunk_ao_a2a._server_patches import _patch_server, _unpatch_server _logger = logging.getLogger(__name__) @@ -33,7 +33,7 @@ class A2AInstrumentor(BaseInstrumentor): # type: ignore[misc] from opentelemetry.sdk.trace import TracerProvider from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor - from galileo_a2a import A2AInstrumentor + from splunk_ao_a2a import A2AInstrumentor provider = TracerProvider() add_splunk_ao_span_processor(provider, SplunkAOSpanProcessor()) diff --git a/galileo-a2a/src/galileo_a2a/py.typed b/splunk-ao-a2a/src/splunk_ao_a2a/py.typed similarity index 100% rename from galileo-a2a/src/galileo_a2a/py.typed rename to splunk-ao-a2a/src/splunk_ao_a2a/py.typed diff --git a/galileo-a2a/tests/conftest.py b/splunk-ao-a2a/tests/conftest.py similarity index 70% rename from galileo-a2a/tests/conftest.py rename to splunk-ao-a2a/tests/conftest.py index 22e5d807..0049f4a9 100644 --- a/galileo-a2a/tests/conftest.py +++ b/splunk-ao-a2a/tests/conftest.py @@ -9,8 +9,8 @@ # 3. Security - prevents real API keys from leaking into test logs import os -os.environ["GALILEO_CONSOLE_URL"] = "http://fake.test:8088" -os.environ["GALILEO_API_KEY"] = "api-1234567890" -os.environ["GALILEO_PROJECT"] = "test-project" -os.environ["GALILEO_LOG_STREAM"] = "test-log-stream" +os.environ["SPLUNK_AO_CONSOLE_URL"] = "http://fake.test:8088" +os.environ["SPLUNK_AO_API_KEY"] = "api-1234567890" +os.environ["SPLUNK_AO_PROJECT"] = "test-project" +os.environ["SPLUNK_AO_LOG_STREAM"] = "test-log-stream" # fmt: on diff --git a/galileo-a2a/tests/test_client_patches.py b/splunk-ao-a2a/tests/test_client_patches.py similarity index 96% rename from galileo-a2a/tests/test_client_patches.py rename to splunk-ao-a2a/tests/test_client_patches.py index 419c3bc7..5f18f0b7 100644 --- a/galileo-a2a/tests/test_client_patches.py +++ b/splunk-ao-a2a/tests/test_client_patches.py @@ -6,10 +6,10 @@ import pytest from opentelemetry.trace import Span, StatusCode, Tracer -from galileo_a2a._client_patches import _originals, _patch_client, _unpatch_client, _wrap_send_message +from splunk_ao_a2a._client_patches import _originals, _patch_client, _unpatch_client, _wrap_send_message -@patch("galileo_a2a._client_patches.BaseClient") +@patch("splunk_ao_a2a._client_patches.BaseClient") class TestPatchClient: def test_patches_all_methods(self, mock_base_client): # Given: a fresh state @@ -45,7 +45,7 @@ def test_idempotent_second_call_is_noop(self, mock_base_client): # Cleanup _originals.clear() - @patch("galileo_a2a._client_patches._wrap_simple_method") + @patch("splunk_ao_a2a._client_patches._wrap_simple_method") def test_rollback_on_failure(self, mock_wrap, mock_base_client): # Given: _wrap_simple_method raises on the third call (get_card) _originals.clear() @@ -59,7 +59,7 @@ def test_rollback_on_failure(self, mock_wrap, mock_base_client): assert len(_originals) == 0 -@patch("galileo_a2a._client_patches.BaseClient") +@patch("splunk_ao_a2a._client_patches.BaseClient") class TestUnpatchClient: def test_restores_originals(self, mock_base_client): # Given: patched state diff --git a/galileo-a2a/tests/test_context.py b/splunk-ao-a2a/tests/test_context.py similarity index 93% rename from galileo-a2a/tests/test_context.py rename to splunk-ao-a2a/tests/test_context.py index cd897422..6b9ac655 100644 --- a/galileo-a2a/tests/test_context.py +++ b/splunk-ao-a2a/tests/test_context.py @@ -5,8 +5,8 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.trace import Link -from galileo_a2a._constants import AGNTCY_OBSERVE_KEY, GALILEO_OBSERVE_KEY -from galileo_a2a._context import ( +from splunk_ao_a2a._constants import AGNTCY_OBSERVE_KEY, SPLUNK_AO_OBSERVE_KEY +from splunk_ao_a2a._context import ( create_span_link_from_context, extract_trace_context, inject_trace_context, @@ -33,10 +33,10 @@ def test_includes_agent_name(self): class TestExtractTraceContext: - def test_extracts_from_galileo_observe_key(self): - # Given: metadata with galileo_observe context + def test_extracts_from_splunk_ao_observe_key(self): + # Given: metadata with splunk_ao_observe context metadata = { - GALILEO_OBSERVE_KEY: { + SPLUNK_AO_OBSERVE_KEY: { "traceparent": "00-aabb00112233445566778899aabbccdd-1122334455667788-01", "agent_name": "planner", } @@ -45,7 +45,7 @@ def test_extracts_from_galileo_observe_key(self): # When: extracting trace context result = extract_trace_context(metadata) - # Then: context extracted from galileo_observe key + # Then: context extracted from splunk_ao_observe key assert result is not None assert result["traceparent"] == "00-aabb00112233445566778899aabbccdd-1122334455667788-01" assert result["agent_name"] == "planner" @@ -66,19 +66,19 @@ def test_extracts_from_agntcy_observe_key(self): assert result is not None assert "traceparent" in result - def test_galileo_key_takes_precedence_over_agntcy(self): + def test_splunk_ao_key_takes_precedence_over_agntcy(self): # Given: metadata with both keys metadata = { - GALILEO_OBSERVE_KEY: {"traceparent": "galileo-traceparent"}, + SPLUNK_AO_OBSERVE_KEY: {"traceparent": "splunk-ao-traceparent"}, AGNTCY_OBSERVE_KEY: {"traceparent": "agntcy-traceparent"}, } # When: extracting trace context result = extract_trace_context(metadata) - # Then: galileo key takes precedence + # Then: splunk_ao key takes precedence assert result is not None - assert result["traceparent"] == "galileo-traceparent" + assert result["traceparent"] == "splunk-ao-traceparent" def test_returns_none_when_missing(self): # Given: metadata with no observe keys diff --git a/galileo-a2a/tests/test_instrumentor.py b/splunk-ao-a2a/tests/test_instrumentor.py similarity index 82% rename from galileo-a2a/tests/test_instrumentor.py rename to splunk-ao-a2a/tests/test_instrumentor.py index fb80bcb8..23f1fcb1 100644 --- a/galileo-a2a/tests/test_instrumentor.py +++ b/splunk-ao-a2a/tests/test_instrumentor.py @@ -2,7 +2,7 @@ from unittest.mock import MagicMock, patch -from galileo_a2a.instrumentor import A2AInstrumentor +from splunk_ao_a2a.instrumentor import A2AInstrumentor class TestA2AInstrumentor: @@ -16,8 +16,8 @@ def test_instrumentation_dependencies(self): # Then: requires a2a-sdk assert "a2a-sdk>=0.3.0,<1.0.0" in deps - @patch("galileo_a2a.instrumentor._patch_server") - @patch("galileo_a2a.instrumentor._patch_client") + @patch("splunk_ao_a2a.instrumentor._patch_server") + @patch("splunk_ao_a2a.instrumentor._patch_client") def test_instrument_calls_patch_functions(self, mock_patch_client, mock_patch_server): # Given: an instrumentor instrumentor = A2AInstrumentor() @@ -33,8 +33,8 @@ def test_instrument_calls_patch_functions(self, mock_patch_client, mock_patch_se _, kwargs = mock_patch_client.call_args assert kwargs["agent_name"] == "test-agent" - @patch("galileo_a2a.instrumentor._unpatch_server") - @patch("galileo_a2a.instrumentor._unpatch_client") + @patch("splunk_ao_a2a.instrumentor._unpatch_server") + @patch("splunk_ao_a2a.instrumentor._unpatch_client") def test_uninstrument_calls_unpatch_functions(self, mock_unpatch_client, mock_unpatch_server): # Given: an instrumentor instrumentor = A2AInstrumentor() @@ -46,8 +46,8 @@ def test_uninstrument_calls_unpatch_functions(self, mock_unpatch_client, mock_un mock_unpatch_client.assert_called_once() mock_unpatch_server.assert_called_once() - @patch("galileo_a2a.instrumentor._patch_server") - @patch("galileo_a2a.instrumentor._patch_client") + @patch("splunk_ao_a2a.instrumentor._patch_server") + @patch("splunk_ao_a2a.instrumentor._patch_client") def test_instrument_passes_tracer_provider(self, mock_patch_client, mock_patch_server): # Given: a mock tracer provider mock_provider = MagicMock() diff --git a/galileo-a2a/tests/test_server_patches.py b/splunk-ao-a2a/tests/test_server_patches.py similarity index 96% rename from galileo-a2a/tests/test_server_patches.py rename to splunk-ao-a2a/tests/test_server_patches.py index 044f3c4e..86985880 100644 --- a/galileo-a2a/tests/test_server_patches.py +++ b/splunk-ao-a2a/tests/test_server_patches.py @@ -6,10 +6,10 @@ import pytest from opentelemetry.trace import Span, StatusCode, Tracer -from galileo_a2a._server_patches import _originals, _patch_server, _unpatch_server, _wrap_on_message_send_stream +from splunk_ao_a2a._server_patches import _originals, _patch_server, _unpatch_server, _wrap_on_message_send_stream -@patch("galileo_a2a._server_patches.DefaultRequestHandler") +@patch("splunk_ao_a2a._server_patches.DefaultRequestHandler") class TestPatchServer: def test_patches_all_methods(self, mock_handler): # Given: a fresh state @@ -44,7 +44,7 @@ def test_idempotent_second_call_is_noop(self, mock_handler): _originals.clear() -@patch("galileo_a2a._server_patches.DefaultRequestHandler") +@patch("splunk_ao_a2a._server_patches.DefaultRequestHandler") class TestUnpatchServer: def test_restores_originals(self, mock_handler): # Given: patched state diff --git a/galileo-a2a/tests/test_spans.py b/splunk-ao-a2a/tests/test_spans.py similarity index 99% rename from galileo-a2a/tests/test_spans.py rename to splunk-ao-a2a/tests/test_spans.py index d603a9d2..39e4f196 100644 --- a/galileo-a2a/tests/test_spans.py +++ b/splunk-ao-a2a/tests/test_spans.py @@ -7,8 +7,8 @@ import pytest from opentelemetry.trace import Span, StatusCode -from galileo_a2a import _spans -from galileo_a2a._constants import ( +from splunk_ao_a2a import _spans +from splunk_ao_a2a._constants import ( A2A_CONTEXT_ID, A2A_RPC_METHOD, A2A_TASK_ID,