Skip to content

Commit 8b9c05e

Browse files
author
あで
committed
Expose metrics and other improvements
1 parent 44ba726 commit 8b9c05e

18 files changed

+387
-294
lines changed

.github/workflows/main.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ jobs:
1313
strategy:
1414
matrix:
1515
python-version: ["3.8", "3.11", "pypy3.10"]
16+
env:
17+
FORCE_COLOR: 1
1618
steps:
1719
- uses: actions/checkout@v3
1820
- name: Install poetry
@@ -28,4 +30,4 @@ jobs:
2830
- name: Lint code
2931
run: poetry run pyright
3032
- name: Run tests
31-
run: poetry run pytest
33+
run: poetry run pytest -n auto

CHANGELOG.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1212

1313
### Added
1414

15-
-
15+
- Added the `start_http_server`, which starts a separate HTTP server to expose
16+
the metrics instead of using a separate endpoint in the existing server. (#77)
17+
- Added the `init` function that you can use to configure autometrics. (#77)
1618

1719
### Changed
1820

1921
- Renamed the `function.calls.count` metric to `function.calls` (which is exported
2022
to Prometheus as `function_calls_total`) to be in line with OpenTelemetry and
21-
OpenMetrics naming conventions. **Dashboards and alerting rules must be updated.**
23+
OpenMetrics naming conventions. **Dashboards and alerting rules must be updated.** (#74)
2224
- When the `function.calls.duration` histogram is exported to Prometheus, it now
2325
includes the units (`function_calls_duration_seconds`) to be in line with
24-
Prometheus/OpenMetrics naming conventions. **Dashboards and alerting rules must be updated.**
26+
Prometheus/OpenMetrics naming conventions. **Dashboards and alerting rules must be updated.** (#74)
2527
- The `caller` label on the `function.calls` metric was replaced with `caller.function`
26-
and `caller.module`
28+
and `caller.module` (#75)
2729
- All metrics now have a `service.name` label attached. This is set via runtime environment
28-
variable (`AUTOMETRICS_SERVICE_NAME` or `OTEL_SERVICE_NAME`), or falls back to the package name.
30+
variable (`AUTOMETRICS_SERVICE_NAME` or `OTEL_SERVICE_NAME`), or falls back to the package name. (#76)
2931

3032
### Deprecated
3133

README.md

+15-7
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ See [Why Autometrics?](https://github.com/autometrics-dev#why-autometrics) for m
2222
- 💡 Writes Prometheus queries so you can understand the data generated without
2323
knowing PromQL
2424
- 🔗 Create links to live Prometheus charts directly into each function's docstring
25-
- [🔍 Identify commits](#identifying-commits-that-introduced-problems) that introduced errors or increased latency
25+
- [🔍 Identify commits](#build-info) that introduced errors or increased latency
2626
- [🚨 Define alerts](#alerts--slos) using SLO best practices directly in your source code
2727
- [📊 Grafana dashboards](#dashboards) work out of the box to visualize the performance of instrumented functions & SLOs
28-
- [⚙️ Configurable](#metrics-libraries) metric collection library (`opentelemetry` or `prometheus`)
28+
- [⚙️ Configurable](#settings) metric collection library (`opentelemetry` or `prometheus`)
2929
- [📍 Attach exemplars](#exemplars) to connect metrics with traces
3030
- ⚡ Minimal runtime overhead
3131

@@ -89,14 +89,17 @@ def api_handler():
8989

9090
Autometrics keeps track of instrumented functions calling each other. If you have a function that calls another function, metrics for later will include `caller` label set to the name of the autometricised function that called it.
9191

92-
## Metrics Libraries
92+
## Settings
9393

94-
Configure the package that autometrics will use to produce metrics with the `AUTOMETRICS_TRACKER` environment variable.
94+
Autometrics makes use of a number of environment variables to configure its behavior. All of them are also configurable with keyword arguments to the `init` function.
9595

96-
- `opentelemetry` - Enabled by default, can also be explicitly set using the env var `AUTOMETRICS_TRACKER="OPEN_TELEMETERY"`. Look in `pyproject.toml` for the versions of the OpenTelemetry packages that will be used.
97-
- `prometheus` - Can be set using the env var `AUTOMETRICS_TRACKER="PROMETHEUS"`. Look in `pyproject.toml` for the version of the `prometheus-client` package that will be used.
96+
- `tracker` - Configure the package that autometrics will use to produce metrics. Default is `opentelemetry`, but you can also use `prometheus`. Look in `pyproject.toml` for the corresponding versions of packages that will be used.
97+
- `histogram_buckets` - Configure the buckets used for latency histograms. Default is `[0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0]`.
98+
- `enable_exemplars` - Enable [exemplar collection](#exemplars). Default is `False`.
99+
- `service_name` - Configure the [service name](#service-name).
100+
- `version`, `commit`, `branch` - Used to configure [build_info](#build-info).
98101

99-
## Identifying commits that introduced problems
102+
## Identifying commits that introduced problems <span name="build-info" />
100103

101104
> **NOTE** - As of writing, `build_info` will not work correctly when using the default tracker (`AUTOMETRICS_TRACKER=OPEN_TELEMETRY`).
102105
> This will be fixed once the following PR is merged on the opentelemetry-python project: https://github.com/open-telemetry/opentelemetry-python/pull/3306
@@ -126,6 +129,7 @@ The service name is loaded from the following environment variables, in this ord
126129

127130
1. `AUTOMETRICS_SERVICE_NAME` (at runtime)
128131
2. `OTEL_SERVICE_NAME` (at runtime)
132+
3. First part of `__package__` (at runtime)
129133

130134
## Exemplars
131135

@@ -137,6 +141,10 @@ Exemplars are a way to associate a metric sample to a trace by attaching `trace_
137141
To use exemplars, you need to first switch to a tracker that supports them by setting `AUTOMETRICS_TRACKER=prometheus` and enable
138142
exemplar collection by setting `AUTOMETRICS_EXEMPLARS=true`. You also need to enable exemplars in Prometheus by launching Prometheus with the `--enable-feature=exemplar-storage` flag.
139143

144+
## Exporting metrics
145+
146+
After collecting metrics with Autometrics, you need to export them to Prometheus. You can either add a separate route to your server and use the `generate_latest` function from the `prometheus_client` package, or you can use the `start_http_server` function from the same package to start a separate server that will expose the metrics. Autometrics also re-exports the `start_http_server` function with a preselected port 9464 for compatibility with other Autometrics packages.
147+
140148
## Development of the package
141149

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

examples/README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ This is a default Django project with autometrics configured. You can find examp
6969

7070
## `starlette-otel-exemplars.py`
7171

72-
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 from OpenTelemetry 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:
73-
74-
`AUTOMETRICS_TRACKER=prometheus AUTOMETRICS_EXEMPLARS=true uvicorn starlette-otel-exemplars:app --port 8080`
72+
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 from OpenTelemetry 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.
7573

7674
> 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/fastapi-example.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import asyncio
2-
from fastapi import FastAPI, Response
32
import uvicorn
3+
44
from autometrics import autometrics
5+
from fastapi import FastAPI, Response
56
from prometheus_client import generate_latest
67

78
app = FastAPI()

examples/starlette-otel-exemplars.py

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
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
1+
import uvicorn
2+
3+
from autometrics import autometrics, init
84
from opentelemetry import trace
95
from opentelemetry.sdk.trace import TracerProvider
106
from opentelemetry.sdk.trace.export import (
117
BatchSpanProcessor,
128
ConsoleSpanExporter,
139
)
10+
from prometheus_client import REGISTRY
11+
from prometheus_client.openmetrics.exposition import generate_latest
12+
from starlette import applications
13+
from starlette.responses import PlainTextResponse
14+
from starlette.routing import Route
1415

1516
# Let's start by setting up the OpenTelemetry SDK with some defaults
1617
provider = TracerProvider()
@@ -21,6 +22,10 @@
2122
# Now we can instrument our Starlette application
2223
tracer = trace.get_tracer(__name__)
2324

25+
# Exemplars support requires some additional configuration on autometrics,
26+
# so we need to initialize it with the proper settings
27+
init(tracker="prometheus", enable_exemplars=True)
28+
2429

2530
# We need to add tracer decorator before autometrics so that we see the spans
2631
@tracer.start_as_current_span("request")
@@ -39,7 +44,7 @@ def inner_function():
3944

4045
def metrics(request):
4146
# Exemplars are not supported by default prometheus format, so we specifically
42-
# make an endpoint that uses the OpenMetrics format that supoorts exemplars.
47+
# make an endpoint that uses the OpenMetrics format that supports exemplars.
4348
body = generate_latest(REGISTRY)
4449
return PlainTextResponse(body, media_type="application/openmetrics-text")
4550

@@ -48,9 +53,10 @@ def metrics(request):
4853
routes=[Route("/", outer_function), Route("/metrics", metrics)]
4954
)
5055

51-
# Now, start the app (env variables are required to enable exemplars):
52-
# AUTOMETRICS_TRACKER=prometheus AUTOMETRICS_EXEMPLARS=true uvicorn starlette-otel-exemplars:app --port 8080
53-
# And make some requests to /. You should see the spans in the console.
56+
if __name__ == "__main__":
57+
uvicorn.run(app, port=8080)
58+
59+
# Start the app and make some requests to http://127.0.0.1:8080/, you should see the spans in the console.
5460
# With autometrics extension installed, you can now hover over the hello handler
5561
# and see the charts and queries associated with them. Open one of the queries
5662
# in Prometheus and you should see exemplars added to the metrics. Don't forget

0 commit comments

Comments
 (0)