Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e44ac88
add opentelemetry-instrumentation-asyncpg dependency repo-wide
bisgaard-itis Jul 7, 2025
934fdde
add asyncpg instrumention in aiohttp case
bisgaard-itis Jul 7, 2025
eeb2b6e
clean up tracing tests
bisgaard-itis Jul 7, 2025
84b26fa
minor cleanup
bisgaard-itis Jul 7, 2025
fe380c6
add decorator to generate pyinstrument profile span
bisgaard-itis Jul 7, 2025
388728d
ensure entire profile is shown
bisgaard-itis Jul 7, 2025
08dbf7b
minor simplification
bisgaard-itis Jul 7, 2025
a5dbadc
experiment a bit with new function decorator
bisgaard-itis Jul 8, 2025
a8931d2
add test for handler decorator
bisgaard-itis Jul 8, 2025
01920eb
parametrize test to cover more cases
bisgaard-itis Jul 8, 2025
acb7a99
cleanup
bisgaard-itis Jul 8, 2025
51f810a
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 8, 2025
36718e6
remove comment
bisgaard-itis Jul 8, 2025
31546e4
remove decorator again
bisgaard-itis Jul 8, 2025
0560b2d
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 8, 2025
c464840
enable tracing on local deployment
bisgaard-itis Jul 8, 2025
acd8c13
add profile spans for debugging together with @pcrespov
bisgaard-itis Jul 8, 2025
0df115d
fix types
bisgaard-itis Jul 8, 2025
f6f82d4
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 9, 2025
9b41e2f
remove profile spans to see if they are causing tests to fail
bisgaard-itis Jul 9, 2025
48ff90a
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 9, 2025
78f2200
add tracing when testing storage
bisgaard-itis Jul 9, 2025
b128fe2
improve fixtures to mock tracing
bisgaard-itis Jul 9, 2025
44e7632
readd profile spans
bisgaard-itis Jul 9, 2025
d0e5b63
Merge branch 'master' into 8065-instrument-asyncpg
mrnicegyu11 Jul 9, 2025
121313f
Revert "readd profile spans"
bisgaard-itis Jul 9, 2025
99da31d
Merge branch '8065-instrument-asyncpg' of github.com:bisgaard-itis/os…
bisgaard-itis Jul 9, 2025
a3b8d6b
add profile span for @matusdrobuliak66
bisgaard-itis Jul 9, 2025
4197d4c
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 9, 2025
5650206
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 9, 2025
fbc0aee
add profile span to permissions endpoint
bisgaard-itis Jul 10, 2025
c04e853
Merge branch 'master' into 8065-instrument-asyncpg
bisgaard-itis Jul 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/aws-library/requirements/_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ opentelemetry-api==1.34.1
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-aio-pika
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-botocore
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-redis
Expand All @@ -160,12 +161,15 @@ opentelemetry-exporter-otlp-proto-http==1.34.1
opentelemetry-instrumentation==0.55b1
# via
# opentelemetry-instrumentation-aio-pika
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-botocore
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
opentelemetry-instrumentation-aio-pika==0.55b1
# via -r requirements/../../../packages/service-library/requirements/_base.in
opentelemetry-instrumentation-asyncpg==0.55b1
# via -r requirements/../../../packages/service-library/requirements/_base.in
opentelemetry-instrumentation-botocore==0.55b1
# via -r requirements/_base.in
opentelemetry-instrumentation-logging==0.55b1
Expand All @@ -189,6 +193,7 @@ opentelemetry-sdk==1.34.1
opentelemetry-semantic-conventions==0.55b1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-botocore
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
Expand Down
5 changes: 5 additions & 0 deletions packages/celery-library/requirements/_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ opentelemetry-api==1.34.1
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-aio-pika
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
Expand All @@ -150,11 +151,14 @@ opentelemetry-exporter-otlp-proto-http==1.34.1
opentelemetry-instrumentation==0.55b1
# via
# opentelemetry-instrumentation-aio-pika
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
opentelemetry-instrumentation-aio-pika==0.55b1
# via -r requirements/../../../packages/service-library/requirements/_base.in
opentelemetry-instrumentation-asyncpg==0.55b1
# via -r requirements/../../../packages/service-library/requirements/_base.in
opentelemetry-instrumentation-logging==0.55b1
# via -r requirements/../../../packages/service-library/requirements/_base.in
opentelemetry-instrumentation-redis==0.55b1
Expand All @@ -174,6 +178,7 @@ opentelemetry-sdk==1.34.1
opentelemetry-semantic-conventions==0.55b1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
# opentelemetry-sdk
Expand Down
23 changes: 0 additions & 23 deletions packages/notifications-library/requirements/_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ idna==3.10
# via
# email-validator
# yarl
importlib-metadata==8.5.0
# via opentelemetry-api
jinja2==3.1.5
# via
# -c requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
Expand Down Expand Up @@ -64,19 +62,6 @@ mdurl==0.1.2
# via markdown-it-py
multidict==6.1.0
# via yarl
opentelemetry-api==1.34.1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
# opentelemetry-semantic-conventions
opentelemetry-instrumentation==0.55b1
# via opentelemetry-instrumentation-asyncpg
opentelemetry-instrumentation-asyncpg==0.55b1
# via -r requirements/../../../packages/postgres-database/requirements/_base.in
opentelemetry-semantic-conventions==0.55b1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
orjson==3.10.15
# via
# -c requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
Expand All @@ -92,8 +77,6 @@ orjson==3.10.15
# -r requirements/../../../packages/models-library/requirements/_base.in
# -r requirements/../../../packages/postgres-database/requirements/../../../packages/common-library/requirements/_base.in
# -r requirements/../../../packages/settings-library/requirements/../../../packages/common-library/requirements/_base.in
packaging==24.2
# via opentelemetry-instrumentation
propcache==0.3.0
# via yarl
psycopg2-binary==2.9.10
Expand Down Expand Up @@ -187,15 +170,9 @@ types-python-dateutil==2.9.0.20241206
typing-extensions==4.14.1
# via
# alembic
# opentelemetry-api
# opentelemetry-semantic-conventions
# pydantic
# pydantic-core
# pydantic-extra-types
# typer
wrapt==1.17.2
# via opentelemetry-instrumentation
yarl==1.18.3
# via -r requirements/../../../packages/postgres-database/requirements/_base.in
zipp==3.21.0
# via importlib-metadata
1 change: 0 additions & 1 deletion packages/notifications-library/requirements/_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ mypy-extensions==1.1.0
# via mypy
packaging==24.2
# via
# -c requirements/_base.txt
# pytest
# pytest-sugar
pathspec==0.12.1
Expand Down
1 change: 0 additions & 1 deletion packages/notifications-library/requirements/_tools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ nodeenv==1.9.1
# via pre-commit
packaging==24.2
# via
# -c requirements/_base.txt
# -c requirements/_test.txt
# black
# build
Expand Down
1 change: 0 additions & 1 deletion packages/postgres-database/requirements/_base.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
--requirement ../../../packages/common-library/requirements/_base.in

alembic
opentelemetry-instrumentation-asyncpg
pydantic
sqlalchemy[postgresql_psycopg2binary,postgresql_asyncpg] # SEE extras in https://github.com/sqlalchemy/sqlalchemy/blob/main/setup.cfg#L43
yarl
23 changes: 0 additions & 23 deletions packages/postgres-database/requirements/_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ greenlet==3.1.1
# via sqlalchemy
idna==3.10
# via yarl
importlib-metadata==8.5.0
# via opentelemetry-api
mako==1.3.10
# via
# -c requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
Expand All @@ -19,26 +17,11 @@ markupsafe==3.0.2
# via mako
multidict==6.1.0
# via yarl
opentelemetry-api==1.34.1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
# opentelemetry-semantic-conventions
opentelemetry-instrumentation==0.55b1
# via opentelemetry-instrumentation-asyncpg
opentelemetry-instrumentation-asyncpg==0.55b1
# via -r requirements/_base.in
opentelemetry-semantic-conventions==0.55b1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
orjson==3.10.15
# via
# -c requirements/../../../packages/common-library/requirements/../../../requirements/constraints.txt
# -c requirements/../../../requirements/constraints.txt
# -r requirements/../../../packages/common-library/requirements/_base.in
packaging==24.2
# via opentelemetry-instrumentation
propcache==0.3.0
# via yarl
psycopg2-binary==2.9.10
Expand All @@ -63,14 +46,8 @@ sqlalchemy==1.4.54
typing-extensions==4.14.1
# via
# alembic
# opentelemetry-api
# opentelemetry-semantic-conventions
# pydantic
# pydantic-core
# pydantic-extra-types
wrapt==1.17.2
# via opentelemetry-instrumentation
yarl==1.18.3
# via -r requirements/_base.in
zipp==3.21.0
# via importlib-metadata
4 changes: 1 addition & 3 deletions packages/postgres-database/requirements/_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ mypy==1.16.1
mypy-extensions==1.1.0
# via mypy
packaging==24.2
# via
# -c requirements/_base.txt
# pytest
# via pytest
pathspec==0.12.1
# via mypy
pluggy==1.5.0
Expand Down
1 change: 0 additions & 1 deletion packages/postgres-database/requirements/_tools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ nodeenv==1.9.1
# via pre-commit
packaging==24.2
# via
# -c requirements/_base.txt
# -c requirements/_test.txt
# black
# build
Expand Down
1 change: 1 addition & 0 deletions packages/service-library/requirements/_base.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ faststream
opentelemetry-api
opentelemetry-exporter-otlp
opentelemetry-instrumentation-aio-pika
opentelemetry-instrumentation-asyncpg
opentelemetry-instrumentation-logging
opentelemetry-instrumentation-redis
opentelemetry-instrumentation-requests
Expand Down
5 changes: 5 additions & 0 deletions packages/service-library/requirements/_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ opentelemetry-api==1.34.1
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-aio-pika
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
Expand All @@ -116,11 +117,14 @@ opentelemetry-exporter-otlp-proto-http==1.34.1
opentelemetry-instrumentation==0.55b1
# via
# opentelemetry-instrumentation-aio-pika
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
opentelemetry-instrumentation-aio-pika==0.55b1
# via -r requirements/_base.in
opentelemetry-instrumentation-asyncpg==0.55b1
# via -r requirements/_base.in
opentelemetry-instrumentation-logging==0.55b1
# via -r requirements/_base.in
opentelemetry-instrumentation-redis==0.55b1
Expand All @@ -140,6 +144,7 @@ opentelemetry-sdk==1.34.1
opentelemetry-semantic-conventions==0.55b1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asyncpg
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
# opentelemetry-sdk
Expand Down
19 changes: 19 additions & 0 deletions packages/service-library/src/servicelib/aiohttp/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
HAS_AIOPG = True
except ImportError:
HAS_AIOPG = False
try:
from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor

HAS_ASYNCPG = True
except ImportError:
HAS_ASYNCPG = False

try:
from opentelemetry.instrumentation.requests import RequestsInstrumentor

Expand Down Expand Up @@ -130,6 +137,13 @@ def _startup(
msg="Attempting to add aio-pg opentelemetry autoinstrumentation...",
):
AiopgInstrumentor().instrument()
if HAS_ASYNCPG:
with log_context(
_logger,
logging.INFO,
msg="Attempting to add asyncpg opentelemetry autoinstrumentation...",
):
AsyncPGInstrumentor().instrument()
if HAS_BOTOCORE:
with log_context(
_logger,
Expand Down Expand Up @@ -180,6 +194,11 @@ def _shutdown() -> None:
AiopgInstrumentor().uninstrument()
except Exception: # pylint:disable=broad-exception-caught
_logger.exception("Failed to uninstrument AiopgInstrumentor")
if HAS_ASYNCPG:
try:
AsyncPGInstrumentor().uninstrument()
except Exception: # pylint:disable=broad-exception-caught
_logger.exception("Failed to uninstrument AsyncPGInstrumentor")
if HAS_BOTOCORE:
try:
BotocoreInstrumentor().uninstrument()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
_logger = logging.getLogger(__name__)

try:
from opentelemetry.instrumentation.asyncpg import ( # type: ignore[import-not-found]
from opentelemetry.instrumentation.asyncpg import (
AsyncPGInstrumentor,
)

Expand Down
48 changes: 46 additions & 2 deletions packages/service-library/src/servicelib/tracing.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from collections.abc import Callable, Coroutine
from contextlib import contextmanager
from contextvars import Token
from typing import TypeAlias
from functools import wraps
from typing import Any, Final, TypeAlias

import pyinstrument
import pyinstrument.renderers
from opentelemetry import context as otcontext
from opentelemetry import trace
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from settings_library.tracing import TracingSettings

TracingContext: TypeAlias = otcontext.Context | None

_OSPARC_TRACE_ID_HEADER = "x-osparc-trace-id"
_TRACER_NAME: Final[str] = "servicelib.tracing"
_PROFILE_ATTRIBUTE_NAME: Final[str] = "pyinstrument.profile"
_OSPARC_TRACE_ID_HEADER: Final[str] = "x-osparc-trace-id"


def _is_tracing() -> bool:
Expand Down Expand Up @@ -49,3 +55,41 @@ def get_trace_id_header() -> dict[str, str] | None:
) # Convert trace_id to 32-character hex string
return {_OSPARC_TRACE_ID_HEADER: trace_id_hex}
return None


def with_profiled_span(
func: Callable[..., Coroutine[Any, Any, Any]],
) -> Callable[..., Coroutine[Any, Any, Any]]:
"""Decorator that wraps an async function in an OpenTelemetry span with pyinstrument profiling."""

@wraps(func)
async def wrapper(*args: Any, **kwargs: Any) -> Any:
if not _is_tracing():
return await func(*args, **kwargs)

tracer = trace.get_tracer(_TRACER_NAME)
span_name = f"{func.__module__}.{func.__qualname__}"

with tracer.start_as_current_span(span_name) as span:
profiler = pyinstrument.Profiler(async_mode="enabled")
profiler.start()

try:
return await func(*args, **kwargs)

except Exception as e:
span.record_exception(e)
span.set_status(trace.Status(trace.StatusCode.ERROR, f"{e}"))
raise

finally:
profiler.stop()
renderer = pyinstrument.renderers.ConsoleRenderer(
unicode=True, color=False, show_all=True
)
span.set_attribute(
_PROFILE_ATTRIBUTE_NAME,
profiler.output(renderer=renderer),
)

return wrapper
Loading
Loading