Skip to content

Commit 06e5b23

Browse files
authored
Merge pull request #9 from community-of-python/feature/make-docs-great-again
Start making some nice docs
2 parents 3554e8f + c74a4b5 commit 06e5b23

File tree

12 files changed

+525
-45
lines changed

12 files changed

+525
-45
lines changed

README.md

Lines changed: 462 additions & 17 deletions
Large diffs are not rendered by default.

microbootstrap/bootstrappers/base.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@
2323
class ApplicationBootstrapper(abc.ABC, typing.Generic[SettingsT, ApplicationT, DataclassT]):
2424
application_type: type[ApplicationT]
2525
application_config: DataclassT
26-
__instrument_box: InstrumentBox = InstrumentBox()
2726
console_writer: ConsoleWriter
27+
__instrument_box: InstrumentBox
2828

2929
def __init__(self, settings: SettingsT) -> None:
3030
self.settings = settings
3131
self.console_writer = ConsoleWriter(writer_enabled=settings.service_debug)
32+
33+
if not hasattr(self, "__instrument_box"):
34+
self.__instrument_box = InstrumentBox()
3235
self.__instrument_box.initialize(self.settings)
3336

3437
def configure_application(
@@ -45,22 +48,34 @@ def configure_instrument(
4548
self.__instrument_box.configure_instrument(instrument_config)
4649
return self
4750

51+
def configure_instruments(
52+
self: typing_extensions.Self,
53+
*instrument_configs: InstrumentConfigT,
54+
) -> typing_extensions.Self:
55+
for instrument_config in instrument_configs:
56+
self.configure_instrument(instrument_config)
57+
return self
58+
4859
@classmethod
4960
def use_instrument(
5061
cls,
5162
) -> typing.Callable[
5263
[type[Instrument[InstrumentConfigT]]],
5364
type[Instrument[InstrumentConfigT]],
5465
]:
66+
if not hasattr(cls, "__instrument_box"):
67+
cls.__instrument_box = InstrumentBox()
5568
return cls.__instrument_box.extend_instruments
5669

5770
def bootstrap(self: typing_extensions.Self) -> ApplicationT:
5871
resulting_application_config = dataclass_to_dict_no_defaults(self.application_config)
5972
for instrument in self.__instrument_box.instruments:
6073
if instrument.is_ready():
74+
instrument.bootstrap()
75+
6176
resulting_application_config = merge_dict_configs(
6277
resulting_application_config,
63-
instrument.bootstrap(),
78+
instrument.bootstrap_before(),
6479
)
6580
instrument.write_status(self.console_writer)
6681

microbootstrap/instruments/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def is_ready(self) -> bool:
3939
raise NotImplementedError
4040

4141
@abc.abstractmethod
42-
def bootstrap(self) -> dict[str, typing.Any]:
42+
def bootstrap(self) -> None:
4343
raise NotImplementedError
4444

4545
@abc.abstractmethod

microbootstrap/instruments/logging_instrument.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def is_ready(self) -> bool:
147147
def teardown(self) -> None:
148148
structlog.reset_defaults()
149149

150-
def bootstrap(self) -> dict[str, typing.Any]:
150+
def bootstrap(self) -> None:
151151
for unset_handlers_logger in self.instrument_config.logging_unset_handlers:
152152
logging.getLogger(unset_handlers_logger).handlers = []
153153

@@ -167,8 +167,6 @@ def bootstrap(self) -> dict[str, typing.Any]:
167167
cache_logger_on_first_use=True,
168168
)
169169

170-
return self.bootstrap_before()
171-
172170
@classmethod
173171
def get_config_type(cls) -> type[LoggingConfig]:
174172
return LoggingConfig

microbootstrap/instruments/opentelemetry_instrument.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class OpentelemetryConfig(BaseInstrumentConfig):
3131
opentelemetry_namespace: str | None = None
3232
opentelemetry_insecure: bool = pydantic.Field(default=True)
3333
opentelemetry_insrtumentors: list[OpenTelemetryInstrumentor] = pydantic.Field(default_factory=list)
34-
opentelemetry_exclude_urls: list[str] = pydantic.Field(default=["/health"])
34+
opentelemetry_exclude_urls: list[str] = pydantic.Field(default=[])
3535

3636

3737
class OpentelemetryInstrument(Instrument[OpentelemetryConfig]):
@@ -60,7 +60,7 @@ def teardown(self) -> None:
6060
for instrumentor_with_params in self.instrument_config.opentelemetry_insrtumentors:
6161
instrumentor_with_params.instrumentor.uninstrument(**instrumentor_with_params.additional_params)
6262

63-
def bootstrap(self) -> dict[str, typing.Any]:
63+
def bootstrap(self) -> None:
6464
resource: typing.Final = resources.Resource.create(
6565
attributes={
6666
resources.SERVICE_NAME: self.instrument_config.service_name,
@@ -85,7 +85,6 @@ def bootstrap(self) -> dict[str, typing.Any]:
8585
tracer_provider=self.tracer_provider,
8686
**opentelemetry_instrumentor.additional_params,
8787
)
88-
return self.bootstrap_before()
8988

9089
@classmethod
9190
def get_config_type(cls) -> type[OpentelemetryConfig]:

microbootstrap/instruments/prometheus_instrument.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def is_ready(self) -> bool:
3737
def teardown(self) -> None:
3838
return
3939

40-
def bootstrap(self) -> dict[str, typing.Any]:
41-
return self.bootstrap_before()
40+
def bootstrap(self) -> None:
41+
pass
4242

4343
@classmethod
4444
def get_config_type(cls) -> type[PrometheusConfig]:

microbootstrap/instruments/sentry_instrument.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def is_ready(self) -> bool:
4141
def teardown(self) -> None:
4242
return
4343

44-
def bootstrap(self) -> dict[str, typing.Any]:
44+
def bootstrap(self) -> None:
4545
sentry_sdk.init(
4646
dsn=self.instrument_config.sentry_dsn,
4747
sample_rate=self.instrument_config.sentry_sample_rate,
@@ -52,7 +52,6 @@ def bootstrap(self) -> dict[str, typing.Any]:
5252
integrations=self.instrument_config.sentry_integrations,
5353
**self.instrument_config.sentry_additional_params,
5454
)
55-
return self.bootstrap_before()
5655

5756
@classmethod
5857
def get_config_type(cls) -> type[SentryConfig]:

tests/bootstrappers/test_litestar.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ async def test_litestar_configure_instrument() -> None:
2727
assert response.status_code == status_codes.HTTP_200_OK
2828

2929

30+
async def test_litestar_configure_instruments() -> None:
31+
test_metrics_path: typing.Final = "/test-metrics-path"
32+
application: typing.Final = (
33+
LitestarBootstrapper(LitestarSettings())
34+
.configure_instruments(
35+
PrometheusConfig(prometheus_metrics_path=test_metrics_path),
36+
)
37+
.bootstrap()
38+
)
39+
40+
async with AsyncTestClient(app=application) as async_client:
41+
response: typing.Final = await async_client.get(test_metrics_path)
42+
assert response.status_code == status_codes.HTTP_200_OK
43+
44+
3045
async def test_litestar_configure_application_add_handler() -> None:
3146
test_handler_path: typing.Final = "/test-handler"
3247
test_response: typing.Final = {"hello": "world"}

tests/instruments/test_logging.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_logging_is_ready(minimum_logging_config: LoggingConfig, console_writer:
2323
def test_logging_bootstrap_is_not_ready(minimum_logging_config: LoggingConfig) -> None:
2424
minimum_logging_config.service_debug = True
2525
logging_instrument: typing.Final = LoggingInstrument(minimum_logging_config)
26-
assert logging_instrument.bootstrap() == {}
26+
assert logging_instrument.bootstrap_before() == {}
2727

2828

2929
def test_logging_bootstrap_after(
@@ -43,7 +43,8 @@ def test_logging_teardown(
4343

4444
def test_litestar_logging_bootstrap(minimum_logging_config: LoggingConfig) -> None:
4545
logging_instrument: typing.Final = LitestarLoggingInstrument(minimum_logging_config)
46-
bootsrap_result: typing.Final = logging_instrument.bootstrap()
46+
logging_instrument.bootstrap()
47+
bootsrap_result: typing.Final = logging_instrument.bootstrap_before()
4748
assert "middleware" in bootsrap_result
4849
assert isinstance(bootsrap_result["middleware"], list)
4950
assert len(bootsrap_result["middleware"]) == 1
@@ -56,9 +57,10 @@ async def test_litestar_logging_bootstrap_working(minimum_logging_config: Loggin
5657
async def error_handler() -> str:
5758
return "Ok"
5859

60+
logging_instrument.bootstrap()
5961
litestar_application: typing.Final = litestar.Litestar(
6062
route_handlers=[error_handler],
61-
**logging_instrument.bootstrap(),
63+
**logging_instrument.bootstrap_before(),
6264
)
6365

6466
async with AsyncTestClient(app=litestar_application) as async_client:
@@ -77,9 +79,10 @@ async def test_litestar_logging_bootstrap_tracer_injection(minimum_logging_confi
7779
async def error_handler() -> str:
7880
return "Ok"
7981

82+
logging_instrument.bootstrap()
8083
litestar_application: typing.Final = litestar.Litestar(
8184
route_handlers=[error_handler],
82-
**logging_instrument.bootstrap(),
85+
**logging_instrument.bootstrap_before(),
8386
)
8487
with tracer.start_as_current_span("my_fake_span") as span:
8588
# Do some fake work inside the span

tests/instruments/test_opentelemetry.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_opentelemetry_is_ready(
2424
def test_opentelemetry_bootstrap_is_not_ready(minimum_opentelemetry_config: OpentelemetryConfig) -> None:
2525
minimum_opentelemetry_config.service_name = ""
2626
opentelemetry_instrument: typing.Final = OpentelemetryInstrument(minimum_opentelemetry_config)
27-
assert opentelemetry_instrument.bootstrap() == {}
27+
assert not opentelemetry_instrument.is_ready()
2828

2929

3030
def test_opentelemetry_bootstrap_after(
@@ -49,7 +49,8 @@ def test_litestar_opentelemetry_bootstrap(
4949
minimum_opentelemetry_config.opentelemetry_insrtumentors = [magic_mock]
5050
opentelemetry_instrument: typing.Final = LitetstarOpentelemetryInstrument(minimum_opentelemetry_config)
5151

52-
opentelemetry_bootstrap_result: typing.Final = opentelemetry_instrument.bootstrap()
52+
opentelemetry_instrument.bootstrap()
53+
opentelemetry_bootstrap_result: typing.Final = opentelemetry_instrument.bootstrap_before()
5354

5455
assert opentelemetry_bootstrap_result
5556
assert "middleware" in opentelemetry_bootstrap_result
@@ -73,7 +74,8 @@ async def test_litestar_opentelemetry_bootstrap_working(
7374
async_mock: AsyncMock,
7475
) -> None:
7576
opentelemetry_instrument: typing.Final = LitetstarOpentelemetryInstrument(minimum_opentelemetry_config)
76-
opentelemetry_bootstrap_result: typing.Final = opentelemetry_instrument.bootstrap()
77+
opentelemetry_instrument.bootstrap()
78+
opentelemetry_bootstrap_result: typing.Final = opentelemetry_instrument.bootstrap_before()
7779

7880
opentelemetry_middleware = opentelemetry_bootstrap_result["middleware"][0]
7981
assert isinstance(opentelemetry_middleware, DefineMiddleware)

0 commit comments

Comments
 (0)