Skip to main content

wshtlib

Lightweight observability library for AWS Lambda and FastAPI. Zero external dependencies.

A focused alternative to aws-powertools — covers structured logging, CloudWatch metrics (EMF), request context propagation, and Lambda handler boilerplate. Nothing more.

Install

pip install wshtlib

FastAPI/Starlette middleware is optional:

pip install wshtlib[fastapi]

Usage

Lambda handler

Two decorators, one per invocation mode.

@bootstrapsynchronous invocations (API Gateway), where the return value is the response:

from wshtlib import bootstrap, get_logger

logger = get_logger("my-service")

@bootstrap
def handler(event, context):
    logger.info("invoked", path=event.get("path"))
    return {"statusCode": 200}

It handles:

  • Warming events ("source": "lambda-warming") — returns 200 early
  • Context init and structured log enrichment
  • Unhandled exceptions — logs error, returns 500

@workerasynchronous invocations (S3, EventBridge, SQS), where the return value is discarded:

from wshtlib import worker, get_logger

logger = get_logger("my-worker")

@worker
def handler(event, context):
    logger.info("processing", records=len(event["Records"]))

Same context init and structured error logging, but the exception is re-raised rather than swallowed — retries, on_failure destinations, the DLQ, and the Errors metric all depend on Lambda seeing the invocation fail. No warming-event handling.

Structured logging

from wshtlib import get_logger

logger = get_logger("my-service")
logger.info("user signed in", user_id="u_123", plan="pro")

Output is JSON to stdout, enriched with level, timestamp, service, location, runtime fields, and Lambda context on invocation.

CloudWatch metrics (EMF)

from wshtlib.metrics import metrics

metrics.count("OrderPlaced")
metrics.put("Duration", 142.5, unit="Milliseconds")
metrics.flush()

metrics is a module-level MetricsContext instance. For isolated contexts (e.g. per-request), instantiate MetricsContext() directly.

Namespace defaults to the METRICS_NAMESPACE env var, falling back to "Wholeshoot".

Request context

from wshtlib import get_context, set_user_id

set_user_id(claims["sub"])
ctx = get_context()  # {"trace_id": ..., "correlation_id": ..., "user_id": ...}

Context is stored in a ContextVar — safe for concurrent async handlers.

FastAPI middleware

from fastapi import FastAPI
from wshtlib.middleware import WshtlibMiddleware

app = FastAPI()
app.add_middleware(WshtlibMiddleware)

Initialises request context, logs method, path, status, duration_ms per request, and injects X-Trace-Id into the response.

Utilities

from wshtlib import require_env, require_https_url, require_secret

db_url = require_env("DATABASE_URL")          # raises RuntimeError if missing/empty
endpoint = require_https_url(require_env("API_URL"))  # raises ValueError if not https
api_key = require_secret("api/key")           # raises RuntimeError if missing/empty, cached

Environment variables

Variable Default Description
LOG_LEVEL INFO Logger level
METRICS_NAMESPACE Wholeshoot CloudWatch namespace
ENVIRONMENT Added as a metrics dimension if set

Development

uv sync --group dev
uv run pytest
uv run mypy wshtlib
uv run ruff check wshtlib

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wshtlib-0.2.0.tar.gz (44.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wshtlib-0.2.0-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file wshtlib-0.2.0.tar.gz.

File metadata

  • Download URL: wshtlib-0.2.0.tar.gz
  • Upload date:
  • Size: 44.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for wshtlib-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c6dbfe45ef056761bcdc264fe79cd7d5c1b8b25ddcd8443df1d8c0d0b0a29614
MD5 20066831cd172cd1042773ccee42a901
BLAKE2b-256 378302ca5239760b623bf4d0001271ea847ab6456d3de6dae723af19257f5558

See more details on using hashes here.

Provenance

The following attestation bundles were made for wshtlib-0.2.0.tar.gz:

Publisher: ci.yml on pjosols/wshtlib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wshtlib-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: wshtlib-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for wshtlib-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 15041f3a25dc9ac644f3ac846b7122e196182d04c4a25afa0c46041156040d09
MD5 1470a8f7512e3a6884df620153c80353
BLAKE2b-256 940a56cca20988b6b4c7010387644e614644e552329e45344db63953744587a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for wshtlib-0.2.0-py3-none-any.whl:

Publisher: ci.yml on pjosols/wshtlib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

This release

0.2.0 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page