Skip to content

Provide xray_recorder.capture() as context manager #77

Closed
@Dunedan

Description

@Dunedan

This is a feature request to be able to use the functionality of AWSXRayRecorder.capture() as context manager.
The motivation for that is to have something to replace begin_subsegment() and end_subsegment() calls with a context manager which does proper exception handling. That's especially important when using nested subsegments, as subsegment-traces in one "branch" below the current segment will only be streamed to X-Ray if all subsegments in that branch got closed properly. When doing no proper exception handling manually to ensure to close all subsegments that quickly leads to missing data in X-Ray. What contributes to that is that AWSXRayRecorder.end_subsegment() doesn't close a specific subsegment, but rather the current open one and because of that AWSXRayRecorder isn't able to notice if one got missed.

Currently one would have to do something like that for every subsegment:

def some_function():
    print("code without custom subsegment")
    subsegment = xray_recorder.begin_subsegment("my_subsegment")
    exception = None
    stack = None
    try:
        print("code to trace as custom subsegment")
    except Exception as exception:
        stack = traceback.extract_stack(limit=self.max_trace_back)
        raise
    finally:
        if subsegment is not None:
            if exception:
                subsegment.add_exception(exception, stack)
            xray_recorder.end_subsegment()

With capture() available as context manager that would be as simple as:

def some_function():
    print("code without custom subsegment")
    with xray_recorder.capture("my_subsegment"):
        print("code to trace as custom subsegment")

As a workaround we currently use the following custom context manager, but it would be nicer if AWSXRayRecorder.capture() would support it directly of course:

class XRayCaptureContextManager:
    def __init__(self, name):
        self.name = name
        self.subsegment = None

    def __enter__(self):
        self.subsegment = xray_recorder.begin_subsegment(self.name)

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.subsegment is not None:
            if exc_val:
                self.subsegment.add_exception(exc_val, traceback.extract_tb(exc_tb))
            xray_recorder.end_subsegment()

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions