Skip to content

Commit 20ca9fa

Browse files
author
あで
committed
Add exemplar support
1 parent 5a8a344 commit 20ca9fa

File tree

8 files changed

+612
-93
lines changed

8 files changed

+612
-93
lines changed

README.md

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
![GitHub_headerImage](https://user-images.githubusercontent.com/3262610/221191767-73b8a8d9-9f8b-440e-8ab6-75cb3c82f2bc.png)
22

3-
# autometrics-py
3+
[![Discord Shield](https://discordapp.com/api/guilds/950489382626951178/widget.png?style=shield)](https://discord.gg/kHtwcH8As9)
44

5-
A Python library that exports a decorator that makes it easy to understand the error rate, response time, and production usage of any function in your code. Jump straight from your IDE to live Prometheus charts for each HTTP/RPC handler, database method, or other piece of application logic.
5+
> A Python port of the Rust
6+
> [autometrics-rs](https://github.com/fiberplane/autometrics-rs) library
7+
8+
**Autometrics is a library that exports a decorator that makes it easy to understand the error rate, response time, and production usage of any function in your code.** Jump straight from your IDE to live Prometheus charts for each HTTP/RPC handler, database method, or other piece of application logic.
69

710
Autometrics for Python provides:
811

@@ -22,6 +25,7 @@ See [Why Autometrics?](https://github.com/autometrics-dev#why-autometrics) for m
2225
- [🚨 Define alerts](#alerts--slos) using SLO best practices directly in your source code
2326
- [📊 Grafana dashboards](#dashboards) work out of the box to visualize the performance of instrumented functions & SLOs
2427
- [⚙️ Configurable](#metrics-libraries) metric collection library (`opentelemetry`, `prometheus`, or `metrics`)
28+
- [📍 Attach exemplars](https://github.com/autometrics-dev/autometrics-py/blob/main/examples/starlette-otel-exemplars.py) to connect metrics with traces
2529
- ⚡ Minimal runtime overhead
2630

2731
## Using autometrics-py
@@ -130,6 +134,15 @@ The `version` is read from the `AUTOMETRICS_VERSION` environment variable, and t
130134

131135
This follows the method outlined in [Exposing the software version to Prometheus](https://www.robustperception.io/exposing-the-software-version-to-prometheus/).
132136

137+
## Exemplars
138+
139+
> **NOTE** - As of writing, aren't supported by the default tracker (`AUTOMETRICS_TRACKER=OPEN_TELEMETRY`).
140+
> You can track the progress of this feature here: https://github.com/open-telemetry/opentelemetry-python/issues/2407
141+
>
142+
> Because this feature is currently experimental, you have to explicitly enable it by setting the environment variables `AUTOMETRICS_EXEMPLARS=true` and `AUTOMETRICS_TRACKER=prometheus`. Prometheus also doesn't support exemplars in default configuration, to enable them you need to launch Prometheus with the `--enable-feature=exemplar-storage` flag.
143+
144+
Exemplars are a way to attach additional information to a metric. If you have OpenTelemetry instrumentation set up, autometrics will try to attach the trace ID and span ID to the metrics. This allows you to jump from a metric to the trace that caused it.
145+
133146
## Development of the package
134147

135148
This package uses [poetry](https://python-poetry.org) as a package manager, with all dependencies separated into three groups:

examples/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ You should be able to run each example by:
55
- cloning this repository
66
- run `poetry install --with examples`
77
- and execute `poetry run python examples/<example>.py` from the root of the repo.
8+
- for django and starlette examples, you can find the instructions in their respective READMEs
89

910
You can change the base url for Prometheus links via the `PROMETHEUS_URL` environment variable. So, if your local Prometheus were on a non-default port, like 9091, you would run:
1011

@@ -57,3 +58,17 @@ Autometrics also tracks a label, `caller`, which is the name of the function tha
5758
This is an example that shows you how to use autometrics to get metrics on http handlers with FastAPI. In this case, we're setting up the API ourselves, which means we need to expose a `/metrics` endpoint manually.
5859

5960
> Don't forget to configure Prometheus itself to scrape the metrics endpoint. Refer to the example `prometheus.yaml` file in the root of this project on how to set this up.
61+
62+
## `django-example`
63+
64+
This is a default Django project with autometrics configured. You can find examples of instrumenting function and class based views in `django_example/views`.
65+
66+
> Don't forget to configure Prometheus itself to scrape the metrics endpoint. Refer to the example `prometheus.yaml` file in the root of this project on how to set this up.
67+
68+
## `starlette-otel-exemplars.py`
69+
70+
This app shows how to use the OpenTelemetry integration to add exemplars to your metrics. In a distributed system, it allows you to track a request as it flows through your system by adding trace/span ids to it. We can catch these ids and expose them to Prometheus as exemplars. Do note that exemplars are an experimental feature and you need to enable it in Prometheus with a `--enable-feature=exemplar-storage` flag. Run the example with a command:
71+
72+
`AUTOMETRICS_TRACKER=prometheus AUTOMETRICS_EXEMPLARS=true uvicorn starlette-otel-exemplars:app --port 3000`
73+
74+
> Don't forget to configure Prometheus itself to scrape the metrics endpoint. Refer to the example `prometheus.yaml` file in the root of this project on how to set this up.

examples/starlette-otel-exemplars.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from opentelemetry import trace
2+
from autometrics import autometrics
3+
from prometheus_client import REGISTRY
4+
from prometheus_client.openmetrics.exposition import generate_latest
5+
from starlette import applications
6+
from starlette.responses import PlainTextResponse
7+
from starlette.routing import Route
8+
from opentelemetry import trace
9+
from opentelemetry.sdk.trace import TracerProvider
10+
from opentelemetry.sdk.trace.export import (
11+
BatchSpanProcessor,
12+
ConsoleSpanExporter,
13+
)
14+
15+
# Let's start by setting up the OpenTelemetry SDK with some defaults
16+
provider = TracerProvider()
17+
processor = BatchSpanProcessor(ConsoleSpanExporter())
18+
provider.add_span_processor(processor)
19+
trace.set_tracer_provider(provider)
20+
21+
# Now we can instrument our Starlette application
22+
tracer = trace.get_tracer(__name__)
23+
24+
25+
# We need to add tracer decorator before autometrics so that we see the spans
26+
@tracer.start_as_current_span("hello")
27+
@autometrics
28+
def hello(request):
29+
return PlainTextResponse("hello world")
30+
31+
32+
def metrics(request):
33+
# Exemplars are not supported by default prometheus format, so we specifically
34+
# make an endpoint that uses the OpenMetrics format that supoorts exemplars.
35+
body = generate_latest(REGISTRY)
36+
return PlainTextResponse(body, media_type="application/openmetrics-text")
37+
38+
39+
app = applications.Starlette(routes=[Route("/", hello), Route("/metrics", metrics)])
40+
41+
# Now, start the app (env variables are required to enable exemplars):
42+
# AUTOMETRICS_TRACKER=prometheus AUTOMETRICS_EXEMPLARS=true uvicorn starlette-otel-exemplars:app --port 3000
43+
# And make some requests to /. You should see the spans in the console.
44+
# You can hover over the hello handler and see the links to the metrics provided by autometrics.
45+
# If you open the queries in prometheus, you should see span and trace id exemplars added to metrics.

examples/starlette.sh

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AUTOMETRICS_TRACKER=prometheus AUTOMETRICS_EXEMPLARS=true uvicorn starlette-otel-exemplars:app --port 3000

0 commit comments

Comments
 (0)