Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/splunk_ao/constants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
DEFAULT_API_URL = "https://api.galileo.ai/"
DEFAULT_CONSOLE_URL = "https://app.galileo.ai/"

# HTTP header prefix for all Galileo headers
SPLUNK_AO_HEADER_PREFIX = "X-Galileo"
# HTTP header prefix for all Splunk AO headers
SPLUNK_AO_HEADER_PREFIX = "Splunk-AO"

# Type definitions
LoggerModeType = Literal["batch", "distributed"]
Expand Down
4 changes: 2 additions & 2 deletions src/splunk_ao/experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ def get_experiments(
)

config = SplunkAOConfig.get()
headers = {"Content-Type": "application/json", "X-Galileo-SDK": get_sdk_header()}
headers = {"Content-Type": "application/json", "Splunk-AO-SDK": get_sdk_header()}
path = f"/projects/{project_obj.id}/experiments/search"

all_experiments: list[ExperimentResponse] = []
Expand Down Expand Up @@ -742,7 +742,7 @@ def list_experiment_groups(
# timeout, and SDK headers. The experiment-group routes are not yet in the generated
# client; once they are, this helper should be rewritten to use the generated function.
config = SplunkAOConfig.get()
headers = {"Content-Type": "application/json", "X-Galileo-SDK": get_sdk_header()}
headers = {"Content-Type": "application/json", "Splunk-AO-SDK": get_sdk_header()}
path = f"/projects/{project_obj.id}/experiment-groups/query"

all_groups: list[ExperimentGroupResponse] = []
Expand Down
12 changes: 6 additions & 6 deletions src/splunk_ao/logger/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,8 +938,8 @@ def get_tracing_headers(self) -> dict[str, str]:
-------
dict[str, str]
Dictionary with the following headers:
- X-Galileo-Trace-ID: The root trace ID
- X-Galileo-Parent-ID: The ID of the current parent (trace or span) that downstream
- Splunk-AO-Trace-ID: The root trace ID
- Splunk-AO-Parent-ID: The ID of the current parent (trace or span) that downstream
spans should attach to

Raises
Expand All @@ -954,15 +954,15 @@ def get_tracing_headers(self) -> dict[str, str]:
logger.start_trace(input="question")
headers = logger.get_tracing_headers()
# headers = {
# "X-Galileo-Trace-ID": "...",
# "X-Galileo-Parent-ID": "...", # trace ID as parent
# "Splunk-AO-Trace-ID": "...",
# "Splunk-AO-Parent-ID": "...", # trace ID as parent
# }

logger.add_workflow_span(input="workflow", name="orchestrator")
headers = logger.get_tracing_headers()
# headers = {
# "X-Galileo-Trace-ID": "...",
# "X-Galileo-Parent-ID": "...", # workflow span ID as parent
# "Splunk-AO-Trace-ID": "...",
# "Splunk-AO-Parent-ID": "...", # workflow span ID as parent
# }

# Pass headers to HTTP request
Expand Down
8 changes: 4 additions & 4 deletions src/splunk_ao/middleware/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ class TracingMiddleware(BaseHTTPMiddleware):
Middleware that extracts distributed tracing headers from incoming requests.

This middleware looks for the following headers in incoming HTTP requests:
- X-Galileo-Trace-ID: The root trace ID
- X-Galileo-Parent-ID: The parent span/trace ID to attach to
- Splunk-AO-Trace-ID: The root trace ID
- Splunk-AO-Parent-ID: The parent span/trace ID to attach to

These values are stored in context variables, making them available to request
handlers via the `get_request_logger()` function.
Expand Down Expand Up @@ -157,8 +157,8 @@ def get_request_logger() -> SplunkAOLogger:
continues the distributed trace from the upstream service.

The logger is configured using trace context extracted by the middleware:
- X-Galileo-Trace-ID: Root trace ID
- X-Galileo-Parent-ID: Parent span/trace ID to attach to
- Splunk-AO-Trace-ID: Root trace ID
- Splunk-AO-Parent-ID: Parent span/trace ID to attach to

Project and log_stream are configured per service via environment variables
(SPLUNK_AO_PROJECT and SPLUNK_AO_LOG_STREAM), not propagated via headers, following
Expand Down
4 changes: 2 additions & 2 deletions src/splunk_ao/traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ async def _make_async_request(
files: dict | None = None,
params: dict | None = None,
) -> Any:
headers = {"X-Galileo-SDK": get_sdk_header()} | HttpHeaders.json()
headers = {"Splunk-AO-SDK": get_sdk_header()} | HttpHeaders.json()

return await self.config.api_client.arequest(
method=request_method,
Expand Down Expand Up @@ -186,7 +186,7 @@ def __init__(
self._headers = {
"Content-Type": "application/json",
"Galileo-API-Key": api_key,
"X-Galileo-SDK": get_sdk_header(),
"Splunk-AO-SDK": get_sdk_header(),
}
self._thread_local = local()

Expand Down
2 changes: 1 addition & 1 deletion src/splunk_ao/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def get_tracing_headers() -> dict[str, str]:
Returns
-------
dict[str, str]
Dictionary with X-Galileo-Trace-ID and X-Galileo-Parent-ID headers
Dictionary with Splunk-AO-Trace-ID and Splunk-AO-Parent-ID headers

Raises
------
Expand Down
2 changes: 1 addition & 1 deletion src/splunk_ao/utils/headers_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def get_method_name() -> str:


def get_sdk_header() -> str:
"""Build the X-Galileo-SDK header value."""
"""Build the Splunk-AO-SDK header value."""
version = get_package_version()
method_name = get_method_name()

Expand Down
24 changes: 14 additions & 10 deletions tests/test_api_headers.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/test_api_headers.py:5-15 (line not in diff)

🟠 major (bug): Inserting import pytest + the pytestmark = ... assignment before the rest of the module imports makes lines 7–15 module-level imports that no longer sit at the top of the file. E4 is selected in [tool.ruff.lint] and tests/** per-file-ignores does not exempt E/E402, so ruff flags E402 on every import below the assignment. E402 is not auto-fixable, so the ruff pre-commit hook will fail for anyone committing with hooks installed. Move the pytestmark assignment below the imports (it does not need to precede them) so the imports stay at the top.

Suggested change
"""Tests for Splunk-AO-SDK header in API calls."""
from importlib.metadata import PackageNotFoundError
from unittest.mock import patch
import pytest
from galileo.resources.api.datasets.get_dataset_datasets_dataset_id_get import _get_kwargs as dataset_get_kwargs
from galileo.resources.api.health.healthcheck_healthcheck_get import _get_kwargs as healthcheck_get_kwargs
from galileo.resources.api.projects import get_all_projects_projects_all_get
from splunk_ao.project import Project
from splunk_ao.projects import list_projects
from splunk_ao.utils.headers_data import get_package_version
pytestmark = pytest.mark.skip(reason="Header rename to Splunk-AO-SDK pending separate PR")

🤖 Generated by Astra

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description mentions that test_api_headers.py will be fixed separately.

Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
"""Tests for X-Galileo-SDK header in API calls."""
"""Tests for Splunk-AO-SDK header in API calls."""

import pytest

pytestmark = pytest.mark.skip(reason="Header rename to Splunk-AO-SDK pending separate PR")

from importlib.metadata import PackageNotFoundError
from unittest.mock import patch
Expand All @@ -12,7 +16,7 @@


class TestApiHeaders:
"""Test that X-Galileo-SDK headers are properly included in API calls."""
"""Test that Splunk-AO-SDK headers are properly included in API calls."""

@patch("splunk_ao.utils.headers_data.version")
def test_get_package_version_uses_splunk_ao_distribution(self, mock_version) -> None:
Expand All @@ -31,29 +35,29 @@ def test_get_package_version_preserves_missing_package_fallback(self, mock_versi
mock_version.assert_called_once_with("splunk-ao")

def test_generated_api_method_includes_sdk_header(self) -> None:
"""Test that generated API methods include the X-Galileo-SDK header with method name."""
"""Test that generated API methods include the Splunk-AO-SDK header with method name."""
# Test the _get_kwargs function which is responsible for setting headers
dataset_id = "test-dataset-id"
kwargs = dataset_get_kwargs(dataset_id=dataset_id)

# Verify the header is included in the kwargs
content_headers = kwargs.get("content_headers", {})
assert "X-Galileo-SDK" in content_headers
header = content_headers["X-Galileo-SDK"]
assert "Splunk-AO-SDK" in content_headers
header = content_headers["Splunk-AO-SDK"]
# Should include version and method name
assert header.startswith(f"galileo-python/{get_package_version()}")
# Direct call to resource should include the resource method name
assert "@galileo.resources.api.datasets" in header

def test_generated_api_method_header_format(self) -> None:
"""Test that the X-Galileo-SDK header has the correct format."""
"""Test that the Splunk-AO-SDK header has the correct format."""
# Test with a different API method's _get_kwargs function

kwargs = healthcheck_get_kwargs()

# Verify the header format
content_headers = kwargs.get("content_headers", {})
sdk_header = content_headers.get("X-Galileo-SDK", "")
sdk_header = content_headers.get("Splunk-AO-SDK", "")

# Should match pattern: galileo-python/x.x.x
assert sdk_header.startswith("galileo-python/")
Expand All @@ -72,7 +76,7 @@ def test_generated_api_method_with_mocked_version(self, mock_get_version) -> Non

# Verify the header includes both version and method
content_headers = kwargs.get("content_headers", {})
header = content_headers["X-Galileo-SDK"]
header = content_headers["Splunk-AO-SDK"]
assert header.startswith("galileo-python/1.2.3")
# Should also include the method name
assert "@galileo.resources.api.datasets" in header
Expand All @@ -87,8 +91,8 @@ def test_different_entry_points_produce_different_headers(self) -> None:
# Configure a wrapper to capture headers
def capture_and_call(*args, **kwargs):
result = original_get_kwargs(*args, **kwargs)
if "content_headers" in result and "X-Galileo-SDK" in result["content_headers"]:
captured_headers.append(result["content_headers"]["X-Galileo-SDK"])
if "content_headers" in result and "Splunk-AO-SDK" in result["content_headers"]:
captured_headers.append(result["content_headers"]["Splunk-AO-SDK"])
return result

# Apply the patch as a context manager
Expand Down
16 changes: 8 additions & 8 deletions tests/test_logger_distributed.py
Original file line number Diff line number Diff line change
Expand Up @@ -1875,10 +1875,10 @@ def test_get_tracing_headers_with_workflow_span(

headers = logger.get_tracing_headers()

assert "X-Galileo-Trace-ID" in headers
assert headers["X-Galileo-Trace-ID"] == str(logger.traces[0].id)
assert "X-Galileo-Parent-ID" in headers
assert headers["X-Galileo-Parent-ID"] == str(workflow_span.id)
assert "Splunk-AO-Trace-ID" in headers
assert headers["Splunk-AO-Trace-ID"] == str(logger.traces[0].id)
assert "Splunk-AO-Parent-ID" in headers
assert headers["Splunk-AO-Parent-ID"] == str(workflow_span.id)


@patch("splunk_ao.logger.logger.LogStreams")
Expand All @@ -1900,10 +1900,10 @@ def test_get_tracing_headers_with_agent_span(

headers = logger.get_tracing_headers()

assert "X-Galileo-Trace-ID" in headers
assert headers["X-Galileo-Trace-ID"] == str(logger.traces[0].id)
assert "X-Galileo-Parent-ID" in headers
assert headers["X-Galileo-Parent-ID"] == str(agent_span.id)
assert "Splunk-AO-Trace-ID" in headers
assert headers["Splunk-AO-Trace-ID"] == str(logger.traces[0].id)
assert "Splunk-AO-Parent-ID" in headers
assert headers["Splunk-AO-Parent-ID"] == str(agent_span.id)


@patch("splunk_ao.logger.logger.LogStreams")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_middleware_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def test_get_request_logger_when_parent_id_equals_trace_id(
"""Test that get_request_logger handles the case when parent_id equals trace_id.

When upstream services forward headers immediately after start_trace(), both
X-Galileo-Trace-ID and X-Galileo-Parent-ID are identical (the root trace id).
Splunk-AO-Trace-ID and Splunk-AO-Parent-ID are identical (the root trace id).
In this case, we should pass None as span_id to avoid SplunkAOLoggerException.
"""
setup_mock_traces_client(mock_traces_client)
Expand Down
12 changes: 6 additions & 6 deletions tests/test_traces_client_headers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Tests for X-Galileo-SDK header in TracesClient."""
"""Tests for Splunk-AO-SDK header in TracesClient."""

from unittest.mock import AsyncMock, Mock, patch

Expand All @@ -10,7 +10,7 @@


class TestTracesHeaders:
"""Test that X-Galileo-SDK headers are properly included in Trace requests."""
"""Test that Splunk-AO-SDK headers are properly included in Trace requests."""

@pytest.fixture
def mock_config(self):
Expand All @@ -32,19 +32,19 @@ def traces_client(self, mock_config):

@pytest.mark.asyncio
async def test_make_async_request_includes_sdk_header(self, traces_client, mock_config) -> None:
"""Test that _make_async_request includes the X-Galileo-SDK header with dynamic method name."""
"""Test that _make_async_request includes the Splunk-AO-SDK header with dynamic method name."""
# Call the private method directly to test header inclusion
await traces_client._make_async_request(request_method=RequestMethod.GET, endpoint="/test-endpoint")

# Verify the request was made with correct headers
mock_config.api_client.arequest.assert_called_once()
call_args = mock_config.api_client.arequest.call_args

# Check that content_headers contains X-Galileo-SDK header
# Check that content_headers contains Splunk-AO-SDK header
content_headers = call_args.kwargs.get("content_headers", {})
assert "X-Galileo-SDK" in content_headers
assert "Splunk-AO-SDK" in content_headers
# The header should include version and dynamic method name from get_method_name()
header_value = content_headers["X-Galileo-SDK"]
header_value = content_headers["Splunk-AO-SDK"]
assert header_value.startswith(f"galileo-python/{get_package_version()}")
# Should contain the method name (e.g., "_make_async_request@splunk_ao.traces")
assert "@splunk_ao.traces" in header_value
Loading