Skip to main content

e-volv-logs

e-volv Log Manager SDK for Python — batched log shipping, trace context and error capture against the e-volv ingest endpoint (POST /api/public/v1/logs). Companion: the Node.js SDK @e-volv/logs.

Python 3.10+.

pip install e-volv-logs

Quick start

import e_volv_logs as evolve_logs
from e_volv_logs import init, log, span, trace

init(
    key="evk_…",  # project ingest key
    url="https://your-host/api/public/v1/logs",
    service="api",
    environment="production",
    release="1.4.2",
)

log.info("order created", {"orderId": "o_1", "total": 42.5})
log.error("payment failed", {"orderId": "o_1"})

try:
    await charge()
except Exception as err:
    log.exception(err, {"orderId": "o_1"})  # exception.type/message/stack

# Traces live in contextvars — they flow across await. httpx/requests
# requests made inside a trace get a W3C traceparent header automatically.
with trace():
    with span("db.query", {"table": "orders"}):
        await db.query("SELECT …")
    await httpx.get("https://internal/svc")  # traceparent injected

If key or url is missing, init() returns a no-op client and warns once. The SDK never raises into user code.

Batching, retries, drops

  • Flushes at 200 events, 2 s (age of the oldest buffered event), or a 512 KB payload — whichever comes first. Bodies are gzipped (Content-Encoding: gzip).
  • 429 retries with exponential backoff (0.5 s doubling, capped at 10 s), up to 3 attempts. 413 halves the batch and retries.
  • When the pending buffer exceeds 2× batch size, the oldest events are dropped; losses are visible on client.dropped.
  • atexit flushes whatever is pending.

Options

init(key=, url=, service=, environment=, release=, redact_keys=[...], sample_rate=1.0, capture_excepthook=True) — redact_keys are merged into the backstop regex password|secret|token|authorization|cookie|set-cookie|api[-_]?key (case-insensitive), applied to attrs before queueing.

stdlib logging

import logging
from e_volv_logs import init, LogHandler

init(key="evk_…", url="…", service="api")
logging.getLogger("myapp").addHandler(LogHandler())

Levels map to OTel severities (DEBUG→5, INFO→9, WARNING→13, ERROR→17, CRITICAL→21). extra={...} on the log call becomes event attrs; exc_info becomes exception.* fields. sys.excepthook capture is on by default.

FastAPI / Starlette

from e_volv_logs.integrations.fastapi import EvolveLogsMiddleware

app.add_middleware(EvolveLogsMiddleware)  # one root span per request

The middleware continues the trace when the inbound request carries an x-evolve-traceparent header (e-volv backend → evolve-ai propagation), otherwise starts a fresh root trace.

LangChain and LangGraph

pip install "e-volv-logs[langchain]"
from e_volv_logs.integrations.langchain import EvolveLogsCallbackHandler

result = graph.invoke(
    {"question": "…"},
    config={"callbacks": [EvolveLogsCallbackHandler()]},
)

One span per LangChain run, nested by parent_run_id, all sharing one trace — so a LangGraph node's tool calls and model calls appear inside the node on the e-volv trace graph. Span names:

Callback Span name
on_chain_start with langgraph_node graph.<node>
on_chain_start otherwise chain.<name>
on_tool_start tool.<name>
on_llm_start / on_chat_model_start llm.<model>

Errors end the span through _log_span_error (severity error, exception.* attrs), exactly like span() raised inside a body.

Queue hops

A span on the consumer side joins the producer's trace only if the traceparent travels with the job:

from e_volv_logs import run_with_traceparent, span, traceparent

# producer
queue.enqueue(work, payload, trace=traceparent())

# consumer: the body runs as a new hop of the producer's trace.
with run_with_traceparent(job.trace), span("queue.work", {"queue": "work"}):
    handle(job)

run_with_traceparent(header) parses a W3C traceparent; an absent or malformed header starts a fresh trace, so a producer that sends nothing still yields a trace of its own.

Feature flags (e-volv Launch)

Evaluate e-volv Launch flags locally, in-process, on the same key as telemetry — through the OpenFeature provider or directly:

pip install e-volv-openfeature   # OpenFeature provider
# or just e-volv-logs — flags are built in
from openfeature import api
from openfeature.evaluation_context import EvaluationContext

from e_volv_logs import init
from evolve_openfeature import EvolveProvider

client = init(key="evk_…", url="https://your-host/api/public/v1/logs")
api.set_provider(EvolveProvider(client.flags))

details = api.get_client().get_boolean_details(
    "checkout.new",
    False,
    EvaluationContext(targeting_key="u_1", attributes={"plan": "pro"}),
)

Directly on the client:

from e_volv_logs import FlagsOptions, init

client = init(key="evk_…", url="…", flags=FlagsOptions())

client.flags.bool("checkout.new", False, {"targetingKey": "u_1", "plan": "pro"})
client.flags.string("banner.copy", "Hello")
client.flags.number("limits.maxItems", 10)
client.flags.json("theme.config", {})
client.flags.detail("checkout.new", False, ctx)  # Evaluation(value, variant, reason)

client.flags.ready(timeout=5.0)  # the only call that waits
client.flags.on_change(lambda keys: ...)
client.flags.last_updated_at  # epoch seconds, None before the first payload
client.flags.verify()  # install check against GET /ping

Flag options (Python spellings of the Launch contract, §4):

FlagsOptions field Default Meaning
enabled True start the flags client
mode "stream" stream | poll | offline
poll_interval_seconds 30 poll period; minimum 15
cache temp dir last-known-payload dir; False disables
bootstrap none a bundled ruleset served before the first fetch
exposures_enabled True record exposures
exposures_sample_rate 1.0 probability an evaluation is recorded
exposures_dedupe_window_seconds 60 suppress repeats of the same subject/variant
exposures_send_attributes False send context attributes with exposures
private_attributes [] attribute names never sent anywhere

Guarantees (the e-volv Launch SDK contract):

  • Evaluation is synchronous, never raises, never performs I/O — every call answers from the last-held ruleset or your default.
  • Wrong type → your default with reason TYPE_MISMATCH.
  • Absent flag → your default with reason FLAG_NOT_FOUND.
  • The control plane unreachable → last held value; a cold start serves a valid cache file instantly while fetching in the background.
  • Server keys never send Origin or x-evolve-app-id; requests carry User-Agent: e-volv-logs-py/<version>.
  • Flag evaluation is byte-for-byte identical to every other e-volv SDK: the Python kernel is a port held to packages/flags-kernel/fixture.json.

Development

cd packages/logs-py
uv sync
uv run pytest tests/ -q

Metadata

Release files for e-volv-logs 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for e-volv-logs 0.2.0
File Size Uploaded
e_volv_logs-0.2.0.tar.gz 164.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for e-volv-logs 0.2.0
File Interpreter ABI Platform
e_volv_logs-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 203.2 kB

Release files / e_volv_logs-0.2.0.tar.gz

Download URL e_volv_logs-0.2.0.tar.gz
Size 164.2 kB
Tags Source
SHA-256 checksum
How to use checksums
07e16aec292a8bd067fb90398d96fa0940578456ab5d441e61acc5755329c836
BLAKE2b-256 checksum
How to use checksums
a28fde0c505769fb1476f9e232f4e4885cab60284b33e950c509ee4fa3104361
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / e_volv_logs-0.2.0-py3-none-any.whl

Download URL e_volv_logs-0.2.0-py3-none-any.whl
Size 39.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0396ea137586a8185d7c21c97336ef2aa5528fac6435ce4aac83e16f1d1587a
BLAKE2b-256 checksum
How to use checksums
2519569ecd21ba286164b5a2fab48755f8ec28c96d570822b82b870314702d15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page