nexo-logging 0.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 hubagrayuda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexo-logging
3
+ Version: 0.0.1
4
+ Summary: Logging package for Nexo
5
+ Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
+ License: Proprietary
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: annotated-types>=0.7.0
11
+ Requires-Dist: black>=25.1.0
12
+ Requires-Dist: cachetools>=5.5.2
13
+ Requires-Dist: certifi>=2025.8.3
14
+ Requires-Dist: cfgv>=3.4.0
15
+ Requires-Dist: charset-normalizer>=3.4.3
16
+ Requires-Dist: click>=8.3.0
17
+ Requires-Dist: colorama>=0.4.6
18
+ Requires-Dist: distlib>=0.4.0
19
+ Requires-Dist: filelock>=3.19.1
20
+ Requires-Dist: google-api-core>=2.25.1
21
+ Requires-Dist: google-auth>=2.40.3
22
+ Requires-Dist: google-cloud-appengine-logging>=1.6.2
23
+ Requires-Dist: google-cloud-audit-log>=0.3.2
24
+ Requires-Dist: google-cloud-core>=2.4.3
25
+ Requires-Dist: google-cloud-logging>=3.12.1
26
+ Requires-Dist: googleapis-common-protos>=1.70.0
27
+ Requires-Dist: grpc-google-iam-v1>=0.14.2
28
+ Requires-Dist: grpcio>=1.75.0
29
+ Requires-Dist: grpcio-status>=1.75.0
30
+ Requires-Dist: identify>=2.6.14
31
+ Requires-Dist: idna>=3.10
32
+ Requires-Dist: importlib_metadata>=8.7.0
33
+ Requires-Dist: mypy_extensions>=1.1.0
34
+ Requires-Dist: nexo-types>=0.0.1
35
+ Requires-Dist: nodeenv>=1.9.1
36
+ Requires-Dist: opentelemetry-api>=1.37.0
37
+ Requires-Dist: packaging>=25.0
38
+ Requires-Dist: pathspec>=0.12.1
39
+ Requires-Dist: platformdirs>=4.4.0
40
+ Requires-Dist: pre_commit>=4.3.0
41
+ Requires-Dist: proto-plus>=1.26.1
42
+ Requires-Dist: protobuf>=6.32.1
43
+ Requires-Dist: pyasn1>=0.6.1
44
+ Requires-Dist: pyasn1_modules>=0.4.2
45
+ Requires-Dist: pydantic>=2.11.9
46
+ Requires-Dist: pydantic_core>=2.33.2
47
+ Requires-Dist: pytokens>=0.1.10
48
+ Requires-Dist: PyYAML>=6.0.2
49
+ Requires-Dist: requests>=2.32.5
50
+ Requires-Dist: rsa>=4.9.1
51
+ Requires-Dist: typing-inspection>=0.4.1
52
+ Requires-Dist: typing_extensions>=4.15.0
53
+ Requires-Dist: urllib3>=2.5.0
54
+ Requires-Dist: virtualenv>=20.34.0
55
+ Requires-Dist: zipp>=3.23.0
56
+ Dynamic: license-file
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexo-logging
3
+ Version: 0.0.1
4
+ Summary: Logging package for Nexo
5
+ Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
+ License: Proprietary
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: annotated-types>=0.7.0
11
+ Requires-Dist: black>=25.1.0
12
+ Requires-Dist: cachetools>=5.5.2
13
+ Requires-Dist: certifi>=2025.8.3
14
+ Requires-Dist: cfgv>=3.4.0
15
+ Requires-Dist: charset-normalizer>=3.4.3
16
+ Requires-Dist: click>=8.3.0
17
+ Requires-Dist: colorama>=0.4.6
18
+ Requires-Dist: distlib>=0.4.0
19
+ Requires-Dist: filelock>=3.19.1
20
+ Requires-Dist: google-api-core>=2.25.1
21
+ Requires-Dist: google-auth>=2.40.3
22
+ Requires-Dist: google-cloud-appengine-logging>=1.6.2
23
+ Requires-Dist: google-cloud-audit-log>=0.3.2
24
+ Requires-Dist: google-cloud-core>=2.4.3
25
+ Requires-Dist: google-cloud-logging>=3.12.1
26
+ Requires-Dist: googleapis-common-protos>=1.70.0
27
+ Requires-Dist: grpc-google-iam-v1>=0.14.2
28
+ Requires-Dist: grpcio>=1.75.0
29
+ Requires-Dist: grpcio-status>=1.75.0
30
+ Requires-Dist: identify>=2.6.14
31
+ Requires-Dist: idna>=3.10
32
+ Requires-Dist: importlib_metadata>=8.7.0
33
+ Requires-Dist: mypy_extensions>=1.1.0
34
+ Requires-Dist: nexo-types>=0.0.1
35
+ Requires-Dist: nodeenv>=1.9.1
36
+ Requires-Dist: opentelemetry-api>=1.37.0
37
+ Requires-Dist: packaging>=25.0
38
+ Requires-Dist: pathspec>=0.12.1
39
+ Requires-Dist: platformdirs>=4.4.0
40
+ Requires-Dist: pre_commit>=4.3.0
41
+ Requires-Dist: proto-plus>=1.26.1
42
+ Requires-Dist: protobuf>=6.32.1
43
+ Requires-Dist: pyasn1>=0.6.1
44
+ Requires-Dist: pyasn1_modules>=0.4.2
45
+ Requires-Dist: pydantic>=2.11.9
46
+ Requires-Dist: pydantic_core>=2.33.2
47
+ Requires-Dist: pytokens>=0.1.10
48
+ Requires-Dist: PyYAML>=6.0.2
49
+ Requires-Dist: requests>=2.32.5
50
+ Requires-Dist: rsa>=4.9.1
51
+ Requires-Dist: typing-inspection>=0.4.1
52
+ Requires-Dist: typing_extensions>=4.15.0
53
+ Requires-Dist: urllib3>=2.5.0
54
+ Requires-Dist: virtualenv>=20.34.0
55
+ Requires-Dist: zipp>=3.23.0
56
+ Dynamic: license-file
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ pyproject.toml
3
+ nexo_logging.egg-info/PKG-INFO
4
+ nexo_logging.egg-info/SOURCES.txt
5
+ nexo_logging.egg-info/dependency_links.txt
6
+ nexo_logging.egg-info/requires.txt
7
+ nexo_logging.egg-info/top_level.txt
8
+ src/__init__.py
9
+ src/config.py
10
+ src/enums.py
11
+ src/logger.py
@@ -0,0 +1,46 @@
1
+ annotated-types>=0.7.0
2
+ black>=25.1.0
3
+ cachetools>=5.5.2
4
+ certifi>=2025.8.3
5
+ cfgv>=3.4.0
6
+ charset-normalizer>=3.4.3
7
+ click>=8.3.0
8
+ colorama>=0.4.6
9
+ distlib>=0.4.0
10
+ filelock>=3.19.1
11
+ google-api-core>=2.25.1
12
+ google-auth>=2.40.3
13
+ google-cloud-appengine-logging>=1.6.2
14
+ google-cloud-audit-log>=0.3.2
15
+ google-cloud-core>=2.4.3
16
+ google-cloud-logging>=3.12.1
17
+ googleapis-common-protos>=1.70.0
18
+ grpc-google-iam-v1>=0.14.2
19
+ grpcio>=1.75.0
20
+ grpcio-status>=1.75.0
21
+ identify>=2.6.14
22
+ idna>=3.10
23
+ importlib_metadata>=8.7.0
24
+ mypy_extensions>=1.1.0
25
+ nexo-types>=0.0.1
26
+ nodeenv>=1.9.1
27
+ opentelemetry-api>=1.37.0
28
+ packaging>=25.0
29
+ pathspec>=0.12.1
30
+ platformdirs>=4.4.0
31
+ pre_commit>=4.3.0
32
+ proto-plus>=1.26.1
33
+ protobuf>=6.32.1
34
+ pyasn1>=0.6.1
35
+ pyasn1_modules>=0.4.2
36
+ pydantic>=2.11.9
37
+ pydantic_core>=2.33.2
38
+ pytokens>=0.1.10
39
+ PyYAML>=6.0.2
40
+ requests>=2.32.5
41
+ rsa>=4.9.1
42
+ typing-inspection>=0.4.1
43
+ typing_extensions>=4.15.0
44
+ urllib3>=2.5.0
45
+ virtualenv>=20.34.0
46
+ zipp>=3.23.0
@@ -0,0 +1,71 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nexo-logging"
7
+ version = "0.0.1"
8
+ description = "Logging package for Nexo"
9
+ authors = [
10
+ { name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
11
+ ]
12
+ license = { text = "Proprietary"}
13
+ readme = "README.md"
14
+ requires-python = ">=3.12"
15
+ dependencies = [
16
+ "annotated-types>=0.7.0",
17
+ "black>=25.1.0",
18
+ "cachetools>=5.5.2",
19
+ "certifi>=2025.8.3",
20
+ "cfgv>=3.4.0",
21
+ "charset-normalizer>=3.4.3",
22
+ "click>=8.3.0",
23
+ "colorama>=0.4.6",
24
+ "distlib>=0.4.0",
25
+ "filelock>=3.19.1",
26
+ "google-api-core>=2.25.1",
27
+ "google-auth>=2.40.3",
28
+ "google-cloud-appengine-logging>=1.6.2",
29
+ "google-cloud-audit-log>=0.3.2",
30
+ "google-cloud-core>=2.4.3",
31
+ "google-cloud-logging>=3.12.1",
32
+ "googleapis-common-protos>=1.70.0",
33
+ "grpc-google-iam-v1>=0.14.2",
34
+ "grpcio>=1.75.0",
35
+ "grpcio-status>=1.75.0",
36
+ "identify>=2.6.14",
37
+ "idna>=3.10",
38
+ "importlib_metadata>=8.7.0",
39
+ "mypy_extensions>=1.1.0",
40
+ "nexo-types>=0.0.1",
41
+ "nodeenv>=1.9.1",
42
+ "opentelemetry-api>=1.37.0",
43
+ "packaging>=25.0",
44
+ "pathspec>=0.12.1",
45
+ "platformdirs>=4.4.0",
46
+ "pre_commit>=4.3.0",
47
+ "proto-plus>=1.26.1",
48
+ "protobuf>=6.32.1",
49
+ "pyasn1>=0.6.1",
50
+ "pyasn1_modules>=0.4.2",
51
+ "pydantic>=2.11.9",
52
+ "pydantic_core>=2.33.2",
53
+ "pytokens>=0.1.10",
54
+ "PyYAML>=6.0.2",
55
+ "requests>=2.32.5",
56
+ "rsa>=4.9.1",
57
+ "typing-inspection>=0.4.1",
58
+ "typing_extensions>=4.15.0",
59
+ "urllib3>=2.5.0",
60
+ "virtualenv>=20.34.0",
61
+ "zipp>=3.23.0",
62
+ ]
63
+
64
+ [tool.setuptools]
65
+ packages = ["nexo.logging"]
66
+
67
+ [tool.setuptools.package-data]
68
+ "nexo.logging" = ["*.json", "*.yaml"]
69
+
70
+ [tool.setuptools.package-dir]
71
+ "nexo.logging" = "src"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,38 @@
1
+ from google.cloud.logging import Client
2
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
3
+ from typing import Self
4
+ from typing_extensions import Annotated
5
+ from nexo.types.dict import OptStrToStrDict
6
+ from nexo.types.string import OptStr
7
+ from .enums import Level
8
+
9
+
10
+ class LogConfig(BaseModel):
11
+ model_config = ConfigDict(arbitrary_types_allowed=True)
12
+
13
+ dir: Annotated[str, Field(..., description="Log's directory")]
14
+ level: Annotated[Level, Field(Level.INFO, description="Log's level")] = Level.INFO
15
+
16
+ google_cloud_logging: Annotated[
17
+ Client | None, Field(None, description="Google cloud logging")
18
+ ] = None
19
+
20
+ labels: Annotated[
21
+ OptStrToStrDict, Field(None, description="Log labels. (Optional)")
22
+ ] = None
23
+
24
+ aggregate_file_name: Annotated[
25
+ OptStr, Field(None, description="Log aggregate file name")
26
+ ] = None
27
+
28
+ individual_log: Annotated[
29
+ bool, Field(True, description="Whether to have individual log")
30
+ ] = True
31
+
32
+ @model_validator(mode="after")
33
+ def validate_aggregate_file_name(self) -> Self:
34
+ if isinstance(self.aggregate_file_name, str):
35
+ if not self.aggregate_file_name.endswith(".log"):
36
+ self.aggregate_file_name += ".log"
37
+
38
+ return self
@@ -0,0 +1,36 @@
1
+ import logging
2
+ from enum import IntEnum, StrEnum
3
+ from nexo.types.integer import ListOfInts
4
+ from nexo.types.string import ListOfStrs
5
+
6
+
7
+ class Level(IntEnum):
8
+ CRITICAL = logging.CRITICAL
9
+ FATAL = logging.FATAL
10
+ ERROR = logging.ERROR
11
+ WARNING = logging.WARNING
12
+ WARN = logging.WARN
13
+ INFO = logging.INFO
14
+ DEBUG = logging.DEBUG
15
+ NOTSET = logging.NOTSET
16
+
17
+ @classmethod
18
+ def choices(cls) -> ListOfInts:
19
+ return [e.value for e in cls]
20
+
21
+
22
+ class LoggerType(StrEnum):
23
+ BASE = "base"
24
+ APPLICATION = "application"
25
+ CACHE = "cache"
26
+ CLIENT = "client"
27
+ CONTROLLER = "controller"
28
+ DATABASE = "database"
29
+ EXCEPTION = "exception"
30
+ MIDDLEWARE = "middleware"
31
+ REPOSITORY = "repository"
32
+ SERVICE = "service"
33
+
34
+ @classmethod
35
+ def choices(cls) -> ListOfStrs:
36
+ return [e.value for e in cls]
@@ -0,0 +1,565 @@
1
+ import logging
2
+ import os
3
+ from datetime import datetime, timezone
4
+ from google.cloud.logging.handlers import CloudLoggingHandler
5
+ from pydantic import BaseModel, ConfigDict, Field
6
+ from typing import Generic, Literal, TypeVar, overload
7
+ from nexo.types.dict import StrToStrDict
8
+ from nexo.types.misc import StrOrStrEnum
9
+ from nexo.types.string import OptStr
10
+ from .config import LogConfig
11
+ from .enums import LoggerType
12
+
13
+
14
+ EnvironmentT = TypeVar("EnvironmentT", bound=StrOrStrEnum)
15
+ ServiceKeyT = TypeVar("ServiceKeyT", bound=StrOrStrEnum)
16
+
17
+
18
+ # * We suggest to NOT use this class
19
+ # * Instead use the inherited classes
20
+ class Base(
21
+ logging.Logger,
22
+ Generic[
23
+ EnvironmentT,
24
+ ServiceKeyT,
25
+ ],
26
+ ):
27
+ def __init__(
28
+ self,
29
+ type: LoggerType = LoggerType.BASE,
30
+ *,
31
+ environment: EnvironmentT | None = None,
32
+ service_key: ServiceKeyT | None = None,
33
+ client_key: OptStr = None,
34
+ config: LogConfig,
35
+ ):
36
+ self._type = type # Declare logger type
37
+
38
+ # Ensure environment exists
39
+ actual_environment = environment or os.getenv("ENVIRONMENT")
40
+ if actual_environment is None:
41
+ raise ValueError(
42
+ "ENVIRONMENT environment variable must be set if 'environment' is set to None"
43
+ )
44
+ else:
45
+ self._environment = actual_environment
46
+
47
+ # Ensure service_key exists
48
+ actual_service_key = service_key or os.getenv("SERVICE_KEY")
49
+ if actual_service_key is None:
50
+ raise ValueError(
51
+ "SERVICE_KEY environment variable must be set if 'service_key' is set to None"
52
+ )
53
+ else:
54
+ self._service_key = actual_service_key
55
+
56
+ self._client_key = client_key # Declare client key
57
+
58
+ # Ensure client_key is valid if logger type is a client
59
+ if self._type is LoggerType.CLIENT and self._client_key is None:
60
+ raise ValueError(
61
+ "'client_key' parameter must be provided if 'logger_type' is 'client'"
62
+ )
63
+
64
+ # Define logger name
65
+ base_name = f"{self._environment} - {self._service_key} - {self._type}"
66
+ if self._type is LoggerType.CLIENT:
67
+ self._name = f"{base_name} - {self._client_key}"
68
+ else:
69
+ self._name = base_name
70
+
71
+ # Define log labels
72
+ self._labels: StrToStrDict = {
73
+ "logger_type": self._type.value,
74
+ "service_environment": str(self._environment),
75
+ "service_key": str(self._service_key),
76
+ }
77
+ if client_key is not None:
78
+ self._labels["client_key"] = client_key
79
+ if config.labels is not None:
80
+ self._labels.update(config.labels)
81
+
82
+ self._config = config
83
+
84
+ super().__init__(self._name, self._config.level) # Init the superclass's logger
85
+
86
+ # Clear existing handlers to prevent duplicates
87
+ for handler in list(self.handlers):
88
+ self.removeHandler(handler)
89
+ handler.close()
90
+
91
+ # Console handler
92
+ console_handler = logging.StreamHandler()
93
+ console_handler.setFormatter(
94
+ logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
95
+ )
96
+ self.addHandler(console_handler)
97
+
98
+ # Google Cloud Logging handler (If enabled)
99
+ if self._config.google_cloud_logging is not None:
100
+ self._cloud_logging_handler = CloudLoggingHandler(
101
+ self._config.google_cloud_logging,
102
+ name=self._name.replace(" ", ""),
103
+ labels=self._labels,
104
+ )
105
+ self.addHandler(self._cloud_logging_handler)
106
+ else:
107
+ self.warning(
108
+ "Cloud logging is not configured. Will not add cloud logging handler"
109
+ )
110
+
111
+ # Define aggregate log directory
112
+ if self._config.aggregate_file_name is not None:
113
+ self._aggregate_log_dir = os.path.join(self._config.dir, "aggregate")
114
+ os.makedirs(self._aggregate_log_dir, exist_ok=True)
115
+ if not self._config.aggregate_file_name.endswith(".log"):
116
+ self._config.aggregate_file_name += ".log"
117
+ log_filename = os.path.join(
118
+ self._aggregate_log_dir, self._config.aggregate_file_name
119
+ )
120
+
121
+ # File handler
122
+ file_handler = logging.FileHandler(log_filename, mode="a")
123
+ file_handler.setFormatter(
124
+ logging.Formatter(
125
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
126
+ )
127
+ )
128
+ self.addHandler(file_handler)
129
+
130
+ # Define individual log directory
131
+ if self._config.individual_log:
132
+ self._individual_log_dir = os.path.join(self._config.dir, self._type)
133
+ if self._type is LoggerType.CLIENT:
134
+ if self._client_key is None:
135
+ raise ValueError(
136
+ "'client_key' parameter must be provided if 'logger_type' is 'client'"
137
+ )
138
+ self._individual_log_dir = os.path.join(
139
+ self._individual_log_dir, self._client_key
140
+ )
141
+ os.makedirs(self._individual_log_dir, exist_ok=True)
142
+
143
+ # Generate timestamped filename
144
+ log_filename = os.path.join(
145
+ self._individual_log_dir,
146
+ f"{datetime.now(tz=timezone.utc).isoformat(timespec="seconds")}.log",
147
+ )
148
+
149
+ # File handler
150
+ file_handler = logging.FileHandler(log_filename, mode="a")
151
+ file_handler.setFormatter(
152
+ logging.Formatter(
153
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
154
+ )
155
+ )
156
+ self.addHandler(file_handler)
157
+
158
+ logging.Logger.manager.loggerDict[self._name] = self
159
+
160
+ def dispose(self):
161
+ """Dispose of the logger by removing all handlers."""
162
+ for handler in list(self.handlers):
163
+ self.removeHandler(handler)
164
+ handler.close()
165
+ self.handlers.clear()
166
+
167
+
168
+ class Application(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
169
+ def __init__(
170
+ self,
171
+ *,
172
+ environment: EnvironmentT | None = None,
173
+ service_key: ServiceKeyT | None = None,
174
+ config: LogConfig,
175
+ ):
176
+ super().__init__(
177
+ LoggerType.APPLICATION,
178
+ environment=environment,
179
+ service_key=service_key,
180
+ client_key=None,
181
+ config=config,
182
+ )
183
+
184
+
185
+ class Cache(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
186
+ def __init__(
187
+ self,
188
+ *,
189
+ environment: EnvironmentT | None = None,
190
+ service_key: ServiceKeyT | None = None,
191
+ config: LogConfig,
192
+ ):
193
+ super().__init__(
194
+ LoggerType.CACHE,
195
+ environment=environment,
196
+ service_key=service_key,
197
+ client_key=None,
198
+ config=config,
199
+ )
200
+
201
+
202
+ class Client(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
203
+ def __init__(
204
+ self,
205
+ *,
206
+ environment: EnvironmentT | None = None,
207
+ service_key: ServiceKeyT | None = None,
208
+ client_key: str,
209
+ config: LogConfig,
210
+ ):
211
+ super().__init__(
212
+ LoggerType.CLIENT,
213
+ environment=environment,
214
+ service_key=service_key,
215
+ client_key=client_key,
216
+ config=config,
217
+ )
218
+
219
+
220
+ class Controller(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
221
+ def __init__(
222
+ self,
223
+ *,
224
+ environment: EnvironmentT | None = None,
225
+ service_key: ServiceKeyT | None = None,
226
+ config: LogConfig,
227
+ ):
228
+ super().__init__(
229
+ LoggerType.CONTROLLER,
230
+ environment=environment,
231
+ service_key=service_key,
232
+ client_key=None,
233
+ config=config,
234
+ )
235
+
236
+
237
+ class Database(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
238
+ def __init__(
239
+ self,
240
+ *,
241
+ environment: EnvironmentT | None = None,
242
+ service_key: ServiceKeyT | None = None,
243
+ config: LogConfig,
244
+ ):
245
+ super().__init__(
246
+ LoggerType.DATABASE,
247
+ environment=environment,
248
+ service_key=service_key,
249
+ client_key=None,
250
+ config=config,
251
+ )
252
+
253
+
254
+ class Exception(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
255
+ def __init__(
256
+ self,
257
+ *,
258
+ environment: EnvironmentT | None = None,
259
+ service_key: ServiceKeyT | None = None,
260
+ config: LogConfig,
261
+ ):
262
+ super().__init__(
263
+ LoggerType.EXCEPTION,
264
+ environment=environment,
265
+ service_key=service_key,
266
+ client_key=None,
267
+ config=config,
268
+ )
269
+
270
+
271
+ class Middleware(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
272
+ def __init__(
273
+ self,
274
+ *,
275
+ environment: EnvironmentT | None = None,
276
+ service_key: ServiceKeyT | None = None,
277
+ config: LogConfig,
278
+ ):
279
+ super().__init__(
280
+ LoggerType.MIDDLEWARE,
281
+ environment=environment,
282
+ service_key=service_key,
283
+ client_key=None,
284
+ config=config,
285
+ )
286
+
287
+
288
+ class Repository(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
289
+ def __init__(
290
+ self,
291
+ *,
292
+ environment: EnvironmentT | None = None,
293
+ service_key: ServiceKeyT | None = None,
294
+ config: LogConfig,
295
+ ):
296
+ super().__init__(
297
+ LoggerType.REPOSITORY,
298
+ environment=environment,
299
+ service_key=service_key,
300
+ client_key=None,
301
+ config=config,
302
+ )
303
+
304
+
305
+ class Service(Base[EnvironmentT, ServiceKeyT], Generic[EnvironmentT, ServiceKeyT]):
306
+ def __init__(
307
+ self,
308
+ *,
309
+ environment: EnvironmentT | None = None,
310
+ service_key: ServiceKeyT | None = None,
311
+ config: LogConfig,
312
+ ):
313
+ super().__init__(
314
+ LoggerType.SERVICE,
315
+ environment=environment,
316
+ service_key=service_key,
317
+ client_key=None,
318
+ config=config,
319
+ )
320
+
321
+
322
+ @overload
323
+ def create(
324
+ type: Literal[LoggerType.APPLICATION],
325
+ *,
326
+ environment: EnvironmentT | None = None,
327
+ service_key: ServiceKeyT | None = None,
328
+ config: LogConfig,
329
+ ) -> Application[EnvironmentT, ServiceKeyT]: ...
330
+ @overload
331
+ def create(
332
+ type: Literal[LoggerType.CACHE],
333
+ *,
334
+ environment: EnvironmentT | None = None,
335
+ service_key: ServiceKeyT | None = None,
336
+ config: LogConfig,
337
+ ) -> Cache[EnvironmentT, ServiceKeyT]: ...
338
+ @overload
339
+ def create(
340
+ type: Literal[LoggerType.CLIENT],
341
+ *,
342
+ environment: EnvironmentT | None = None,
343
+ service_key: ServiceKeyT | None = None,
344
+ client_key: str,
345
+ config: LogConfig,
346
+ ) -> Client[EnvironmentT, ServiceKeyT]: ...
347
+ @overload
348
+ def create(
349
+ type: Literal[LoggerType.CONTROLLER],
350
+ *,
351
+ environment: EnvironmentT | None = None,
352
+ service_key: ServiceKeyT | None = None,
353
+ config: LogConfig,
354
+ ) -> Controller[EnvironmentT, ServiceKeyT]: ...
355
+ @overload
356
+ def create(
357
+ type: Literal[LoggerType.DATABASE],
358
+ *,
359
+ environment: EnvironmentT | None = None,
360
+ service_key: ServiceKeyT | None = None,
361
+ config: LogConfig,
362
+ ) -> Database[EnvironmentT, ServiceKeyT]: ...
363
+ @overload
364
+ def create(
365
+ type: Literal[LoggerType.EXCEPTION],
366
+ *,
367
+ environment: EnvironmentT | None = None,
368
+ service_key: ServiceKeyT | None = None,
369
+ config: LogConfig,
370
+ ) -> Exception[EnvironmentT, ServiceKeyT]: ...
371
+ @overload
372
+ def create(
373
+ type: Literal[LoggerType.MIDDLEWARE],
374
+ *,
375
+ environment: EnvironmentT | None = None,
376
+ service_key: ServiceKeyT | None = None,
377
+ config: LogConfig,
378
+ ) -> Middleware[EnvironmentT, ServiceKeyT]: ...
379
+ @overload
380
+ def create(
381
+ type: Literal[LoggerType.REPOSITORY],
382
+ *,
383
+ environment: EnvironmentT | None = None,
384
+ service_key: ServiceKeyT | None = None,
385
+ config: LogConfig,
386
+ ) -> Repository[EnvironmentT, ServiceKeyT]: ...
387
+ @overload
388
+ def create(
389
+ type: Literal[LoggerType.SERVICE],
390
+ *,
391
+ environment: EnvironmentT | None = None,
392
+ service_key: ServiceKeyT | None = None,
393
+ config: LogConfig,
394
+ ) -> Service[EnvironmentT, ServiceKeyT]: ...
395
+ def create(
396
+ type: LoggerType = LoggerType.BASE,
397
+ *,
398
+ environment: EnvironmentT | None = None,
399
+ service_key: ServiceKeyT | None = None,
400
+ client_key: OptStr = None,
401
+ config: LogConfig,
402
+ ) -> (
403
+ Base[EnvironmentT, ServiceKeyT]
404
+ | Application[EnvironmentT, ServiceKeyT]
405
+ | Cache[EnvironmentT, ServiceKeyT]
406
+ | Client[EnvironmentT, ServiceKeyT]
407
+ | Controller[EnvironmentT, ServiceKeyT]
408
+ | Database[EnvironmentT, ServiceKeyT]
409
+ | Exception[EnvironmentT, ServiceKeyT]
410
+ | Middleware[EnvironmentT, ServiceKeyT]
411
+ | Repository[EnvironmentT, ServiceKeyT]
412
+ | Service[EnvironmentT, ServiceKeyT]
413
+ ):
414
+ if type is LoggerType.BASE:
415
+ return Base[EnvironmentT, ServiceKeyT](
416
+ environment=environment,
417
+ service_key=service_key,
418
+ client_key=client_key,
419
+ config=config,
420
+ )
421
+ elif type is LoggerType.APPLICATION:
422
+ return Application[EnvironmentT, ServiceKeyT](
423
+ environment=environment,
424
+ service_key=service_key,
425
+ config=config,
426
+ )
427
+ elif type is LoggerType.CACHE:
428
+ return Cache[EnvironmentT, ServiceKeyT](
429
+ environment=environment,
430
+ service_key=service_key,
431
+ config=config,
432
+ )
433
+ elif type is LoggerType.CLIENT:
434
+ if client_key is None:
435
+ raise ValueError(
436
+ "Argument 'client_key' can not be None if 'logger_type' is 'client'"
437
+ )
438
+ return Client[EnvironmentT, ServiceKeyT](
439
+ environment=environment,
440
+ service_key=service_key,
441
+ client_key=client_key,
442
+ config=config,
443
+ )
444
+ elif type is LoggerType.CONTROLLER:
445
+ return Controller[EnvironmentT, ServiceKeyT](
446
+ environment=environment,
447
+ service_key=service_key,
448
+ config=config,
449
+ )
450
+ elif type is LoggerType.DATABASE:
451
+ return Database[EnvironmentT, ServiceKeyT](
452
+ environment=environment,
453
+ service_key=service_key,
454
+ config=config,
455
+ )
456
+ elif type is LoggerType.EXCEPTION:
457
+ return Exception[EnvironmentT, ServiceKeyT](
458
+ environment=environment,
459
+ service_key=service_key,
460
+ config=config,
461
+ )
462
+ elif type is LoggerType.MIDDLEWARE:
463
+ return Middleware[EnvironmentT, ServiceKeyT](
464
+ environment=environment,
465
+ service_key=service_key,
466
+ config=config,
467
+ )
468
+ elif type is LoggerType.REPOSITORY:
469
+ return Repository[EnvironmentT, ServiceKeyT](
470
+ environment=environment,
471
+ service_key=service_key,
472
+ config=config,
473
+ )
474
+ elif type is LoggerType.SERVICE:
475
+ return Service[EnvironmentT, ServiceKeyT](
476
+ environment=environment,
477
+ service_key=service_key,
478
+ config=config,
479
+ )
480
+
481
+
482
+ class ApplicationLoggers(BaseModel, Generic[EnvironmentT, ServiceKeyT]):
483
+ model_config = ConfigDict(arbitrary_types_allowed=True)
484
+
485
+ application: Application[EnvironmentT, ServiceKeyT] = Field(
486
+ ..., description="Application logger"
487
+ )
488
+ cache: Cache[EnvironmentT, ServiceKeyT] = Field(..., description="Cache logger")
489
+ controller: Controller[EnvironmentT, ServiceKeyT] = Field(
490
+ ..., description="Controller logger"
491
+ )
492
+ database: Database[EnvironmentT, ServiceKeyT] = Field(
493
+ ..., description="Database logger"
494
+ )
495
+ exception: Exception[EnvironmentT, ServiceKeyT] = Field(
496
+ ..., description="Exception logger"
497
+ )
498
+ middleware: Middleware[EnvironmentT, ServiceKeyT] = Field(
499
+ ..., description="Middleware logger"
500
+ )
501
+ repository: Repository[EnvironmentT, ServiceKeyT] = Field(
502
+ ..., description="Repository logger"
503
+ )
504
+ service: Service[EnvironmentT, ServiceKeyT] = Field(
505
+ ..., description="Service logger"
506
+ )
507
+
508
+ @classmethod
509
+ def new(
510
+ cls,
511
+ *,
512
+ environment: EnvironmentT | None = None,
513
+ service_key: ServiceKeyT | None = None,
514
+ config: LogConfig,
515
+ ) -> "ApplicationLoggers[EnvironmentT, ServiceKeyT]":
516
+ return cls(
517
+ application=create(
518
+ LoggerType.APPLICATION,
519
+ environment=environment,
520
+ service_key=service_key,
521
+ config=config,
522
+ ),
523
+ cache=create(
524
+ LoggerType.CACHE,
525
+ environment=environment,
526
+ service_key=service_key,
527
+ config=config,
528
+ ),
529
+ controller=create(
530
+ LoggerType.CONTROLLER,
531
+ environment=environment,
532
+ service_key=service_key,
533
+ config=config,
534
+ ),
535
+ database=create(
536
+ LoggerType.DATABASE,
537
+ environment=environment,
538
+ service_key=service_key,
539
+ config=config,
540
+ ),
541
+ exception=create(
542
+ LoggerType.EXCEPTION,
543
+ environment=environment,
544
+ service_key=service_key,
545
+ config=config,
546
+ ),
547
+ middleware=create(
548
+ LoggerType.MIDDLEWARE,
549
+ environment=environment,
550
+ service_key=service_key,
551
+ config=config,
552
+ ),
553
+ repository=create(
554
+ LoggerType.REPOSITORY,
555
+ environment=environment,
556
+ service_key=service_key,
557
+ config=config,
558
+ ),
559
+ service=create(
560
+ LoggerType.SERVICE,
561
+ environment=environment,
562
+ service_key=service_key,
563
+ config=config,
564
+ ),
565
+ )