Skip to content

Commit 9a7014a

Browse files
Feature/eli 369 dynamodb x ray tracing (#256)
* handled none headers from request * x-ray tracing setup for dynamo, s3, firehose * enable_xray_patching env variable for lambda * sonar fixes --------- Co-authored-by: karthikeyannhs <174426205+Karthikeyannhs@users.noreply.github.com>
1 parent de8ebac commit 9a7014a

12 files changed

Lines changed: 77 additions & 24 deletions

File tree

infrastructure/modules/lambda/lambda.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" {
2222
KINESIS_AUDIT_STREAM_TO_S3 = var.kinesis_audit_stream_to_s3_name
2323
ENV = var.environment
2424
LOG_LEVEL = var.log_level
25+
ENABLE_XRAY_PATCHING = var.enable_xray_patching
2526
}
2627
}
2728

infrastructure/modules/lambda/variables.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,8 @@ variable "log_level" {
4747
description = "log level"
4848
type = string
4949
}
50+
51+
variable "enable_xray_patching"{
52+
description = "flag to enable xray tracing, which puts an entry for dynamodb, s3 and firehose in trace map"
53+
type = string
54+
}

infrastructure/stacks/api-layer/lambda.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ module "eligibility_signposting_lambda_function" {
2424
eligibility_status_table_name = module.eligibility_status_table.table_name
2525
kinesis_audit_stream_to_s3_name = module.eligibility_audit_firehose_delivery_stream.firehose_stream_name
2626
log_level = "INFO"
27+
enable_xray_patching = "true"
2728
stack_name = local.stack_name
2829
}

poetry.lock

Lines changed: 19 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ python-json-logger = "^3.3.0"
3535
fhir-resources = "^8.0.0"
3636
python-dateutil = "^2.9.0"
3737
pyhamcrest = "^2.1.0"
38+
aws-xray-sdk = "2.14.0"
3839

3940
[tool.poetry.group.dev.dependencies]
4041
ruff = "^0.11.13"

src/eligibility_signposting_api/app.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import logging
2+
import os
23
from typing import Any
34

45
import wireup.integration.flask
56
from asgiref.wsgi import WsgiToAsgi
7+
from aws_xray_sdk.core import patch_all
68
from flask import Flask
79
from mangum import Mangum
810
from mangum.types import LambdaContext, LambdaEvent
@@ -11,10 +13,14 @@
1113
from eligibility_signposting_api.common.error_handler import handle_exception
1214
from eligibility_signposting_api.common.request_validator import validate_request_params
1315
from eligibility_signposting_api.config.config import config
14-
from eligibility_signposting_api.logging.logs_helper import log_request_ids
15-
from eligibility_signposting_api.logging.logs_manager import add_request_id_to_logs, init_logging
16+
from eligibility_signposting_api.logging.logs_helper import log_request_ids_from_headers
17+
from eligibility_signposting_api.logging.logs_manager import add_lambda_request_id_to_logger, init_logging
18+
from eligibility_signposting_api.logging.tracing_helper import tracing_setup
1619
from eligibility_signposting_api.views import eligibility_blueprint
1720

21+
if os.getenv("ENABLE_XRAY_PATCHING"):
22+
patch_all()
23+
1824
init_logging()
1925
logger = logging.getLogger(__name__)
2026

@@ -25,8 +31,9 @@ def main() -> None: # pragma: no cover
2531
app.run(debug=config()["log_level"] == logging.DEBUG)
2632

2733

28-
@add_request_id_to_logs()
29-
@log_request_ids()
34+
@add_lambda_request_id_to_logger()
35+
@tracing_setup()
36+
@log_request_ids_from_headers()
3037
@validate_request_params()
3138
def lambda_handler(event: LambdaEvent, context: LambdaContext) -> dict[str, Any]: # pragma: no cover
3239
"""Run the Flask app as an AWS Lambda."""

src/eligibility_signposting_api/config/config.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def config() -> dict[str, Any]:
2222
rules_bucket_name = BucketName(os.getenv("RULES_BUCKET_NAME", "test-rules-bucket"))
2323
audit_bucket_name = BucketName(os.getenv("AUDIT_BUCKET_NAME", "test-audit-bucket"))
2424
aws_default_region = AwsRegion(os.getenv("AWS_DEFAULT_REGION", "eu-west-1"))
25+
enable_xray_patching = bool(os.getenv("ENABLE_XRAY_PATCHING", "false"))
2526
kinesis_audit_stream_to_s3 = AwsKinesisFirehoseStreamName(
2627
os.getenv("KINESIS_AUDIT_STREAM_TO_S3", "test_kinesis_audit_stream_to_s3")
2728
)
@@ -39,19 +40,22 @@ def config() -> dict[str, Any]:
3940
"audit_bucket_name": audit_bucket_name,
4041
"firehose_endpoint": None,
4142
"kinesis_audit_stream_to_s3": kinesis_audit_stream_to_s3,
43+
"enable_xray_patching": enable_xray_patching,
4244
"log_level": log_level,
4345
}
4446

47+
local_stack_endpoint = "http://localhost:4566"
4548
return {
4649
"aws_access_key_id": AwsAccessKey(os.getenv("AWS_ACCESS_KEY_ID", "dummy_key")),
4750
"aws_default_region": aws_default_region,
4851
"aws_secret_access_key": AwsSecretAccessKey(os.getenv("AWS_SECRET_ACCESS_KEY", "dummy_secret")),
49-
"dynamodb_endpoint": URL(os.getenv("DYNAMODB_ENDPOINT", "http://localhost:4566")),
52+
"dynamodb_endpoint": URL(os.getenv("DYNAMODB_ENDPOINT", local_stack_endpoint)),
5053
"person_table_name": person_table_name,
51-
"s3_endpoint": URL(os.getenv("S3_ENDPOINT", "http://localhost:4566")),
54+
"s3_endpoint": URL(os.getenv("S3_ENDPOINT", local_stack_endpoint)),
5255
"rules_bucket_name": rules_bucket_name,
5356
"audit_bucket_name": audit_bucket_name,
54-
"firehose_endpoint": URL(os.getenv("FIREHOSE_ENDPOINT", "http://localhost:4566")),
57+
"firehose_endpoint": URL(os.getenv("FIREHOSE_ENDPOINT", local_stack_endpoint)),
5558
"kinesis_audit_stream_to_s3": kinesis_audit_stream_to_s3,
59+
"enable_xray_patching": enable_xray_patching,
5660
"log_level": log_level,
5761
}

src/eligibility_signposting_api/logging/logs_helper.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
logger = logging.getLogger(__name__)
99

1010

11-
def log_request_ids() -> Callable:
11+
def log_request_ids_from_headers() -> Callable:
1212
def decorator(func: Callable) -> Callable:
1313
@wraps(func)
1414
def wrapper(event: LambdaEvent, context: LambdaContext) -> dict[str, Any] | None:
15-
gateway_request_id = event.get("requestContext", {}).get("requestId")
16-
headers = event.get("headers", {})
15+
gateway_request_id = (event.get("requestContext") or {}).get("requestId")
16+
headers = event.get("headers") or {}
1717
logger.info(
1818
"request trace metadata",
1919
extra={

src/eligibility_signposting_api/logging/logs_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
LOG_FORMAT = "%(asctime)s %(levelname)-8s %(name)s %(module)s.py:%(funcName)s():%(lineno)d %(message)s"
1515

1616

17-
def add_request_id_to_logs() -> Callable:
17+
def add_lambda_request_id_to_logger() -> Callable:
1818
def decorator(func: Callable) -> Callable:
1919
@wraps(func)
2020
def wrapper(event: LambdaEvent, context: LambdaContext) -> dict[str, Any] | None:
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from collections.abc import Callable
2+
from functools import wraps
3+
from typing import Any
4+
5+
from aws_xray_sdk.core import xray_recorder
6+
from mangum.types import LambdaContext, LambdaEvent
7+
8+
9+
def tracing_setup() -> Callable:
10+
def decorator(func: Callable) -> Callable:
11+
@wraps(func)
12+
def wrapper(event: LambdaEvent, context: LambdaContext) -> dict[str, Any] | None:
13+
xray_recorder.begin_subsegment("Lambda")
14+
try:
15+
return func(event, context)
16+
finally:
17+
xray_recorder.end_subsegment()
18+
19+
return wrapper
20+
21+
return decorator

0 commit comments

Comments
 (0)