Skip to content

Commit 8c3acd2

Browse files
committed
RSPEED-2326: feat(observability): add inference event builder for rlsapi v1
Implement build_inference_event() matching rlsapi Splunk event format: - InferenceEventData dataclass for structured input - Handles auth_disabled case for org_id/system_id - Maps all fields from request data and configuration - Empty placeholders for RAG fields (not yet implemented) Signed-off-by: Major Hayden <major@redhat.com>
1 parent 0e824e3 commit 8c3acd2

5 files changed

Lines changed: 147 additions & 2 deletions

File tree

src/observability/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
33
This module provides functionality for sending telemetry events to external
44
systems like Splunk HEC for monitoring and analytics.
5+
6+
The splunk module provides a format-agnostic send_splunk_event() function.
7+
Event formats are in the formats subpackage - see formats.rlsapi for the
8+
default implementation, or create your own format module.
59
"""
610

11+
from observability.formats import InferenceEventData, build_inference_event
712
from observability.splunk import send_splunk_event
8-
from observability.telemetry import build_inference_event
913

10-
__all__ = ["send_splunk_event", "build_inference_event"]
14+
__all__ = ["send_splunk_event", "InferenceEventData", "build_inference_event"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""Event format builders for Splunk telemetry.
2+
3+
Each submodule provides format-specific event builders. The rlsapi module
4+
provides the default format matching Red Hat's rlsapi v1 specification.
5+
"""
6+
7+
from observability.formats.rlsapi import InferenceEventData, build_inference_event
8+
9+
__all__ = ["InferenceEventData", "build_inference_event"]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""Event builders for rlsapi v1 Splunk format.
2+
3+
This module provides event builders specific to the rlsapi v1 telemetry format.
4+
To implement a custom format, create a new module in this package with your own
5+
event builder function that returns a dict, then pass the result to send_splunk_event().
6+
"""
7+
8+
from dataclasses import dataclass
9+
from typing import Any
10+
11+
from configuration import configuration
12+
13+
14+
@dataclass
15+
class InferenceEventData: # pylint: disable=too-many-instance-attributes
16+
"""Data required to build an inference telemetry event."""
17+
18+
question: str
19+
response: str
20+
inference_time: float
21+
model: str
22+
org_id: str
23+
system_id: str
24+
request_id: str
25+
cla_version: str
26+
system_os: str
27+
system_version: str
28+
system_arch: str
29+
30+
31+
def build_inference_event(data: InferenceEventData) -> dict[str, Any]:
32+
"""Build an inference telemetry event payload matching rlsapi format.
33+
34+
Args:
35+
data: The inference event data.
36+
37+
Returns:
38+
A dictionary matching the rlsapi Splunk event format.
39+
"""
40+
return {
41+
"question": data.question,
42+
"refined_questions": [],
43+
"context": "",
44+
"response": data.response,
45+
"inference_time": data.inference_time,
46+
"model": data.model,
47+
"deployment": configuration.deployment_environment,
48+
"org_id": data.org_id,
49+
"system_id": data.system_id,
50+
# Token counting not yet implemented in lightspeed-stack; rlsapi uses 0 as default
51+
"total_llm_tokens": 0,
52+
"request_id": data.request_id,
53+
"cla_version": data.cla_version,
54+
"system_os": data.system_os,
55+
"system_version": data.system_version,
56+
"system_arch": data.system_arch,
57+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Unit tests for observability event format builders."""
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Unit tests for rlsapi v1 event builders."""
2+
3+
from unittest.mock import patch
4+
5+
import pytest
6+
7+
from observability.formats.rlsapi import InferenceEventData, build_inference_event
8+
9+
10+
@pytest.fixture(name="sample_event_data")
11+
def sample_event_data_fixture() -> InferenceEventData:
12+
"""Create sample inference event data for testing."""
13+
return InferenceEventData(
14+
question="How do I configure SSH?",
15+
response="To configure SSH, edit /etc/ssh/sshd_config...",
16+
inference_time=2.34,
17+
model="granite-3-8b-instruct",
18+
org_id="12345678",
19+
system_id="abc-def-123",
20+
request_id="req_xyz789",
21+
cla_version="CLA/0.4.0",
22+
system_os="RHEL",
23+
system_version="9.3",
24+
system_arch="x86_64",
25+
)
26+
27+
28+
def test_builds_event_with_all_fields(sample_event_data: InferenceEventData) -> None:
29+
"""Test event contains all required fields and placeholders."""
30+
with patch("observability.formats.rlsapi.configuration") as mock_config:
31+
mock_config.deployment_environment = "production"
32+
33+
event = build_inference_event(sample_event_data)
34+
35+
assert event["question"] == "How do I configure SSH?"
36+
assert event["response"] == "To configure SSH, edit /etc/ssh/sshd_config..."
37+
assert event["inference_time"] == 2.34
38+
assert event["model"] == "granite-3-8b-instruct"
39+
assert event["org_id"] == "12345678"
40+
assert event["system_id"] == "abc-def-123"
41+
assert event["request_id"] == "req_xyz789"
42+
assert event["cla_version"] == "CLA/0.4.0"
43+
assert event["system_os"] == "RHEL"
44+
assert event["system_version"] == "9.3"
45+
assert event["system_arch"] == "x86_64"
46+
assert event["deployment"] == "production"
47+
assert not event["refined_questions"]
48+
assert event["context"] == ""
49+
assert event["total_llm_tokens"] == 0
50+
51+
52+
def test_handles_auth_disabled_values() -> None:
53+
"""Test event handles auth_disabled placeholder values."""
54+
data = InferenceEventData(
55+
question="test",
56+
response="test",
57+
inference_time=1.0,
58+
model="test-model",
59+
org_id="auth_disabled",
60+
system_id="auth_disabled",
61+
request_id="req_123",
62+
cla_version="test/1.0",
63+
system_os="",
64+
system_version="",
65+
system_arch="",
66+
)
67+
68+
with patch("observability.formats.rlsapi.configuration") as mock_config:
69+
mock_config.deployment_environment = "test"
70+
71+
event = build_inference_event(data)
72+
73+
assert event["org_id"] == "auth_disabled"
74+
assert event["system_id"] == "auth_disabled"

0 commit comments

Comments
 (0)