Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions lite_bootstrap/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from lite_bootstrap.bootstrappers.fastapi_bootstrapper import (
FastAPIBootstrapper,
FastAPIHealthChecksInstrument,
FastAPILoggingInstrument,
FastAPIOpenTelemetryInstrument,
FastAPISentryInstrument,
)
from lite_bootstrap.bootstrappers.free_bootstrapper import FreeBootstrapper
from lite_bootstrap.bootstrappers.litestar_bootstrapper import (
LitestarBootstrapper,
LitestarHealthChecksInstrument,
LitestarLoggingInstrument,
LitestarOpenTelemetryInstrument,
LitestarSentryInstrument,
)
from lite_bootstrap.instruments.healthchecks_instrument import HealthChecksInstrument
from lite_bootstrap.instruments.logging_instrument import LoggingInstrument
from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument
from lite_bootstrap.instruments.sentry_instrument import SentryInstrument


__all__ = [
"FastAPIBootstrapper",
"FastAPIHealthChecksInstrument",
"FastAPILoggingInstrument",
"FastAPIOpenTelemetryInstrument",
"FastAPISentryInstrument",
"FreeBootstrapper",
"HealthChecksInstrument",
"LitestarBootstrapper",
"LitestarHealthChecksInstrument",
"LitestarLoggingInstrument",
"LitestarOpenTelemetryInstrument",
"LitestarSentryInstrument",
"LoggingInstrument",
"OpenTelemetryInstrument",
"SentryInstrument",
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@

from lite_bootstrap.instruments.base import BaseInstrument
from lite_bootstrap.service_config import ServiceConfig
from lite_bootstrap.types import ApplicationT
from lite_bootstrap.types import ApplicationT, BootstrapObjectT


class BaseBootstrap(abc.ABC, typing.Generic[ApplicationT]):
application: ApplicationT
class BaseBootstrapper(abc.ABC, typing.Generic[BootstrapObjectT, ApplicationT]):
bootstrap_object: BootstrapObjectT
instruments: typing.Sequence[BaseInstrument]
service_config: ServiceConfig

def bootstrap(self) -> None:
@abc.abstractmethod
def _prepare_application(self) -> ApplicationT: ...

def bootstrap(self) -> ApplicationT:
for one_instrument in self.instruments:
if one_instrument.is_ready(self.service_config):
one_instrument.bootstrap(self.service_config, self.application)
one_instrument.bootstrap(self.service_config, self.bootstrap_object)
return self._prepare_application()

def teardown(self) -> None:
for one_instrument in self.instruments:
if one_instrument.is_ready(self.service_config):
one_instrument.teardown(self.application)
one_instrument.teardown(self.bootstrap_object)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import dataclasses
import typing

from lite_bootstrap.bootstraps.base import BaseBootstrap
from lite_bootstrap.bootstrappers.base import BaseBootstrapper
from lite_bootstrap.instruments.healthchecks_instrument import HealthChecksInstrument, HealthCheckTypedDict
from lite_bootstrap.instruments.logging_instrument import LoggingInstrument
from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument
Expand Down Expand Up @@ -66,12 +66,15 @@ class FastAPISentryInstrument(SentryInstrument): ...


@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
class FastAPIBootstrap(BaseBootstrap[fastapi.FastAPI]):
application: fastapi.FastAPI
class FastAPIBootstrapper(BaseBootstrapper[fastapi.FastAPI, fastapi.FastAPI]):
bootstrap_object: fastapi.FastAPI
instruments: typing.Sequence[
FastAPIOpenTelemetryInstrument
| FastAPISentryInstrument
| FastAPIHealthChecksInstrument
| FastAPILoggingInstrument
]
service_config: ServiceConfig

def _prepare_application(self) -> fastapi.FastAPI:
return self.bootstrap_object
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import dataclasses
import typing

from lite_bootstrap.bootstraps.base import BaseBootstrap
from lite_bootstrap.bootstrappers.base import BaseBootstrapper
from lite_bootstrap.instruments.logging_instrument import LoggingInstrument
from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument
from lite_bootstrap.instruments.sentry_instrument import SentryInstrument
from lite_bootstrap.service_config import ServiceConfig


@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
class FreeBootstrap(BaseBootstrap[None]):
application: None = None
class FreeBootstrapper(BaseBootstrapper[None, None]):
bootstrap_object: None = None
instruments: typing.Sequence[OpenTelemetryInstrument | SentryInstrument | LoggingInstrument]
service_config: ServiceConfig

def _prepare_application(self) -> None:
return self.bootstrap_object
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import dataclasses
import typing

from lite_bootstrap.bootstraps.base import BaseBootstrap
from lite_bootstrap.bootstrappers.base import BaseBootstrapper
from lite_bootstrap.instruments.healthchecks_instrument import HealthChecksInstrument, HealthCheckTypedDict
from lite_bootstrap.instruments.logging_instrument import LoggingInstrument
from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument
Expand Down Expand Up @@ -64,12 +64,15 @@ class LitestarSentryInstrument(SentryInstrument): ...


@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
class LitestarBootstrap(BaseBootstrap[AppConfig]):
application: AppConfig
class LitestarBootstrapper(BaseBootstrapper[AppConfig, litestar.Litestar]):
bootstrap_object: AppConfig
instruments: typing.Sequence[
LitestarOpenTelemetryInstrument
| LitestarSentryInstrument
| LitestarHealthChecksInstrument
| LitestarLoggingInstrument
]
service_config: ServiceConfig

def _prepare_application(self) -> litestar.Litestar:
return litestar.Litestar.from_config(self.bootstrap_object)
6 changes: 3 additions & 3 deletions lite_bootstrap/instruments/base.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import abc

from lite_bootstrap.service_config import ServiceConfig
from lite_bootstrap.types import ApplicationT
from lite_bootstrap.types import BootstrapObjectT


class BaseInstrument(abc.ABC):
def bootstrap(self, service_config: ServiceConfig, application: ApplicationT | None = None) -> None: ... # noqa: B027
def bootstrap(self, service_config: ServiceConfig, bootstrap_object: BootstrapObjectT | None = None) -> None: ... # noqa: B027

def teardown(self, application: ApplicationT | None = None) -> None: ... # noqa: B027
def teardown(self, bootstrap_object: BootstrapObjectT | None = None) -> None: ... # noqa: B027

@abc.abstractmethod
def is_ready(self, service_config: ServiceConfig) -> bool: ...
6 changes: 3 additions & 3 deletions lite_bootstrap/instruments/logging_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from lite_bootstrap.instruments.base import BaseInstrument
from lite_bootstrap.service_config import ServiceConfig
from lite_bootstrap.types import ApplicationT
from lite_bootstrap.types import BootstrapObjectT


if typing.TYPE_CHECKING:
Expand Down Expand Up @@ -109,7 +109,7 @@ class LoggingInstrument(BaseInstrument):
def is_ready(self, service_config: ServiceConfig) -> bool:
return not service_config.service_debug

def bootstrap(self, _: ServiceConfig, __: ApplicationT | None = None) -> None:
def bootstrap(self, _: ServiceConfig, __: BootstrapObjectT | None = None) -> None:
for unset_handlers_logger in self.logging_unset_handlers:
logging.getLogger(unset_handlers_logger).handlers = []

Expand All @@ -129,5 +129,5 @@ def bootstrap(self, _: ServiceConfig, __: ApplicationT | None = None) -> None:
cache_logger_on_first_use=True,
)

def teardown(self, _: ApplicationT | None = None) -> None:
def teardown(self, _: BootstrapObjectT | None = None) -> None:
structlog.reset_defaults()
6 changes: 3 additions & 3 deletions lite_bootstrap/instruments/opentelemetry_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from lite_bootstrap.instruments.base import BaseInstrument
from lite_bootstrap.service_config import ServiceConfig
from lite_bootstrap.types import ApplicationT
from lite_bootstrap.types import BootstrapObjectT


with contextlib.suppress(ImportError):
Expand Down Expand Up @@ -35,7 +35,7 @@ class OpenTelemetryInstrument(BaseInstrument):
def is_ready(self, _: ServiceConfig) -> bool:
return bool(self.endpoint)

def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None) -> None:
def bootstrap(self, service_config: ServiceConfig, _: BootstrapObjectT | None = None) -> None:
attributes = {
resources.SERVICE_NAME: service_config.service_name,
resources.TELEMETRY_SDK_LANGUAGE: "python",
Expand Down Expand Up @@ -66,7 +66,7 @@ def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None
one_instrumentor.instrument(tracer_provider=tracer_provider)
set_tracer_provider(tracer_provider)

def teardown(self, _: ApplicationT | None = None) -> None:
def teardown(self, _: BootstrapObjectT | None = None) -> None:
for one_instrumentor in self.instrumentors:
if isinstance(one_instrumentor, InstrumentorWithParams):
one_instrumentor.instrumentor.uninstrument(**one_instrumentor.additional_params)
Expand Down
6 changes: 3 additions & 3 deletions lite_bootstrap/instruments/sentry_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from lite_bootstrap.instruments.base import BaseInstrument
from lite_bootstrap.service_config import ServiceConfig
from lite_bootstrap.types import ApplicationT
from lite_bootstrap.types import BootstrapObjectT


with contextlib.suppress(ImportError):
Expand All @@ -27,7 +27,7 @@ class SentryInstrument(BaseInstrument):
def is_ready(self, _: ServiceConfig) -> bool:
return bool(self.dsn)

def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None) -> None:
def bootstrap(self, service_config: ServiceConfig, _: BootstrapObjectT | None = None) -> None:
sentry_sdk.init(
dsn=self.dsn,
sample_rate=self.sample_rate,
Expand All @@ -42,4 +42,4 @@ def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None
tags: dict[str, str] = self.tags or {}
sentry_sdk.set_tags(tags)

def teardown(self, application: ApplicationT | None = None) -> None: ...
def teardown(self, bootstrap_object: BootstrapObjectT | None = None) -> None: ...
1 change: 1 addition & 0 deletions lite_bootstrap/types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import typing


BootstrapObjectT = typing.TypeVar("BootstrapObjectT", bound=typing.Any)
ApplicationT = typing.TypeVar("ApplicationT", bound=typing.Any)
12 changes: 6 additions & 6 deletions tests/test_fastapi_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from starlette import status
from starlette.testclient import TestClient

from lite_bootstrap.bootstraps.fastapi_bootstrap import (
FastAPIBootstrap,
from lite_bootstrap.bootstrappers.fastapi_bootstrapper import (
FastAPIBootstrapper,
FastAPIHealthChecksInstrument,
FastAPILoggingInstrument,
FastAPIOpenTelemetryInstrument,
Expand All @@ -19,8 +19,8 @@


def test_fastapi_bootstrap(fastapi_app: FastAPI, service_config: ServiceConfig) -> None:
fastapi_bootstrap = FastAPIBootstrap(
application=fastapi_app,
bootstrapper = FastAPIBootstrapper(
bootstrap_object=fastapi_app,
service_config=service_config,
instruments=[
FastAPIOpenTelemetryInstrument(
Expand All @@ -37,12 +37,12 @@ def test_fastapi_bootstrap(fastapi_app: FastAPI, service_config: ServiceConfig)
FastAPILoggingInstrument(logging_buffer_capacity=0),
],
)
fastapi_bootstrap.bootstrap()
bootstrapper.bootstrap()
logger.info("testing logging", key="value")

try:
response = TestClient(fastapi_app).get("/health/")
assert response.status_code == status.HTTP_200_OK
assert response.json() == {"health_status": True, "service_name": "microservice", "service_version": "2.0.0"}
finally:
fastapi_bootstrap.teardown()
bootstrapper.teardown()
11 changes: 7 additions & 4 deletions tests/test_free_bootstrap.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import structlog
from opentelemetry.sdk.trace.export import ConsoleSpanExporter

from lite_bootstrap.bootstraps.free_bootstrap import FreeBootstrap
from lite_bootstrap.bootstrappers.free_bootstrapper import FreeBootstrapper
from lite_bootstrap.instruments.logging_instrument import LoggingInstrument
from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument
from lite_bootstrap.instruments.sentry_instrument import SentryInstrument
Expand All @@ -13,7 +13,7 @@


def test_free_bootstrap(service_config: ServiceConfig) -> None:
free_bootstrap = FreeBootstrap(
bootstrapper = FreeBootstrapper(
service_config=service_config,
instruments=[
OpenTelemetryInstrument(
Expand All @@ -27,5 +27,8 @@ def test_free_bootstrap(service_config: ServiceConfig) -> None:
LoggingInstrument(logging_buffer_capacity=0),
],
)
free_bootstrap.bootstrap()
logger.info("testing logging", key="value")
bootstrapper.bootstrap()
try:
logger.info("testing logging", key="value")
finally:
bootstrapper.teardown()
14 changes: 6 additions & 8 deletions tests/test_litestar_bootstrap.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import litestar
import structlog
from litestar import status_codes
from litestar.config.app import AppConfig
from litestar.testing import TestClient
from opentelemetry.sdk.trace.export import ConsoleSpanExporter

from lite_bootstrap.bootstraps.litestar_bootstrap import (
LitestarBootstrap,
from lite_bootstrap.bootstrappers.litestar_bootstrapper import (
LitestarBootstrapper,
LitestarHealthChecksInstrument,
LitestarLoggingInstrument,
LitestarOpenTelemetryInstrument,
Expand All @@ -21,8 +20,8 @@

def test_litestar_bootstrap(service_config: ServiceConfig) -> None:
app_config = AppConfig()
litestar_bootstrap = LitestarBootstrap(
application=app_config,
bootstrapper = LitestarBootstrapper(
bootstrap_object=app_config,
service_config=service_config,
instruments=[
LitestarOpenTelemetryInstrument(
Expand All @@ -39,8 +38,7 @@ def test_litestar_bootstrap(service_config: ServiceConfig) -> None:
LitestarLoggingInstrument(logging_buffer_capacity=0),
],
)
litestar_bootstrap.bootstrap()
application = litestar.Litestar.from_config(app_config)
application = bootstrapper.bootstrap()
logger.info("testing logging", key="value")

try:
Expand All @@ -53,4 +51,4 @@ def test_litestar_bootstrap(service_config: ServiceConfig) -> None:
"service_version": "2.0.0",
}
finally:
litestar_bootstrap.teardown()
bootstrapper.teardown()