Initial production analytics foundation

This commit is contained in:
2026-09-04 05:34:52 +02:00
commit f017d187eb
30 changed files with 1219 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
import io
import json
import tempfile
import unittest
from unittest.mock import patch
from urllib.error import HTTPError
from production_analytics.enlyze.exploration import (
AuthenticationError,
ExplorationClient,
ExplorationSettings,
NonJsonResponseError,
load_secret_file,
)
from production_analytics.enlyze.sanitize import sanitize
class _Response:
status = 200
headers = {"Content-Type": "application/json", "X-Request-Id": "request-123"}
def __init__(self, body: bytes) -> None:
self._body = body
def read(self) -> bytes:
return self._body
def __enter__(self):
return self
def __exit__(self, *_: object) -> None:
return None
class ExplorationClientTests(unittest.TestCase):
def setUp(self) -> None:
self.settings = ExplorationSettings.from_environment(
{
"ENLYZE_BASE_URL": "https://enlyze.example/",
"ENLYZE_API_KEY": "secret",
}
)
@patch("production_analytics.enlyze.exploration.urlopen")
def test_get_uses_explicit_header_and_decodes_json(self, urlopen_mock: object) -> None:
urlopen_mock.return_value = _Response(b'{"items": [1]}') # type: ignore[attr-defined]
response = ExplorationClient(self.settings).get("/observed/path", {"limit": "1"})
request = urlopen_mock.call_args.args[0] # type: ignore[attr-defined]
self.assertEqual(request.get_method(), "GET")
self.assertEqual(request.get_header("Authorization"), "Bearer secret")
self.assertEqual(response.body, {"items": [1]})
@patch("production_analytics.enlyze.exploration.urlopen")
def test_non_json_response_is_clear_error(self, urlopen_mock: object) -> None:
urlopen_mock.return_value = _Response(b"not json") # type: ignore[attr-defined]
with self.assertRaises(NonJsonResponseError):
ExplorationClient(self.settings).get("/observed/path")
@patch("production_analytics.enlyze.exploration.urlopen")
def test_post_json_sends_json_body_and_bearer_header(self, urlopen_mock: object) -> None:
urlopen_mock.return_value = _Response(b'{"data": {}}') # type: ignore[attr-defined]
ExplorationClient(self.settings).post_json("/v2/timeseries", {"machine": "machine-id"})
request = urlopen_mock.call_args.args[0] # type: ignore[attr-defined]
self.assertEqual(request.get_method(), "POST")
self.assertEqual(request.get_header("Content-type"), "application/json")
self.assertEqual(request.data, b'{"machine": "machine-id"}')
self.assertEqual(request.get_header("Authorization"), "Bearer secret")
@patch("production_analytics.enlyze.exploration.urlopen")
def test_authentication_error_does_not_expose_response_body(self, urlopen_mock: object) -> None:
urlopen_mock.side_effect = HTTPError("https://example.invalid", 401, "Unauthorized", {}, io.BytesIO(b"secret")) # type: ignore[attr-defined]
with self.assertRaisesRegex(AuthenticationError, "HTTP 401"):
ExplorationClient(self.settings).get("/observed/path")
class SanitizationTests(unittest.TestCase):
def test_sanitization_preserves_shape_and_redacts_sensitive_values(self) -> None:
response = sanitize(
{
"machine_id": "machine-47",
"token": "very-secret",
"Authorization": "Bearer very-secret",
"site_name": "Sensitive Site",
"api_url": "https://internal.example/v1/items",
"timestamp": "2026-01-01T00:00:00Z",
"unit": "kW",
"value": 12.5,
"quality": "good",
"items": [{"machine_id": "machine-47"}],
}
)
self.assertEqual(response["token"], "<redacted-secret>")
self.assertEqual(response["Authorization"], "<redacted-secret>")
self.assertEqual(response["site_name"], "<redacted-site_name>")
self.assertEqual(response["api_url"], "https://redacted-host.invalid/v1/items")
self.assertEqual(response["timestamp"], "2026-01-01T00:00:00Z")
self.assertEqual(response["unit"], "kW")
self.assertEqual(response["value"], 12.5)
self.assertEqual(response["machine_id"], response["items"][0]["machine_id"])
class SecretFileTests(unittest.TestCase):
def test_secret_file_is_parsed_without_execution(self) -> None:
with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8") as secret_file:
secret_file.write("ENLYZE_API_KEY='key value'\nUNRELATED=plain # comment\n")
secret_file.flush()
values = load_secret_file(secret_file.name)
self.assertEqual(values, {"ENLYZE_API_KEY": "key value", "UNRELATED": "plain"})
if __name__ == "__main__":
unittest.main()