diff --git a/README.md b/README.md index 54c7642..f1ac407 100644 --- a/README.md +++ b/README.md @@ -88,3 +88,24 @@ logger = logging.getLogger("my-logger") logger.addHandler(handler) logger.error(...) ``` + +If Multi-tenancy is enabled then you can use following configuration + + +```python +import logging.handlers +import logging_loki + +# Configuring the LokiQueueHandler with multi-tenancy enabled +handler = logging_loki.LokiHandler( + url="https://my-loki-instance/loki/api/v1/push", # Loki endpoint for log ingestion + tags={"application": "my-app"}, # Additional tags for log identification + auth=("username", "password"), # Authentication credentials for accessing Loki + version="1", # Version of the Loki API being used + tenant_id="som-tenant-id", # Unique identifier for the tenant +) + +logger = logging.getLogger("my-logger") +logger.addHandler(handler) +logger.error(...) +``` diff --git a/logging_loki/emitter.py b/logging_loki/emitter.py index 949ceea..ce3c249 100644 --- a/logging_loki/emitter.py +++ b/logging_loki/emitter.py @@ -30,7 +30,7 @@ class LokiEmitter(abc.ABC): label_replace_with = const.label_replace_with session_class = requests.Session - def __init__(self, url: str, tags: Optional[dict] = None, auth: BasicAuth = None): + def __init__(self, url: str, tags: Optional[dict] = None, auth: BasicAuth = None, tenant_id: Optional[str] = None): """ Create new Loki emitter. @@ -38,6 +38,7 @@ def __init__(self, url: str, tags: Optional[dict] = None, auth: BasicAuth = None url: Endpoint used to send log entries to Loki (e.g. `https://my-loki-instance/loki/api/v1/push`). tags: Default tags added to every log record. auth: Optional tuple with username and password for basic HTTP authentication. + tenant_id: Optional tenant_id for multi Multi-tenancy. """ #: Tags that will be added to all records handled by this handler. @@ -46,6 +47,8 @@ def __init__(self, url: str, tags: Optional[dict] = None, auth: BasicAuth = None self.url = url #: Optional tuple with username and password for basic authentication. self.auth = auth + #: Optional tenant_id for Multi-tenancy support. + self.tenant_id = tenant_id self._session: Optional[requests.Session] = None @@ -67,6 +70,8 @@ def session(self) -> requests.Session: if self._session is None: self._session = self.session_class() self._session.auth = self.auth or None + if self.tenant_id: + self._session.headers.update({"X-Scope-OrgID": self.tenant_id}) return self._session def close(self): diff --git a/logging_loki/handlers.py b/logging_loki/handlers.py index 74a55cb..a13d302 100644 --- a/logging_loki/handlers.py +++ b/logging_loki/handlers.py @@ -42,6 +42,7 @@ def __init__( tags: Optional[dict] = None, auth: Optional[emitter.BasicAuth] = None, version: Optional[str] = None, + tenant_id: Optional[str] = None, ): """ Create new Loki logging handler. @@ -67,7 +68,7 @@ def __init__( version = version or const.emitter_ver if version not in self.emitters: raise ValueError("Unknown emitter version: {0}".format(version)) - self.emitter = self.emitters[version](url, tags, auth) + self.emitter = self.emitters[version](url, tags, auth, tenant_id) def handleError(self, record): # noqa: N802 """Close emitter and let default handler take actions on error.""" diff --git a/setup.py b/setup.py index 153a2b5..cbbef55 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setuptools.setup( name="python-logging-loki", - version="0.3.1", + version="0.3.2", description="Python logging handler for Grafana Loki.", long_description=long_description, long_description_content_type="text/markdown",