Skip to content

Commit

Permalink
Add logfire.instrument_aws_lambda
Browse files Browse the repository at this point in the history
  • Loading branch information
Kludex committed Dec 10, 2024
1 parent 743fb5d commit 202a692
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 39 deletions.
36 changes: 36 additions & 0 deletions docs/integrations/aws-lambda.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# AWS Lambda

The [`logfire.instrument_aws_lambda`][logfire.Logfire.instrument_aws_lambda] function can be used to
instrument AWS Lambda functions to automatically send traces to **Logfire**.

## Installation

Install `logfire` with the `aws-lambda` extra:

{{ install_logfire(extras=['aws-lambda']) }}

## Usage

To instrument an AWS Lambda function, call the `logfire.instrument_aws_lambda` function after defining
the handler function:

```python
import logfire

logfire.configure() # (1)!


def handler(event, context):
return 'Hello from Lambda'

logfire.instrument_aws_lambda() # (2)!
```

1. Remember to set the `LOGFIRE_TOKEN` environment variable on your Lambda function configuration.
2. The `logfire.instrument_aws_lambda` function must be called after defining the handler function.
Otherwise, the handler function will not be instrumented.

[`logfire.instrument_aws_lambda`][logfire.Logfire.instrument_aws_lambda] uses the **OpenTelemetry AWS Lambda Instrumentation** package,
which you can find more information about [here][opentelemetry-aws-lambda].

[opentelemetry-aws-lambda]: https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/aws_lambda/aws_lambda.html
2 changes: 2 additions & 0 deletions logfire/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
instrument_aiohttp_client = DEFAULT_LOGFIRE_INSTANCE.instrument_aiohttp_client
instrument_sqlalchemy = DEFAULT_LOGFIRE_INSTANCE.instrument_sqlalchemy
instrument_sqlite3 = DEFAULT_LOGFIRE_INSTANCE.instrument_sqlite3
instrument_aws_lambda = DEFAULT_LOGFIRE_INSTANCE.instrument_aws_lambda
instrument_redis = DEFAULT_LOGFIRE_INSTANCE.instrument_redis
instrument_pymongo = DEFAULT_LOGFIRE_INSTANCE.instrument_pymongo
instrument_mysql = DEFAULT_LOGFIRE_INSTANCE.instrument_mysql
Expand Down Expand Up @@ -132,6 +133,7 @@ def loguru_handler() -> dict[str, Any]:
'instrument_aiohttp_client',
'instrument_sqlalchemy',
'instrument_sqlite3',
'instrument_aws_lambda',
'instrument_redis',
'instrument_pymongo',
'instrument_mysql',
Expand Down
36 changes: 36 additions & 0 deletions logfire/_internal/integrations/aws_lambda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from __future__ import annotations

from typing import TYPE_CHECKING

try:
from opentelemetry.context import Context
from opentelemetry.instrumentation.aws_lambda import AwsLambdaInstrumentor
from opentelemetry.metrics import MeterProvider
from opentelemetry.trace import TracerProvider
except ImportError:
raise RuntimeError(
'`logfire.instrument_aws_lambda()` requires the `opentelemetry-instrumentation-aws-lambda` package.\n'
'You can install this with:\n'
" pip install 'logfire[aws_lambda]'"
)

if TYPE_CHECKING:
from typing import Any, Callable, TypedDict, Unpack

LambdaEvent = Any

class AwsLambdaInstrumentKwargs(TypedDict):
skip_dep_check: bool
event_context_extractor: Callable[[LambdaEvent], Context]


def instrument_aws_lambda(
*, tracer_provider: TracerProvider, meter_provider: MeterProvider, **kwargs: Unpack[AwsLambdaInstrumentKwargs]
) -> None:
"""Instrument the AWS Lambda runtime so that spans are automatically created for each invocation.
See the `Logfire.instrument_aws_lambda` method for details.
"""
return AwsLambdaInstrumentor().instrument( # type: ignore[no-any-return]
tracer_provider=tracer_provider, meter_provider=meter_provider, **kwargs
)
21 changes: 20 additions & 1 deletion logfire/_internal/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@

from .integrations.asgi import ASGIApp, ASGIInstrumentKwargs
from .integrations.asyncpg import AsyncPGInstrumentKwargs
from .integrations.aws_lambda import AwsLambdaInstrumentKwargs
from .integrations.celery import CeleryInstrumentKwargs
from .integrations.flask import FlaskInstrumentKwargs
from .integrations.httpx import HTTPXInstrumentKwargs
Expand Down Expand Up @@ -1451,12 +1452,30 @@ def instrument_sqlite3(
},
)

def instrument_aws_lambda(self, **kwargs: Unpack[AwsLambdaInstrumentKwargs]) -> None:
"""Instrument AWS Lambda so that spans are automatically created for each invocation.
Uses the
[OpenTelemetry AWS Lambda Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/aws_lambda/aws_lambda.html)
library, specifically `AwsLambdaInstrumentor().instrument()`, to which it passes `**kwargs`.
"""
from .integrations.aws_lambda import instrument_aws_lambda

self._warn_if_not_initialized_for_instrumentation()
return instrument_aws_lambda(
**{ # type: ignore
'tracer_provider': self._config.get_tracer_provider(),
'meter_provider': self._config.get_meter_provider(),
**kwargs,
}
)

def instrument_pymongo(self, **kwargs: Unpack[PymongoInstrumentKwargs]) -> None:
"""Instrument the `pymongo` module so that spans are automatically created for each operation.
Uses the
[OpenTelemetry pymongo Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/pymongo/pymongo.html)
library, specifically `PymongoInstrumentor().instrument()`, to which it passes `**kwargs`.
library, specifically `PymongoInstrumentor().instrument()`, to which it passes `**kwargs`.
"""
from .integrations.pymongo import instrument_pymongo

Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ nav:
- Celery: integrations/celery.md
- Stripe: integrations/stripe.md
- System Metrics: integrations/system-metrics.md
- AWS Lambda: integrations/aws-lambda.md
- Custom:
- Pydantic: integrations/pydantic.md
- OpenAI: integrations/openai.md
Expand Down
43 changes: 24 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ redis = ["opentelemetry-instrumentation-redis >= 0.42b0"]
requests = ["opentelemetry-instrumentation-requests >= 0.42b0"]
mysql = ["opentelemetry-instrumentation-mysql >= 0.42b0"]
sqlite3 = ["opentelemetry-instrumentation-sqlite3 >= 0.42b0"]
aws-lambda = ["opentelemetry-instrumentation-aws-lambda >= 0.42b0"]

[project.scripts]
logfire = "logfire.cli:main"
Expand Down Expand Up @@ -106,25 +107,26 @@ dev = [
"pandas; python_version < '3.9'",
"attrs",
"openai",
"opentelemetry-instrumentation-aiohttp-client",
"opentelemetry-instrumentation-asgi",
"opentelemetry-instrumentation-wsgi",
"opentelemetry-instrumentation-fastapi",
"opentelemetry-instrumentation-starlette",
"opentelemetry-instrumentation-flask",
"opentelemetry-instrumentation-django",
"opentelemetry-instrumentation-httpx",
"opentelemetry-instrumentation-requests",
"opentelemetry-instrumentation-sqlalchemy",
"opentelemetry-instrumentation-system-metrics",
"opentelemetry-instrumentation-asyncpg",
"opentelemetry-instrumentation-psycopg",
"opentelemetry-instrumentation-psycopg2",
"opentelemetry-instrumentation-redis",
"opentelemetry-instrumentation-pymongo",
"opentelemetry-instrumentation-celery",
"opentelemetry-instrumentation-mysql",
"opentelemetry-instrumentation-sqlite3",
"opentelemetry-instrumentation-aiohttp-client>=0.42b0",
"opentelemetry-instrumentation-asgi>=0.42b0",
"opentelemetry-instrumentation-wsgi>=0.42b0",
"opentelemetry-instrumentation-fastapi>=0.42b0",
"opentelemetry-instrumentation-starlette>=0.42b0",
"opentelemetry-instrumentation-flask>=0.42b0",
"opentelemetry-instrumentation-django>=0.42b0",
"opentelemetry-instrumentation-httpx>=0.42b0",
"opentelemetry-instrumentation-requests>=0.42b0",
"opentelemetry-instrumentation-sqlalchemy>=0.42b0",
"opentelemetry-instrumentation-system-metrics>=0.42b0",
"opentelemetry-instrumentation-asyncpg>=0.42b0",
"opentelemetry-instrumentation-psycopg>=0.42b0",
"opentelemetry-instrumentation-psycopg2>=0.42b0",
"opentelemetry-instrumentation-redis>=0.42b0",
"opentelemetry-instrumentation-pymongo>=0.42b0",
"opentelemetry-instrumentation-celery>=0.42b0",
"opentelemetry-instrumentation-mysql>=0.42b0",
"opentelemetry-instrumentation-sqlite3>=0.42b0",
"opentelemetry-instrumentation-aws-lambda>=0.42b0",
"eval-type-backport",
"requests-mock",
"inline-snapshot",
Expand Down Expand Up @@ -170,6 +172,9 @@ docs = [
[tool.uv.sources]
logfire-api = { workspace = true }

[tool.uv]
default-groups = ["dev", "docs"]

[tool.uv.workspace]
members = ["logfire-api"]

Expand Down
70 changes: 51 additions & 19 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 202a692

Please sign in to comment.