Python

TracesMetricsApp LogsCustom LogsProfiling

1. Prerequisites

Before you instrument anything, make sure the basics are in place:

  • Python 3.9+ and pip 23.1.2+ – verify your versions:
    python3 --version
    pip --version
  • (Host mode only) If your app runs in a container, point it at the Host Agent using MW_AGENT_SERVICE.
    • Docker default bridge gateway: 172.17.0.1
    • Kubernetes service name: mw-service.mw-agent-ns.svc.cluster.local (discover with kubectl get service --all-namespaces | grep mw-service).

2. Install

Create an isolated environment, install the SDK, then add auto-instrumentation shims for your frameworks:

python -m venv .venv
source .venv/bin/activate

# SDK
pip install middleware-io

# (optional) enable continuous profiling features
pip install 'middleware-io[profiling]'

# Add OpenTelemetry auto-instrumentation libraries for installed packages (e.g., Flask)
middleware-bootstrap -a install

What middleware-bootstrap -a install does: it scans your active site-packages and installs the matching opentelemetry-instrumentation-* libraries for any frameworks you already have (e.g., Flask → opentelemetry-instrumentation-flask).

You can confirm with pip list | grep -i flask. For containers, add RUN middleware-bootstrap -a install to your Dockerfile.

3. Instrumentation

Pick Host (with the Middleware Host Agent) or Serverless (send directly to Middleware). Within each, choose Auto (zero-code) or Manual (call the tracker in code).

  • Auto instrumentation (zero-code) Use the CLI wrapper that the SDK installs; it starts your app with the correct instrumentation:
    export MW_SERVICE_NAME='MyPythonApp'
    middleware-run python app.py
    The SDK adds a middleware-run CLI to your venv; use it instead of raw commands like flask run so telemetry is captured. In Host mode, the OTLP target defaults to the local agent (http://localhost:9319).

Call mw_tracker(...) once at startup for more control (sampling, detectors, debug output, etc.):

from middleware import mw_tracker, MWOptions

mw_tracker(MWOptions(
  service_name="MyPythonApp",
  console_exporter=True,   # echo telemetry to stdout (dev only)
  log_level="DEBUG",
))

Run it with:

export MW_TRACKER=True
middleware-run python app.py

MW_TRACKER=True is required when you instrument using mw_tracker().

Set the tenant endpoint and API key, then start with the same runner:

export MW_API_KEY='<MW_API_KEY>'
export MW_TARGET='https://<MW_UID>.middleware.io:443'
export MW_SERVICE_NAME='MyPythonApp'
middleware-run python app.py

In serverless mode the app exports directly to Middleware, so both MW_API_KEY and MW_TARGET are required. (docs.middleware.io)

Supply the target and token via MWOptions:

from middleware import mw_tracker, MWOptions, DETECT_AWS_EC2

mw_tracker(MWOptions(
  access_token="<MW_API_KEY>",
  target="https://<MW_UID>.middleware.io:443",
  service_name="MyPythonApp",
  detectors=[DETECT_AWS_EC2],     # example
  otel_propagators="b3,tracecontext",
  console_exporter=True,
  log_level="DEBUG",
))

Run it with:

export MW_TRACKER=True
middleware-run python app.py

4. Advanced configuration (optional)

Two ways to set your service name:

export MW_SERVICE_NAME='MyPythonApp'

Or set service_name in MWOptions(...).

Enable continuous profiling:

pip install 'middleware-io[profiling]'
export MW_APM_COLLECT_PROFILING=True
# serverless requires MW_API_KEY + MW_TARGET as above

Pick the run command that matches your server/framework.

export DJANGO_SETTINGS_MODULE='mysite.settings'
middleware-run python manage.py runserver
export MW_API_KEY='<MW_API_KEY>'
export MW_TARGET='https://<MW_UID>.middleware.io:443'
export DJANGO_SETTINGS_MODULE='demo.settings'
middleware-run gunicorn -c conf/gunicorn.conf.py --workers=4 --bind 0.0.0.0:8000 --timeout 120 demo.wsgi
export MW_API_KEY='<MW_API_KEY>'
export MW_TARGET='https://<MW_UID>.middleware.io:443'
middleware-run uvicorn main:app --host localhost --port 5002

If you’re running in a container with Host mode, set MW_AGENT_SERVICE so your app can reach the Host Agent:

  • Docker default gateway: 172.17.0.1
  • Kubernetes service: mw-service.mw-agent-ns.svc.cluster.local

What “Zero-code” actually does: automatic patching via monkey-patching of popular libraries at runtime (e.g., Flask), driven by the instrumentation packages you installed with middleware-bootstrap.

5. Sending custom data

Create and use a meter to send custom metrics:

from opentelemetry.metrics import get_meter_provider

meter = get_meter_provider().get_meter("custom_meter")

request_counter = meter.create_counter(
  "request_counter", description="Counts the number of requests"
)

request_counter.add(1, {"endpoint": "/home"})

Create and use a tracer to send custom spans:

from opentelemetry.trace import get_tracer

tracer = get_tracer("custom_tracer")

with tracer.start_as_current_span("custom_span"):
  print("Doing some work within the span")

Use logging to emit logs. If your app already has a logger wrapper, add these calls there:

import logging

logging.info("info sample")
logging.warning("Sample Warning Log")
logging.error("Sample Error Log.", extra={"tester": "Alex"})

Attach attributes to spans (they become filter/group dimensions in Middleware):

from opentelemetry.trace import get_tracer

tracer = get_tracer("custom_tracer")

with tracer.start_as_current_span("span_with_attributes") as span:
  span.set_attribute("user.email", "[email protected]")
  span.set_attribute("user.id", 1234)

Record an exception and its stack trace:

from middleware import record_exception

try:
  print("Divide by zero:", 1 / 0)
except Exception as e:
  record_exception(e)

6. Environment variables

OTel env vars are supported and take the highest priority if present. Then Middleware env vars, then code options.

Config attributeEnvironment variable(s)Description/defaultExample
access_tokenMW_API_KEYAuth token (required for serverless/direct).xxxxxxxx…
service_nameMW_SERVICE_NAME, OTEL_SERVICE_NAMEService name shown in APM.payments-api
collect_tracesMW_APM_COLLECT_TRACESEnable traces (default true).true
collect_metricsMW_APM_COLLECT_METRICSEnable metrics (default true).true
collect_logsMW_APM_COLLECT_LOGSEnable logs (default true).true
collect_profilingMW_APM_COLLECT_PROFILINGEnable profiling (requires profiling extra).true
log_levelMW_LOG_LEVEL, OTEL_LOG_LEVELLogging level (default INFO).DEBUG
mw_agent_serviceMW_AGENT_SERVICEHost Agent address in containers.172.17.0.1 / mw-service.mw-agent-ns...
targetMW_TARGET, OTEL_EXPORTER_OTLP_ENDPOINTOTLP endpoint (Host default: http://localhost:9319).https://<MW_UID>.middleware.io:443
custom_resource_attributesMW_CUSTOM_RESOURCE_ATTRIBUTESComma-sep k=v list.call_id=123,region=us-east-1
otel_propagatorsMW_PROPAGATORS, OTEL_PROPAGATORSContext propagation (default b3).b3,tracecontext
console_exporterMW_CONSOLE_EXPORTEREcho telemetry to console (dev).true
debug_log_fileMW_DEBUG_LOG_FILELog telemetry to files (with console exporter).true
project_nameMW_PROJECT_NAMELogical app/project name.ShopApp
sample_rateMW_SAMPLE_RATE0..1 (AlwaysOn=1, AlwaysOff=0).0.5
detectorsMW_DETECTORSe.g., aws_lambda,gcp,azure,envvars.aws_lambda,gcp

7. View your data

After you start the app, give it 3–5 minutes, then open APM → Traces, Logs, and APM → Continuous Profiling in Middleware. See “Application Instrumentation” for where to find dashboards, trace viewer, Log Explorer, and Alerts.

8. Troubleshooting

  • No data (Host mode): Ensure you’re using middleware-run, the Host Agent is installed, and (in containers) MW_AGENT_SERVICE is set to the correct address/service.
  • No data (Serverless): Make sure both MW_API_KEY and MW_TARGET are exported before starting.
  • Instrumentation didn’t hook: Re-run middleware-bootstrap -a install after adding frameworks, and verify with pip list that opentelemetry-instrumentation-* packages exist.
  • Need to confirm register/init ran? Temporarily set MW_CONSOLE_EXPORTER=true (and MW_DEBUG_LOG_FILE=true) to echo spans/logs to stdout/files while you test.
  • Kubernetes reachability: find the service, then set MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local.

Use this option if you want upstream OpenTelemetry auto-instrumentation (opentelemetry-distro, opentelemetry-instrument) and OTLP export directly to Middleware.

Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.