Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-relay-gateway/src/lexigram/ai/relay/gateway/operations/telemetry.py: 73%

11 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-25 07:19 +0800

1"""Request telemetry events for the relay gateway service. 

2 

3Terminal and intermediate request events are emitted as structured 

4structlog events with the request id threaded through. No event ever 

5includes request headers, payloads, or upstream details. 

6""" 

7 

8from __future__ import annotations 

9 

10import time 

11 

12from lexigram.contracts.ai.relay import ( 

13 RelayGatewayError, 

14 RelayGatewayRequest, 

15 RelayGatewayResult, 

16 RelayLoss, 

17) 

18from lexigram.logging import get_logger 

19 

20__all__ = ["log_conversion_loss", "log_request_completed"] 

21 

22logger = get_logger(__name__) 

23 

24 

25def log_conversion_loss( 

26 request_id: str, 

27 converter_id: str, 

28 losses: tuple[RelayLoss, ...] | list[RelayLoss], 

29) -> None: 

30 """Emit the conversion-loss event when a conversion recorded losses. 

31 

32 Args: 

33 request_id: The gateway request identifier. 

34 converter_id: The converter that produced the losses. 

35 losses: Recorded conversion losses. 

36 """ 

37 if losses: 

38 logger.info( 

39 "relay_gateway_conversion_loss", 

40 request_id=request_id, 

41 converter_id=converter_id, 

42 loss_codes=tuple(loss.reason for loss in losses), 

43 ) 

44 

45 

46def log_request_completed( 

47 request: RelayGatewayRequest, 

48 channel_name: str, 

49 outcome: RelayGatewayResult | RelayGatewayError, 

50 started: float, 

51 *, 

52 target: str = "", 

53 loss_codes: tuple[str, ...] = (), 

54) -> None: 

55 """Emit the terminal request-completed event for any outcome. 

56 

57 Args: 

58 request: The original gateway request. 

59 channel_name: Selected channel name (or ``""`` when unknown). 

60 outcome: The success result or the error that ended the flow. 

61 started: Monotonic start time used to compute the duration. 

62 target: Target format name (success path only). 

63 loss_codes: Conversion loss codes (success path only). 

64 """ 

65 logger.info( 

66 "relay_gateway_request_completed", 

67 request_id=request.request_id, 

68 tenant_id=request.tenant_id, 

69 channel=channel_name, 

70 source=request.source, 

71 target=target, 

72 status_code=outcome.status_code, 

73 code=outcome.code if isinstance(outcome, RelayGatewayError) else "OK", 

74 duration_ms=round((time.monotonic() - started) * 1000, 2), 

75 loss_codes=loss_codes, 

76 )