-
Notifications
You must be signed in to change notification settings - Fork 429
feat: add tracer support for async, escape hatch, and patch given modules #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
5e2a022
feat: use new TraceProvider
heitorlessa 63a8ea9
improv: update tests
heitorlessa e3fddaf
improv: update docs, linting
heitorlessa 5ba54a8
improv: docstring readability and links
heitorlessa 0adc7a7
improv: remove tracer provider
heitorlessa 46a11a2
fix: patch modules type
heitorlessa c72e37c
improv: use client ctx_manager for race conditions
heitorlessa 022c373
improv: make disabling provider private again
heitorlessa e038a72
chore: linting
heitorlessa f585506
fix: race condition annotation/metadata
heitorlessa be69d4f
chore: linting
heitorlessa 9e99f8c
feat: add async support for methods
heitorlessa 9e7bd6d
improv: document async use cases, and edge cases
heitorlessa f79edff
improv: upgrade xray, flex pinning
heitorlessa 4b22f75
chore: linting
heitorlessa 44dbab6
improv: update example for async, escape hatch
heitorlessa 107f572
fix: add example dev deps in project
heitorlessa fbfc759
improv: add patch_modules example, formatting
heitorlessa b3447e3
improv: break down concurrent async calls example
heitorlessa c87bf62
docs: main doc clean up
heitorlessa e1b79ea
docs: document async, escape hatch usage
heitorlessa c58a4f1
chore: lint
heitorlessa c91fe32
docs: update example SAM template comments
heitorlessa 7f0c59c
chore: updates poetry lock file
heitorlessa 252e35b
improv: example to use py 3.8
heitorlessa adb244e
fix: AsyncMockMixin not being awaitable in 3.8
heitorlessa ea38254
fix: 3.8 defaulting to AsyncMock
heitorlessa b7507e4
improv: include x-ray bug for concurrent async calls
heitorlessa b8ed79f
fix: address nicolas's feedback
heitorlessa b767567
improv: add security baseline as part of PR process
heitorlessa 3ddcf16
improv: enforce lower code complexity
heitorlessa a5407d5
chore: whitespace
heitorlessa 7647193
improv: add complexity baseline
heitorlessa 238a401
chore: bump version to 0.9.0
heitorlessa 8fa07e6
chore: clean up history changes
heitorlessa ffe7c97
Merge branch 'develop' into improv/tracer
heitorlessa File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,22 @@ | ||
class MetricUnitError(Exception): | ||
"""When metric unit is not supported by CloudWatch""" | ||
|
||
pass | ||
|
||
|
||
class SchemaValidationError(Exception): | ||
"""When serialization fail schema validation""" | ||
|
||
pass | ||
|
||
|
||
class MetricValueError(Exception): | ||
"""When metric value isn't a valid number""" | ||
|
||
pass | ||
|
||
|
||
class UniqueNamespaceError(Exception): | ||
"""When an additional namespace is set""" | ||
|
||
pass |
2 changes: 2 additions & 0 deletions
2
python/aws_lambda_powertools/middleware_factory/exceptions.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
class MiddlewareInvalidArgumentError(Exception): | ||
"""When middleware receives non keyword=arguments""" | ||
|
||
pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
from __future__ import annotations | ||
|
||
import abc | ||
import logging | ||
from typing import Any, List | ||
|
||
import aws_xray_sdk | ||
import aws_xray_sdk.core | ||
|
||
is_cold_start = True | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class TracerProvider(metaclass=abc.ABCMeta): | ||
"""Tracer provider abstract class | ||
|
||
Providers should be initialized independently. This | ||
allows providers to control their config/initialization, | ||
and only pass a class instance to | ||
`aws_lambda_powertools.tracing.tracer.Tracer`. | ||
|
||
It also allows custom providers to keep lean while Tracer provide: | ||
|
||
* a simplified UX | ||
* decorators for Lambda handler and methods | ||
* auto-patching, patch all modules by default or a subset | ||
* disabling all tracing operations with a single parameter or env var | ||
|
||
Trace providers should implement the following methods: | ||
|
||
* **patch** | ||
* **create_subsegment** | ||
* **end_subsegment** | ||
* **put_metadata** | ||
* **put_annotation** | ||
* **disable_tracing_provider** | ||
heitorlessa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
These methods will be called by | ||
`aws_lambda_powertools.tracing.tracer.Tracer` - | ||
See `aws_lambda_powertools.tracing.base.XrayProvider` | ||
for a reference implementation. | ||
|
||
`aws_lambda_powertools.tracing.tracer.Tracer` decorators | ||
for Lambda and methods use the following provider methods: | ||
|
||
* create_subsegment | ||
* put_metadata | ||
* end_subsegment | ||
|
||
Example | ||
------- | ||
**Client using a custom tracing provider** | ||
|
||
from aws_lambda_powertools.tracing import Tracer | ||
... import ... ProviderX | ||
custom_provider = ProviderX() | ||
tracer = Tracer(service="greeting", provider=custom_provider) | ||
""" | ||
|
||
@abc.abstractmethod | ||
def patch(self, modules: List[str] = None): | ||
"""Patch modules for instrumentation | ||
|
||
If modules are None, it should patch | ||
all supported modules by the provider. | ||
|
||
Parameters | ||
---------- | ||
modules : List[str], optional | ||
List of modules to be pathced, by default None | ||
e.g. `['boto3', 'requests']` | ||
""" | ||
raise NotImplementedError | ||
|
||
@abc.abstractmethod | ||
def create_subsegment(self, name: str): | ||
"""Creates subsegment/span with a given name | ||
|
||
Parameters | ||
---------- | ||
name : str | ||
Subsegment/span name | ||
""" | ||
raise NotImplementedError | ||
|
||
@abc.abstractmethod | ||
def end_subsegment(self): | ||
"""Ends an existing subsegment""" | ||
raise NotImplementedError | ||
|
||
@abc.abstractmethod | ||
def put_metadata(self, key: str, value: Any, namespace: str = None): | ||
"""Adds metadata to existing segment/span or subsegment | ||
|
||
Parameters | ||
---------- | ||
key : str | ||
Metadata key | ||
value : Any | ||
Metadata value | ||
namespace : str, optional | ||
Metadata namespace, by default None | ||
""" | ||
raise NotImplementedError | ||
|
||
@abc.abstractmethod | ||
def put_annotation(self, key: str, value: Any): | ||
"""Adds annotation/label to existing segment/span or subsegment | ||
|
||
Parameters | ||
---------- | ||
key : str | ||
Annotation/label key | ||
value : Any | ||
Annotation/label value | ||
""" | ||
raise NotImplementedError | ||
|
||
@abc.abstractmethod | ||
def disable_tracing_provider(self): | ||
"""Forcefully disables tracing provider""" | ||
raise NotImplementedError | ||
|
||
|
||
class XrayProvider(TracerProvider): | ||
"""X-Ray Tracer provider | ||
|
||
It implements all basic ``aws_lambda_powertools.tracing.base.TracerProvider` methods, | ||
and automatically annotates cold start on first subsegment created. | ||
|
||
Parameters | ||
---------- | ||
client : aws_xray_sdk.core.xray_recorder | ||
X-Ray recorder client | ||
""" | ||
|
||
def __init__(self, client: aws_xray_sdk.core.xray_recorder = aws_xray_sdk.core.xray_recorder): | ||
self.client = client | ||
|
||
def create_subsegment(self, name: str) -> aws_xray_sdk.core.models.subsegment: | ||
"""Creates subsegment/span with a given name | ||
|
||
Parameters | ||
---------- | ||
name : str | ||
Subsegment name | ||
|
||
Example | ||
------- | ||
|
||
**Creates a subsegment** | ||
|
||
self.create_subsegment(name="a meaningful name") | ||
|
||
Returns | ||
------- | ||
aws_xray_sdk.core.models.subsegment | ||
AWS X-Ray Subsegment | ||
""" | ||
# Will no longer be needed once #155 is resolved | ||
# https://github.com/aws/aws-xray-sdk-python/issues/155 | ||
subsegment = self.client.begin_subsegment(name=name) | ||
global is_cold_start | ||
heitorlessa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if is_cold_start: | ||
logger.debug("Annotating cold start") | ||
subsegment.put_annotation(key="ColdStart", value=True) | ||
is_cold_start = False | ||
|
||
return subsegment | ||
|
||
def end_subsegment(self): | ||
"""Ends an existing subsegment""" | ||
self.client.end_subsegment() | ||
|
||
def put_annotation(self, key, value): | ||
"""Adds annotation to existing segment or subsegment | ||
|
||
Example | ||
------- | ||
Custom annotation for a pseudo service named payment | ||
|
||
tracer = Tracer(service="payment") | ||
tracer.put_annotation("PaymentStatus", "CONFIRMED") | ||
|
||
Parameters | ||
---------- | ||
key : str | ||
Annotation key (e.g. PaymentStatus) | ||
value : Any | ||
Value for annotation (e.g. "CONFIRMED") | ||
""" | ||
self.client.put_annotation(key=key, value=value) | ||
|
||
def put_metadata(self, key, value, namespace=None): | ||
"""Adds metadata to existing segment or subsegment | ||
|
||
Parameters | ||
---------- | ||
key : str | ||
Metadata key | ||
value : object | ||
Value for metadata | ||
namespace : str, optional | ||
Namespace that metadata will lie under, by default None | ||
|
||
Example | ||
------- | ||
Custom metadata for a pseudo service named payment | ||
|
||
tracer = Tracer(service="payment") | ||
response = collect_payment() | ||
tracer.put_metadata("Payment collection", response) | ||
""" | ||
self.client.put_metadata(key=key, value=value, namespace=namespace) | ||
|
||
def patch(self, modules: List[str] = None): | ||
"""Patch modules for instrumentation. | ||
|
||
Patches all supported modules by default if none are given. | ||
|
||
Parameters | ||
---------- | ||
modules : List[str] | ||
List of modules to be patched, optional by default | ||
""" | ||
if modules is None: | ||
aws_xray_sdk.core.patch_all() | ||
else: | ||
aws_xray_sdk.core.patch(modules) | ||
|
||
def disable_tracing_provider(self): | ||
"""Forcefully disables X-Ray tracing globally""" | ||
aws_xray_sdk.global_sdk_config.set_sdk_enabled(False) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class InvalidTracerProviderError(Exception): | ||
"""When given provider doesn't implement `aws_lambda_powertools.tracing.base.TracerProvider`""" | ||
|
||
pass | ||
|
||
|
||
class TracerProviderNotInitializedError(Exception): | ||
"""When given provider isn't initialized/bound""" | ||
|
||
pass |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.