Skip to content

Commit 83a843b

Browse files
authored
Merge pull request #71 from modern-python/pyroscope
add pyroscope instrument
2 parents 8d04d4b + 4ed5375 commit 83a843b

18 files changed

Lines changed: 355 additions & 9 deletions

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Install via `pip install lite-bootstrap[<group>]` or `uv add lite-bootstrap[<gro
6161
| `litestar-all` | litestar + sentry + otl + logging |
6262
| `faststream-all` | faststream + sentry + otl + logging |
6363
| `free-all` | sentry + otl + logging |
64+
| `pyroscope` | pyroscope-io (add to any group) |
6465

6566
## Code style
6667

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ With `lite-bootstrap`, you receive an application with lightweight built-in supp
1111
- `sentry`
1212
- `prometheus`
1313
- `opentelemetry`
14+
- `pyroscope` - with OpenTelemetry trace-profile linking
1415
- `structlog`
1516
- `cors`
1617
- `swagger` - with additional offline version support

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ With `lite-bootstrap`, you receive an application with lightweight built-in supp
88
- `sentry`
99
- `prometheus`
1010
- `opentelemetry`
11+
- `pyroscope` - with OpenTelemetry trace-profile linking
1112
- `structlog`
1213
- `cors`
1314
- `swagger` - with additional offline version support

docs/introduction/configuration.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ For FastStream you must provide additionally:
8787
- `opentelemetry_middleware_cls`
8888

8989

90+
## Pyroscope
91+
92+
Pyroscope integration uses `pyroscope-io` package under the hood. Install it with the `pyroscope` extra, e.g. `lite-bootstrap[fastapi-all,pyroscope]`.
93+
94+
To bootstrap Pyroscope, you must provide at least:
95+
96+
- `pyroscope_endpoint` - the Pyroscope server address (e.g. `http://pyroscope:4040`).
97+
98+
Additional parameters:
99+
100+
- `pyroscope_sample_rate` - CPU profiling sample rate in Hz (default: `100`).
101+
- `pyroscope_tags` - key/value string pairs attached to all profiles.
102+
- `pyroscope_additional_params` - additional params passed directly to `pyroscope.configure`.
103+
104+
When OpenTelemetry is also enabled, a `PyroscopeSpanProcessor` is automatically added to the tracer provider. It tags root spans with a `pyroscope.profile.id` attribute and sets Pyroscope thread tags so that traces and profiles can be linked in the Grafana UI.
105+
90106
## Structlog
91107

92108
To bootstrap Structlog, you must set `service_debug` to False

docs/introduction/installation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ You can choose required framework and instruments using this table:
99
| sentry | `litestar-sentry` | `faststream-sentry` | `fastapi-sentry` | `sentry` |
1010
| prometheus | `litestar-metrics` | `faststream-metrics` | `fastapi-metrics` | not used |
1111
| opentelemetry | `litestar-otl` | `faststream-otl` | `fastapi-otl` | `otl` |
12+
| pyroscope | `pyroscope` | `pyroscope` | `pyroscope` | `pyroscope` |
1213
| structlog | `litestar-logging` | `faststream-logging` | `fastapi-logging` | `logging` |
1314
| cors | no extra | not used | no extra | not used |
1415
| swagger | no extra | not used | no extra | not used |

lite_bootstrap/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from lite_bootstrap.bootstrappers.faststream_bootstrapper import FastStreamBootstrapper, FastStreamConfig
33
from lite_bootstrap.bootstrappers.free_bootstrapper import FreeBootstrapper, FreeBootstrapperConfig
44
from lite_bootstrap.bootstrappers.litestar_bootstrapper import LitestarBootstrapper, LitestarConfig
5+
from lite_bootstrap.instruments.pyroscope_instrument import PyroscopeConfig, PyroscopeInstrument
56

67

78
__all__ = [
@@ -13,4 +14,6 @@
1314
"FreeBootstrapperConfig",
1415
"LitestarBootstrapper",
1516
"LitestarConfig",
17+
"PyroscopeConfig",
18+
"PyroscopeInstrument",
1619
]

lite_bootstrap/bootstrappers/fastapi_bootstrapper.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from lite_bootstrap.instruments.logging_instrument import LoggingConfig, LoggingInstrument
1616
from lite_bootstrap.instruments.opentelemetry_instrument import OpentelemetryConfig, OpenTelemetryInstrument
1717
from lite_bootstrap.instruments.prometheus_instrument import PrometheusConfig, PrometheusInstrument
18+
from lite_bootstrap.instruments.pyroscope_instrument import PyroscopeConfig, PyroscopeInstrument
1819
from lite_bootstrap.instruments.sentry_instrument import SentryConfig, SentryInstrument
1920
from lite_bootstrap.instruments.swagger_instrument import SwaggerConfig, SwaggerInstrument
2021

@@ -36,7 +37,14 @@
3637

3738
@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
3839
class FastAPIConfig(
39-
CorsConfig, HealthChecksConfig, LoggingConfig, OpentelemetryConfig, PrometheusConfig, SentryConfig, SwaggerConfig
40+
CorsConfig,
41+
HealthChecksConfig,
42+
LoggingConfig,
43+
OpentelemetryConfig,
44+
PrometheusConfig,
45+
PyroscopeConfig,
46+
SentryConfig,
47+
SwaggerConfig,
4048
):
4149
application: "fastapi.FastAPI" = dataclasses.field(default=None) # ty: ignore[invalid-assignment]
4250
application_kwargs: dict[str, typing.Any] = dataclasses.field(default_factory=dict)
@@ -174,6 +182,7 @@ class FastAPIBootstrapper(BaseBootstrapper["fastapi.FastAPI"]):
174182
instruments_types: typing.ClassVar = [
175183
FastAPICorsInstrument,
176184
FastAPIOpenTelemetryInstrument,
185+
PyroscopeInstrument,
177186
FastAPISentryInstrument,
178187
FastAPIHealthChecksInstrument,
179188
FastAPILoggingInstrument,

lite_bootstrap/bootstrappers/faststream_bootstrapper.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from lite_bootstrap.instruments.logging_instrument import LoggingConfig, LoggingInstrument
99
from lite_bootstrap.instruments.opentelemetry_instrument import OpentelemetryConfig, OpenTelemetryInstrument
1010
from lite_bootstrap.instruments.prometheus_instrument import PrometheusConfig, PrometheusInstrument
11+
from lite_bootstrap.instruments.pyroscope_instrument import PyroscopeConfig, PyroscopeInstrument
1112
from lite_bootstrap.instruments.sentry_instrument import SentryConfig, SentryInstrument
1213

1314

@@ -51,7 +52,9 @@ def __init__(
5152

5253

5354
@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
54-
class FastStreamConfig(HealthChecksConfig, LoggingConfig, OpentelemetryConfig, PrometheusConfig, SentryConfig):
55+
class FastStreamConfig(
56+
HealthChecksConfig, LoggingConfig, OpentelemetryConfig, PrometheusConfig, PyroscopeConfig, SentryConfig
57+
):
5558
application: "AsgiFastStream" = dataclasses.field(default_factory=AsgiFastStream)
5659
opentelemetry_middleware_cls: type[FastStreamTelemetryMiddlewareProtocol] | None = None
5760
prometheus_middleware_cls: type[FastStreamPrometheusMiddlewareProtocol] | None = None
@@ -152,6 +155,7 @@ class FastStreamBootstrapper(BaseBootstrapper["AsgiFastStream"]):
152155

153156
instruments_types: typing.ClassVar = [
154157
FastStreamOpenTelemetryInstrument,
158+
PyroscopeInstrument,
155159
FastStreamSentryInstrument,
156160
FastStreamHealthChecksInstrument,
157161
FastStreamLoggingInstrument,

lite_bootstrap/bootstrappers/free_bootstrapper.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
from lite_bootstrap.bootstrappers.base import BaseBootstrapper
55
from lite_bootstrap.instruments.logging_instrument import LoggingConfig, LoggingInstrument
66
from lite_bootstrap.instruments.opentelemetry_instrument import OpentelemetryConfig, OpenTelemetryInstrument
7+
from lite_bootstrap.instruments.pyroscope_instrument import PyroscopeConfig, PyroscopeInstrument
78
from lite_bootstrap.instruments.sentry_instrument import SentryConfig, SentryInstrument
89

910

1011
@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
11-
class FreeBootstrapperConfig(LoggingConfig, OpentelemetryConfig, SentryConfig): ...
12+
class FreeBootstrapperConfig(LoggingConfig, OpentelemetryConfig, PyroscopeConfig, SentryConfig): ...
1213

1314

1415
class FreeBootstrapper(BaseBootstrapper[None]):
@@ -18,6 +19,7 @@ class FreeBootstrapper(BaseBootstrapper[None]):
1819
LoggingInstrument,
1920
SentryInstrument,
2021
OpenTelemetryInstrument,
22+
PyroscopeInstrument,
2123
]
2224
bootstrap_config: FreeBootstrapperConfig
2325
not_ready_message = ""

lite_bootstrap/bootstrappers/litestar_bootstrapper.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from lite_bootstrap.instruments.prometheus_instrument import (
2020
PrometheusInstrument,
2121
)
22+
from lite_bootstrap.instruments.pyroscope_instrument import PyroscopeConfig, PyroscopeInstrument
2223
from lite_bootstrap.instruments.sentry_instrument import SentryConfig, SentryInstrument
2324
from lite_bootstrap.instruments.swagger_instrument import SwaggerConfig, SwaggerInstrument
2425

@@ -83,7 +84,7 @@ async def handle(
8384
default_span_details=build_litestar_route_details_from_scope,
8485
excluded_urls=self._excluded_urls,
8586
tracer_provider=self._tracer_provider,
86-
)(scope, receive, send) # ty: ignore
87+
)(scope, receive, send) # ty: ignore[invalid-argument-type]
8788

8889

8990
@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
@@ -93,6 +94,7 @@ class LitestarConfig(
9394
LoggingConfig,
9495
OpentelemetryConfig,
9596
PrometheusBootstrapperConfig,
97+
PyroscopeConfig,
9698
SentryConfig,
9799
SwaggerConfig,
98100
):
@@ -239,6 +241,7 @@ class LitestarBootstrapper(BaseBootstrapper["litestar.Litestar"]):
239241
instruments_types: typing.ClassVar = [
240242
LitestarCorsInstrument,
241243
LitestarOpenTelemetryInstrument,
244+
PyroscopeInstrument,
242245
LitestarSentryInstrument,
243246
LitestarHealthChecksInstrument,
244247
LitestarLoggingInstrument,

0 commit comments

Comments
 (0)