microbootstrap 1.6.0__tar.gz → 1.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/PKG-INFO +4 -4
  2. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/README.md +3 -3
  3. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/bootstrappers/litestar.py +14 -14
  4. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/opentelemetry_instrument.py +26 -10
  5. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/pyproject.toml +1 -1
  6. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/pyproject.toml.orig +1 -1
  7. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/__init__.py +0 -0
  8. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/bootstrappers/__init__.py +0 -0
  9. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/bootstrappers/base.py +0 -0
  10. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/bootstrappers/fastapi.py +0 -0
  11. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/bootstrappers/fastmcp.py +0 -0
  12. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/bootstrappers/faststream.py +0 -0
  13. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/config/__init__.py +0 -0
  14. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/config/fastapi.py +0 -0
  15. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/config/fastmcp.py +0 -0
  16. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/config/faststream.py +0 -0
  17. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/config/litestar.py +0 -0
  18. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/console_writer.py +0 -0
  19. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/exceptions.py +0 -0
  20. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/granian_server.py +0 -0
  21. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/helpers.py +0 -0
  22. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/__init__.py +0 -0
  23. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/base.py +0 -0
  24. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/cors_instrument.py +0 -0
  25. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/health_checks_instrument.py +0 -0
  26. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/instrument_box.py +0 -0
  27. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/logging_instrument.py +0 -0
  28. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/openapi_security_schemes.py +0 -0
  29. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/openapi_version_docs.py +0 -0
  30. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/prometheus_instrument.py +0 -0
  31. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/pyroscope_instrument.py +0 -0
  32. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/sentry_instrument.py +0 -0
  33. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments/swagger_instrument.py +0 -0
  34. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/instruments_setupper.py +0 -0
  35. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/middlewares/__init__.py +0 -0
  36. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/middlewares/fastapi.py +0 -0
  37. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/middlewares/fastmcp.py +0 -0
  38. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/middlewares/faststream.py +0 -0
  39. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/middlewares/litestar.py +0 -0
  40. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/py.typed +0 -0
  41. {microbootstrap-1.6.0 → microbootstrap-1.6.1}/microbootstrap/settings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: microbootstrap
3
- Version: 1.6.0
3
+ Version: 1.6.1
4
4
  Summary: Package for bootstrapping new micro-services
5
5
  Keywords: python,microservice,bootstrap,opentelemetry,logging,error-tracing,litestar,fastapi,fastmcp,mcp
6
6
  Author: community-of-python
@@ -505,7 +505,7 @@ class YourSettings(BaseServiceSettings):
505
505
  opentelemetry_namespace: str | None = None
506
506
  opentelemetry_insecure: bool = True
507
507
  opentelemetry_instrumentors: list[OpenTelemetryInstrumentor] = []
508
- opentelemetry_exclude_urls: list[str] = []
508
+ opentelemetry_exclude_urls: list[str] = ["/metrics"]
509
509
  opentelemetry_baggage_span_attributes: dict[str, str] = {}
510
510
 
511
511
  ... # Other settings here
@@ -521,9 +521,9 @@ Parameters description:
521
521
  - `opentelemetry_insecure` - is opentelemetry connection secure.
522
522
  - `opentelemetry_container_name` - will be passed to the `Resource`.
523
523
  - `opentelemetry_instrumentors` - a list of extra instrumentors.
524
- - `opentelemetry_exclude_urls` - list of ignored urls.
524
+ - `opentelemetry_exclude_urls` - list of url regexes that produce no server spans (`["/metrics"]` by default). For Litestar they are combined with `OTEL_PYTHON_LITESTAR_EXCLUDED_URLS` (or `OTEL_PYTHON_EXCLUDED_URLS`).
525
525
  - `opentelemetry_log_traces` - traces will be logged to stdout.
526
- - `opentelemetry_generate_health_check_spans` - generate spans for health check handlers if `True`
526
+ - `opentelemetry_generate_health_check_spans` - generate spans for health check handlers if `True`; if `False`, `health_checks_path` is added to the excluded urls.
527
527
  - `opentelemetry_baggage_span_attributes` - maps allowed baggage keys to attributes added to local server and consumer spans.
528
528
 
529
529
  These settings are subsequently passed to [opentelemetry](https://opentelemetry.io/), finalizing your Opentelemetry integration.
@@ -440,7 +440,7 @@ class YourSettings(BaseServiceSettings):
440
440
  opentelemetry_namespace: str | None = None
441
441
  opentelemetry_insecure: bool = True
442
442
  opentelemetry_instrumentors: list[OpenTelemetryInstrumentor] = []
443
- opentelemetry_exclude_urls: list[str] = []
443
+ opentelemetry_exclude_urls: list[str] = ["/metrics"]
444
444
  opentelemetry_baggage_span_attributes: dict[str, str] = {}
445
445
 
446
446
  ... # Other settings here
@@ -456,9 +456,9 @@ Parameters description:
456
456
  - `opentelemetry_insecure` - is opentelemetry connection secure.
457
457
  - `opentelemetry_container_name` - will be passed to the `Resource`.
458
458
  - `opentelemetry_instrumentors` - a list of extra instrumentors.
459
- - `opentelemetry_exclude_urls` - list of ignored urls.
459
+ - `opentelemetry_exclude_urls` - list of url regexes that produce no server spans (`["/metrics"]` by default). For Litestar they are combined with `OTEL_PYTHON_LITESTAR_EXCLUDED_URLS` (or `OTEL_PYTHON_EXCLUDED_URLS`).
460
460
  - `opentelemetry_log_traces` - traces will be logged to stdout.
461
- - `opentelemetry_generate_health_check_spans` - generate spans for health check handlers if `True`
461
+ - `opentelemetry_generate_health_check_spans` - generate spans for health check handlers if `True`; if `False`, `health_checks_path` is added to the excluded urls.
462
462
  - `opentelemetry_baggage_span_attributes` - maps allowed baggage keys to attributes added to local server and consumer spans.
463
463
 
464
464
  These settings are subsequently passed to [opentelemetry](https://opentelemetry.io/), finalizing your Opentelemetry integration.
@@ -15,11 +15,12 @@ from litestar.openapi.plugins import SwaggerRenderPlugin
15
15
  from litestar.types.asgi_types import ASGIApp, Scope
16
16
  from litestar_offline_docs import generate_static_files_config
17
17
  from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
18
- from opentelemetry.util.http import get_excluded_urls
18
+ from opentelemetry.util.http import ExcludeList, get_excluded_urls
19
19
  from sentry_sdk.integrations.litestar import LitestarIntegration
20
20
 
21
21
  from microbootstrap.bootstrappers.base import ApplicationBootstrapper
22
22
  from microbootstrap.config.litestar import LitestarConfig
23
+ from microbootstrap.instruments import opentelemetry_instrument
23
24
  from microbootstrap.instruments.cors_instrument import CorsInstrument
24
25
  from microbootstrap.instruments.health_checks_instrument import (
25
26
  HealthChecksInstrument,
@@ -35,7 +36,6 @@ from microbootstrap.instruments.openapi_security_schemes import (
35
36
  serialize_security_schemes,
36
37
  )
37
38
  from microbootstrap.instruments.openapi_version_docs import SUPPORTED_HTTP_METHODS
38
- from microbootstrap.instruments.opentelemetry_instrument import OpentelemetryInstrument
39
39
  from microbootstrap.instruments.prometheus_instrument import (
40
40
  LitestarPrometheusConfig,
41
41
  PrometheusInstrument,
@@ -239,12 +239,6 @@ class LitestarCorsInstrument(CorsInstrument):
239
239
  LitestarBootstrapper.use_instrument()(PyroscopeInstrument)
240
240
 
241
241
 
242
- def build_span_name(method: str, route: str) -> str:
243
- if not route:
244
- return method
245
- return f"{method} {route}"
246
-
247
-
248
242
  def build_litestar_route_details_from_scope(
249
243
  scope: Scope,
250
244
  ) -> tuple[str, dict[str, str]]:
@@ -261,18 +255,23 @@ def build_litestar_route_details_from_scope(
261
255
  method: typing.Final = str(scope.get("method", "HTTP")).strip()
262
256
  if path_template is not None:
263
257
  path_template_stripped: typing.Final = path_template.strip()
264
- return build_span_name(method, path_template_stripped), {"http.route": path_template_stripped}
258
+ span_name: typing.Final = opentelemetry_instrument.build_span_name(method, path_template_stripped)
259
+ return span_name, {"http.route": path_template_stripped}
265
260
 
266
261
  path: typing.Final = scope.get("path")
267
262
  if path is not None:
268
263
  path_stripped: typing.Final = path.strip()
269
- return build_span_name(method, path_stripped), {"http.route": path_stripped}
264
+ return opentelemetry_instrument.build_span_name(method, path_stripped), {"http.route": path_stripped}
270
265
  return method, {}
271
266
 
272
267
 
273
268
  class LitestarOpenTelemetryInstrumentationMiddleware(ASGIMiddleware):
274
- def __init__(self, config: OpenTelemetryConfig) -> None:
269
+ def __init__(self, config: OpenTelemetryConfig, exclude_urls: typing.Sequence[str] = ()) -> None:
275
270
  self.config = config
271
+ self.excluded_urls = opentelemetry_instrument.CombinedExcludeList(
272
+ ExcludeList(exclude_urls),
273
+ get_excluded_urls(self.config.exclude_urls_env_key),
274
+ )
276
275
 
277
276
  def create_open_telemetry_middleware(self, app: ASGIApp) -> OpenTelemetryMiddleware:
278
277
  return OpenTelemetryMiddleware(
@@ -280,7 +279,7 @@ class LitestarOpenTelemetryInstrumentationMiddleware(ASGIMiddleware):
280
279
  client_request_hook=self.config.client_request_hook_handler,
281
280
  client_response_hook=self.config.client_response_hook_handler,
282
281
  default_span_details=build_litestar_route_details_from_scope,
283
- excluded_urls=get_excluded_urls(self.config.exclude_urls_env_key),
282
+ excluded_urls=self.excluded_urls,
284
283
  meter=self.config.meter,
285
284
  meter_provider=self.config.meter_provider,
286
285
  server_request_hook=self.config.server_request_hook_handler,
@@ -292,7 +291,7 @@ class LitestarOpenTelemetryInstrumentationMiddleware(ASGIMiddleware):
292
291
 
293
292
 
294
293
  @LitestarBootstrapper.use_instrument()
295
- class LitestarOpentelemetryInstrument(OpentelemetryInstrument):
294
+ class LitestarOpentelemetryInstrument(opentelemetry_instrument.OpentelemetryInstrument):
296
295
  def bootstrap_before(self) -> dict[str, typing.Any]:
297
296
  return {
298
297
  "middleware": [
@@ -300,7 +299,8 @@ class LitestarOpentelemetryInstrument(OpentelemetryInstrument):
300
299
  LitestarOpentelemetryConfig(
301
300
  tracer_provider=self.tracer_provider,
302
301
  middleware_class=LitestarOpenTelemetryInstrumentationMiddleware, # type: ignore[arg-type]
303
- )
302
+ ),
303
+ exclude_urls=self.define_exclude_urls(),
304
304
  )
305
305
  ]
306
306
  }
@@ -19,6 +19,7 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExport
19
19
  from opentelemetry.semconv.resource import ResourceAttributes
20
20
  from opentelemetry.trace import SpanKind, format_span_id, get_current_span, set_tracer_provider
21
21
  from opentelemetry.util._importlib_metadata import entry_points
22
+ from opentelemetry.util.http import ExcludeList
22
23
 
23
24
  from microbootstrap.instruments.base import BaseInstrumentConfig, Instrument
24
25
  from microbootstrap.instruments.sentry_instrument import snapshot_sentry_opentelemetry_baggage
@@ -70,6 +71,21 @@ def opentelemetry_baggage_scope(
70
71
  context.detach(token)
71
72
 
72
73
 
74
+ def build_span_name(method: str, route: str) -> str:
75
+ if not route:
76
+ return method
77
+ return f"{method} {route}"
78
+
79
+
80
+ class CombinedExcludeList(ExcludeList):
81
+ def __init__(self, *exclude_lists: ExcludeList) -> None:
82
+ super().__init__([])
83
+ self.exclude_lists = exclude_lists
84
+
85
+ def url_disabled(self, url: str) -> bool:
86
+ return any(one_exclude_list.url_disabled(url) for one_exclude_list in self.exclude_lists)
87
+
88
+
73
89
  @dataclasses.dataclass()
74
90
  class OpenTelemetryInstrumentor:
75
91
  instrumentor: BaseInstrumentor
@@ -167,6 +183,16 @@ class BaseOpentelemetryInstrument(Instrument[OpentelemetryConfigT]):
167
183
  LOGGER_OBJ.debug("Instrumenting failed", entry_point_name=entry_point.name)
168
184
  raise
169
185
 
186
+ def define_exclude_urls(self) -> list[str]:
187
+ exclude_urls: typing.Final = [*self.instrument_config.opentelemetry_exclude_urls]
188
+ if (
189
+ not self.instrument_config.opentelemetry_generate_health_check_spans
190
+ and self.instrument_config.health_checks_path
191
+ and self.instrument_config.health_checks_path not in exclude_urls
192
+ ):
193
+ exclude_urls.append(self.instrument_config.health_checks_path)
194
+ return exclude_urls
195
+
170
196
  def is_ready(self) -> bool:
171
197
  return (
172
198
  bool(self.instrument_config.opentelemetry_endpoint)
@@ -222,16 +248,6 @@ class BaseOpentelemetryInstrument(Instrument[OpentelemetryConfigT]):
222
248
 
223
249
 
224
250
  class OpentelemetryInstrument(BaseOpentelemetryInstrument[OpentelemetryConfig]):
225
- def define_exclude_urls(self) -> list[str]:
226
- exclude_urls: typing.Final = [*self.instrument_config.opentelemetry_exclude_urls]
227
- if (
228
- not self.instrument_config.opentelemetry_generate_health_check_spans
229
- and self.instrument_config.health_checks_path
230
- and self.instrument_config.health_checks_path not in exclude_urls
231
- ):
232
- exclude_urls.append(self.instrument_config.health_checks_path)
233
- return exclude_urls
234
-
235
251
  @classmethod
236
252
  def get_config_type(cls) -> type[OpentelemetryConfig]:
237
253
  return OpentelemetryConfig
@@ -58,7 +58,7 @@ dependencies = [
58
58
  "opentelemetry-instrumentation-asgi>=0.46b0",
59
59
  "orjson>=3.10.18",
60
60
  ]
61
- version = "1.6.0"
61
+ version = "1.6.1"
62
62
 
63
63
  [[project.authors]]
64
64
  name = "community-of-python"
@@ -58,7 +58,7 @@ dependencies = [
58
58
  "opentelemetry-instrumentation-asgi>=0.46b0",
59
59
  "orjson>=3.10.18",
60
60
  ]
61
- version = "1.6.0"
61
+ version = "1.6.1"
62
62
  authors = [{ name = "community-of-python" }]
63
63
 
64
64
  [project.optional-dependencies]