maleo-logging 0.0.5__tar.gz → 0.0.6__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo-logging
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Logging package for MaleoSuite
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: Proprietary
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo-logging
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Logging package for MaleoSuite
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: Proprietary
@@ -7,7 +7,7 @@ maleo_logging.egg-info/dependency_links.txt
7
7
  maleo_logging.egg-info/requires.txt
8
8
  maleo_logging.egg-info/top_level.txt
9
9
  src/__init__.py
10
- src/dtos.py
10
+ src/config.py
11
11
  src/enums.py
12
12
  src/google.py
13
13
  src/logger.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maleo-logging"
7
- version = "0.0.5"
7
+ version = "0.0.6"
8
8
  description = "Logging package for MaleoSuite"
9
9
  authors = [
10
10
  { name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
@@ -0,0 +1,31 @@
1
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
2
+ from typing import Optional, Self
3
+ from maleo.types.base.dict import OptionalStringToStringDict
4
+ from maleo.types.base.string import OptionalString
5
+ from .enums import Level
6
+ from .google import GoogleCloudLogging
7
+
8
+
9
+ class Config(BaseModel):
10
+ model_config = ConfigDict(arbitrary_types_allowed=True)
11
+
12
+ dir: str = Field(..., description="Log's directory")
13
+ level: Level = Field(Level.INFO, description="Log's level")
14
+ google_cloud_logging: Optional[GoogleCloudLogging] = Field(
15
+ default_factory=GoogleCloudLogging, description="Google cloud logging"
16
+ )
17
+ labels: OptionalStringToStringDict = Field(
18
+ None, description="Log labels. (Optional)"
19
+ )
20
+ aggregate_file_name: OptionalString = Field(
21
+ None, description="Log aggregate file name"
22
+ )
23
+ individual_log: bool = Field(True, description="Whether to have individual log")
24
+
25
+ @model_validator(mode="after")
26
+ def validate_aggregate_file_name(self) -> Self:
27
+ if isinstance(self.aggregate_file_name, str):
28
+ if not self.aggregate_file_name.endswith(".log"):
29
+ self.aggregate_file_name += ".log"
30
+
31
+ return self
@@ -0,0 +1,534 @@
1
+ import logging
2
+ import os
3
+ from datetime import datetime, timezone
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+ from typing import Literal, Optional, Union, overload
6
+ from maleo.enums.environment import Environment
7
+ from maleo.enums.service import Key
8
+ from maleo.types.base.dict import StringToStringDict
9
+ from maleo.types.base.string import OptionalString
10
+ from .config import Config
11
+ from .enums import LoggerType
12
+
13
+
14
+ # * We suggest to NOT use this class
15
+ # * Instead use the inherited classes
16
+ class Base(logging.Logger):
17
+ def __init__(
18
+ self,
19
+ type: LoggerType = LoggerType.BASE,
20
+ *,
21
+ environment: Optional[Environment] = None,
22
+ service_key: Optional[Key] = None,
23
+ client_key: OptionalString = None,
24
+ config: Config,
25
+ ):
26
+ self._type = type # Declare logger type
27
+
28
+ # Ensure environment exists
29
+ actual_environment = environment or os.getenv("ENVIRONMENT")
30
+ if actual_environment is None:
31
+ raise ValueError(
32
+ "ENVIRONMENT environment variable must be set if 'environment' is set to None"
33
+ )
34
+ else:
35
+ self._environment = Environment(actual_environment)
36
+
37
+ # Ensure service_key exists
38
+ actual_service_key = service_key or os.getenv("SERVICE_KEY")
39
+ if actual_service_key is None:
40
+ raise ValueError(
41
+ "SERVICE_KEY environment variable must be set if 'service_key' is set to None"
42
+ )
43
+ else:
44
+ self._service_key = Key(actual_service_key)
45
+
46
+ self._client_key = client_key # Declare client key
47
+
48
+ # Ensure client_key is valid if logger type is a client
49
+ if self._type == LoggerType.CLIENT and self._client_key is None:
50
+ raise ValueError(
51
+ "'client_key' parameter must be provided if 'logger_type' is 'client'"
52
+ )
53
+
54
+ # Define logger name
55
+ base_name = f"{self._environment} - {self._service_key} - {self._type}"
56
+ if self._type == LoggerType.CLIENT:
57
+ self._name = f"{base_name} - {self._client_key}"
58
+ else:
59
+ self._name = base_name
60
+
61
+ # Define log labels
62
+ self._labels: StringToStringDict = {
63
+ "logger_type": self._type.value,
64
+ "service_environment": self._environment.value,
65
+ "service_key": self._service_key.value,
66
+ }
67
+ if client_key is not None:
68
+ self._labels["client_key"] = client_key
69
+ if config.labels is not None:
70
+ self._labels.update(config.labels)
71
+
72
+ self._config = config
73
+
74
+ super().__init__(self._name, self._config.level) # Init the superclass's logger
75
+
76
+ # Clear existing handlers to prevent duplicates
77
+ for handler in list(self.handlers):
78
+ self.removeHandler(handler)
79
+ handler.close()
80
+
81
+ # Console handler
82
+ console_handler = logging.StreamHandler()
83
+ console_handler.setFormatter(
84
+ logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
85
+ )
86
+ self.addHandler(console_handler)
87
+
88
+ # Google Cloud Logging handler (If enabled)
89
+ if self._config.google_cloud_logging is not None:
90
+ cloud_logging_handler = self._config.google_cloud_logging.create_handler(
91
+ name=self._name.replace(" ", ""),
92
+ labels=self._labels,
93
+ )
94
+ self.addHandler(cloud_logging_handler)
95
+ else:
96
+ self.warning(
97
+ "Cloud logging is not configured. Will not add cloud logging handler"
98
+ )
99
+
100
+ # Define aggregate log directory
101
+ if self._config.aggregate_file_name is not None:
102
+ aggregate_log_dir = os.path.join(self._log_dir, "aggregate")
103
+ os.makedirs(aggregate_log_dir, exist_ok=True)
104
+ if not self._config.aggregate_file_name.endswith(".log"):
105
+ self._config.aggregate_file_name += ".log"
106
+ log_filename = os.path.join(
107
+ aggregate_log_dir, self._config.aggregate_file_name
108
+ )
109
+
110
+ # File handler
111
+ file_handler = logging.FileHandler(log_filename, mode="a")
112
+ file_handler.setFormatter(
113
+ logging.Formatter(
114
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
115
+ )
116
+ )
117
+ self.addHandler(file_handler)
118
+
119
+ # Define individual log directory
120
+ if self._config.individual_log:
121
+ if self._type == LoggerType.CLIENT:
122
+ log_dir = f"{self._type}/{self._client_key}"
123
+ else:
124
+ log_dir = f"{self._type}"
125
+ self._log_dir = os.path.join(self._config.dir, log_dir)
126
+ os.makedirs(self._log_dir, exist_ok=True)
127
+
128
+ # Generate timestamped filename
129
+ log_filename = os.path.join(
130
+ self._log_dir,
131
+ f"{datetime.now(tz=timezone.utc).isoformat(timespec="seconds")}.log",
132
+ )
133
+
134
+ # File handler
135
+ file_handler = logging.FileHandler(log_filename, mode="a")
136
+ file_handler.setFormatter(
137
+ logging.Formatter(
138
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
139
+ )
140
+ )
141
+ self.addHandler(file_handler)
142
+
143
+ def dispose(self):
144
+ """Dispose of the logger by removing all handlers."""
145
+ for handler in list(self.handlers):
146
+ self.removeHandler(handler)
147
+ handler.close()
148
+ self.handlers.clear()
149
+
150
+
151
+ class Application(Base):
152
+ def __init__(
153
+ self,
154
+ *,
155
+ environment: Optional[Environment] = None,
156
+ service_key: Optional[Key] = None,
157
+ config: Config,
158
+ ):
159
+ super().__init__(
160
+ LoggerType.APPLICATION,
161
+ environment=environment,
162
+ service_key=service_key,
163
+ client_key=None,
164
+ config=config,
165
+ )
166
+
167
+
168
+ class Cache(Base):
169
+ def __init__(
170
+ self,
171
+ *,
172
+ environment: Optional[Environment] = None,
173
+ service_key: Optional[Key] = None,
174
+ config: Config,
175
+ ):
176
+ super().__init__(
177
+ LoggerType.CACHE,
178
+ environment=environment,
179
+ service_key=service_key,
180
+ client_key=None,
181
+ config=config,
182
+ )
183
+
184
+
185
+ class Client(Base):
186
+ def __init__(
187
+ self,
188
+ *,
189
+ environment: Optional[Environment] = None,
190
+ service_key: Optional[Key] = None,
191
+ client_key: str,
192
+ config: Config,
193
+ ):
194
+ super().__init__(
195
+ LoggerType.CACHE,
196
+ environment=environment,
197
+ service_key=service_key,
198
+ client_key=client_key,
199
+ config=config,
200
+ )
201
+
202
+
203
+ class Controller(Base):
204
+ def __init__(
205
+ self,
206
+ *,
207
+ environment: Optional[Environment] = None,
208
+ service_key: Optional[Key] = None,
209
+ config: Config,
210
+ ):
211
+ super().__init__(
212
+ LoggerType.CONTROLLER,
213
+ environment=environment,
214
+ service_key=service_key,
215
+ client_key=None,
216
+ config=config,
217
+ )
218
+
219
+
220
+ class Database(Base):
221
+ def __init__(
222
+ self,
223
+ *,
224
+ environment: Optional[Environment] = None,
225
+ service_key: Optional[Key] = None,
226
+ config: Config,
227
+ ):
228
+ super().__init__(
229
+ LoggerType.DATABASE,
230
+ environment=environment,
231
+ service_key=service_key,
232
+ client_key=None,
233
+ config=config,
234
+ )
235
+
236
+
237
+ class Exception(Base):
238
+ def __init__(
239
+ self,
240
+ *,
241
+ environment: Optional[Environment] = None,
242
+ service_key: Optional[Key] = None,
243
+ config: Config,
244
+ ):
245
+ super().__init__(
246
+ LoggerType.EXCEPTION,
247
+ environment=environment,
248
+ service_key=service_key,
249
+ client_key=None,
250
+ config=config,
251
+ )
252
+
253
+
254
+ class Middleware(Base):
255
+ def __init__(
256
+ self,
257
+ *,
258
+ environment: Optional[Environment] = None,
259
+ service_key: Optional[Key] = None,
260
+ config: Config,
261
+ ):
262
+ super().__init__(
263
+ LoggerType.MIDDLEWARE,
264
+ environment=environment,
265
+ service_key=service_key,
266
+ client_key=None,
267
+ config=config,
268
+ )
269
+
270
+
271
+ class Repository(Base):
272
+ def __init__(
273
+ self,
274
+ *,
275
+ environment: Optional[Environment] = None,
276
+ service_key: Optional[Key] = None,
277
+ config: Config,
278
+ ):
279
+ super().__init__(
280
+ LoggerType.REPOSITORY,
281
+ environment=environment,
282
+ service_key=service_key,
283
+ client_key=None,
284
+ config=config,
285
+ )
286
+
287
+
288
+ class Service(Base):
289
+ def __init__(
290
+ self,
291
+ *,
292
+ environment: Optional[Environment] = None,
293
+ service_key: Optional[Key] = None,
294
+ config: Config,
295
+ ):
296
+ super().__init__(
297
+ LoggerType.SERVICE,
298
+ environment=environment,
299
+ service_key=service_key,
300
+ client_key=None,
301
+ config=config,
302
+ )
303
+
304
+
305
+ @overload
306
+ def create(
307
+ type: Literal[LoggerType.APPLICATION],
308
+ *,
309
+ environment: Optional[Environment] = None,
310
+ service_key: Optional[Key] = None,
311
+ config: Config,
312
+ ) -> Application: ...
313
+ @overload
314
+ def create(
315
+ type: Literal[LoggerType.CACHE],
316
+ *,
317
+ environment: Optional[Environment] = None,
318
+ service_key: Optional[Key] = None,
319
+ config: Config,
320
+ ) -> Cache: ...
321
+ @overload
322
+ def create(
323
+ type: Literal[LoggerType.CLIENT],
324
+ *,
325
+ environment: Optional[Environment] = None,
326
+ service_key: Optional[Key] = None,
327
+ client_key: str,
328
+ config: Config,
329
+ ) -> Client: ...
330
+ @overload
331
+ def create(
332
+ type: Literal[LoggerType.CONTROLLER],
333
+ *,
334
+ environment: Optional[Environment] = None,
335
+ service_key: Optional[Key] = None,
336
+ config: Config,
337
+ ) -> Controller: ...
338
+ @overload
339
+ def create(
340
+ type: Literal[LoggerType.DATABASE],
341
+ *,
342
+ environment: Optional[Environment] = None,
343
+ service_key: Optional[Key] = None,
344
+ config: Config,
345
+ ) -> Database: ...
346
+ @overload
347
+ def create(
348
+ type: Literal[LoggerType.EXCEPTION],
349
+ *,
350
+ environment: Optional[Environment] = None,
351
+ service_key: Optional[Key] = None,
352
+ config: Config,
353
+ ) -> Exception: ...
354
+ @overload
355
+ def create(
356
+ type: Literal[LoggerType.MIDDLEWARE],
357
+ *,
358
+ environment: Optional[Environment] = None,
359
+ service_key: Optional[Key] = None,
360
+ config: Config,
361
+ ) -> Middleware: ...
362
+ @overload
363
+ def create(
364
+ type: Literal[LoggerType.REPOSITORY],
365
+ *,
366
+ environment: Optional[Environment] = None,
367
+ service_key: Optional[Key] = None,
368
+ config: Config,
369
+ ) -> Repository: ...
370
+ @overload
371
+ def create(
372
+ type: Literal[LoggerType.SERVICE],
373
+ *,
374
+ environment: Optional[Environment] = None,
375
+ service_key: Optional[Key] = None,
376
+ config: Config,
377
+ ) -> Service: ...
378
+ def create(
379
+ type: LoggerType = LoggerType.BASE,
380
+ *,
381
+ environment: Optional[Environment] = None,
382
+ service_key: Optional[Key] = None,
383
+ client_key: OptionalString = None,
384
+ config: Config,
385
+ ) -> Union[
386
+ Base,
387
+ Application,
388
+ Cache,
389
+ Client,
390
+ Controller,
391
+ Database,
392
+ Exception,
393
+ Middleware,
394
+ Repository,
395
+ Service,
396
+ ]:
397
+ if type is LoggerType.BASE:
398
+ return Base(
399
+ environment=environment,
400
+ service_key=service_key,
401
+ client_key=client_key,
402
+ config=config,
403
+ )
404
+ elif type is LoggerType.APPLICATION:
405
+ return Application(
406
+ environment=environment,
407
+ service_key=service_key,
408
+ config=config,
409
+ )
410
+ elif type is LoggerType.CACHE:
411
+ return Cache(
412
+ environment=environment,
413
+ service_key=service_key,
414
+ config=config,
415
+ )
416
+ elif type is LoggerType.CLIENT:
417
+ if client_key is None:
418
+ raise ValueError(
419
+ "Argument 'client_key' can not be None if 'logger_type' is 'client'"
420
+ )
421
+ return Client(
422
+ environment=environment,
423
+ service_key=service_key,
424
+ client_key=client_key,
425
+ config=config,
426
+ )
427
+ elif type is LoggerType.CONTROLLER:
428
+ return Controller(
429
+ environment=environment,
430
+ service_key=service_key,
431
+ config=config,
432
+ )
433
+ elif type is LoggerType.DATABASE:
434
+ return Database(
435
+ environment=environment,
436
+ service_key=service_key,
437
+ config=config,
438
+ )
439
+ elif type is LoggerType.EXCEPTION:
440
+ return Exception(
441
+ environment=environment,
442
+ service_key=service_key,
443
+ config=config,
444
+ )
445
+ elif type is LoggerType.MIDDLEWARE:
446
+ return Middleware(
447
+ environment=environment,
448
+ service_key=service_key,
449
+ config=config,
450
+ )
451
+ elif type is LoggerType.REPOSITORY:
452
+ return Repository(
453
+ environment=environment,
454
+ service_key=service_key,
455
+ config=config,
456
+ )
457
+ elif type is LoggerType.SERVICE:
458
+ return Service(
459
+ environment=environment,
460
+ service_key=service_key,
461
+ config=config,
462
+ )
463
+
464
+
465
+ class Loggers(BaseModel):
466
+ model_config = ConfigDict(arbitrary_types_allowed=True)
467
+
468
+ application: Application = Field(..., description="Application logger")
469
+ cache: Cache = Field(..., description="Cache logger")
470
+ controller: Controller = Field(..., description="Controller logger")
471
+ database: Database = Field(..., description="Database logger")
472
+ exception: Exception = Field(..., description="Exception logger")
473
+ middleware: Middleware = Field(..., description="Middleware logger")
474
+ repository: Repository = Field(..., description="Repository logger")
475
+ service: Service = Field(..., description="Service logger")
476
+
477
+ @classmethod
478
+ def create(
479
+ cls,
480
+ *,
481
+ environment: Optional[Environment] = None,
482
+ service_key: Optional[Key] = None,
483
+ config: Config,
484
+ ) -> "Loggers":
485
+ return cls(
486
+ application=create(
487
+ LoggerType.APPLICATION,
488
+ environment=environment,
489
+ service_key=service_key,
490
+ config=config,
491
+ ),
492
+ cache=create(
493
+ LoggerType.CACHE,
494
+ environment=environment,
495
+ service_key=service_key,
496
+ config=config,
497
+ ),
498
+ controller=create(
499
+ LoggerType.CONTROLLER,
500
+ environment=environment,
501
+ service_key=service_key,
502
+ config=config,
503
+ ),
504
+ database=create(
505
+ LoggerType.DATABASE,
506
+ environment=environment,
507
+ service_key=service_key,
508
+ config=config,
509
+ ),
510
+ exception=create(
511
+ LoggerType.EXCEPTION,
512
+ environment=environment,
513
+ service_key=service_key,
514
+ config=config,
515
+ ),
516
+ middleware=create(
517
+ LoggerType.MIDDLEWARE,
518
+ environment=environment,
519
+ service_key=service_key,
520
+ config=config,
521
+ ),
522
+ repository=create(
523
+ LoggerType.REPOSITORY,
524
+ environment=environment,
525
+ service_key=service_key,
526
+ config=config,
527
+ ),
528
+ service=create(
529
+ LoggerType.SERVICE,
530
+ environment=environment,
531
+ service_key=service_key,
532
+ config=config,
533
+ ),
534
+ )
@@ -1,24 +0,0 @@
1
- from pydantic import BaseModel, Field, ConfigDict
2
- from typing import Optional
3
- from maleo.enums.environment import Environment
4
- from maleo.enums.service import Key
5
- from maleo.types.base.string import OptionalString
6
- from .enums import Level, LoggerType
7
- from .google import GoogleCloudLogging
8
-
9
-
10
- class Labels(BaseModel):
11
- logger_type: LoggerType = Field(..., description="Logger's type")
12
- service_environment: Environment = Field(..., description="Service's environment")
13
- service_key: Key = Field(..., description="Service's key")
14
- client_key: OptionalString = Field(None, description="Client's key (Optional)")
15
-
16
-
17
- class SimpleConfig(BaseModel):
18
- model_config = ConfigDict(arbitrary_types_allowed=True)
19
-
20
- dir: str = Field(..., description="Log's directory")
21
- level: Level = Field(Level.INFO, description="Log's level")
22
- google_cloud_logging: Optional[GoogleCloudLogging] = Field(
23
- default_factory=GoogleCloudLogging, description="Google cloud logging"
24
- )
@@ -1,660 +0,0 @@
1
- import logging
2
- import os
3
- from datetime import datetime, timezone
4
- from typing import Literal, Optional, Union, overload
5
- from maleo.enums.environment import Environment
6
- from maleo.enums.service import Key
7
- from maleo.types.base.dict import OptionalStringToStringDict
8
- from maleo.types.base.string import OptionalString
9
- from .dtos import Labels
10
- from maleo.utils.merger import merge_dicts
11
- from .enums import Level, LoggerType
12
- from .google import GoogleCloudLogging
13
-
14
-
15
- class Base(logging.Logger):
16
- def __init__(
17
- self,
18
- type: LoggerType,
19
- dir: str,
20
- *,
21
- environment: Optional[Environment] = None,
22
- service_key: Optional[Key] = None,
23
- client_key: OptionalString = None,
24
- level: Level = Level.INFO,
25
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
26
- labels: OptionalStringToStringDict = None,
27
- aggregate_file_name: OptionalString = None,
28
- inidividual_log: bool = True,
29
- ):
30
- self._type = type # Declare logger type
31
-
32
- # Ensure environment exists
33
- actual_environment = environment or os.getenv("ENVIRONMENT")
34
- if actual_environment is None:
35
- raise ValueError(
36
- "ENVIRONMENT environment variable must be set if 'environment' is set to None"
37
- )
38
- else:
39
- self._environment = Environment(actual_environment)
40
-
41
- # Ensure service_key exists
42
- actual_service_key = service_key or os.getenv("SERVICE_KEY")
43
- if actual_service_key is None:
44
- raise ValueError(
45
- "SERVICE_KEY environment variable must be set if 'service_key' is set to None"
46
- )
47
- else:
48
- self._service_key = Key(actual_service_key)
49
-
50
- self._client_key = client_key # Declare client key
51
-
52
- # Ensure client_key is valid if logger type is a client
53
- if self._type == LoggerType.CLIENT and self._client_key is None:
54
- raise ValueError(
55
- "'client_key' parameter must be provided if 'logger_type' is 'client'"
56
- )
57
-
58
- # Define logger name
59
- base_name = f"{self._environment} - {self._service_key} - {self._type}"
60
- if self._type == LoggerType.CLIENT:
61
- self._name = f"{base_name} - {self._client_key}"
62
- else:
63
- self._name = base_name
64
-
65
- # Define log labels
66
- self._labels = Labels(
67
- logger_type=self._type,
68
- service_environment=self._environment,
69
- service_key=self._service_key,
70
- client_key=client_key,
71
- )
72
-
73
- super().__init__(self._name, level) # Init the superclass's logger
74
-
75
- # Clear existing handlers to prevent duplicates
76
- for handler in list(self.handlers):
77
- self.removeHandler(handler)
78
- handler.close()
79
-
80
- # Console handler
81
- console_handler = logging.StreamHandler()
82
- console_handler.setFormatter(
83
- logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
84
- )
85
- self.addHandler(console_handler)
86
-
87
- # Google Cloud Logging handler (If enabled)
88
- if google_cloud_logging is not None:
89
- final_labels = self._labels.model_dump(mode="json", exclude_none=True)
90
- if labels is not None:
91
- final_labels = merge_dicts(final_labels, labels)
92
- cloud_logging_handler = google_cloud_logging.create_handler(
93
- name=self._name.replace(" ", ""),
94
- labels=final_labels,
95
- )
96
- self.addHandler(cloud_logging_handler)
97
- else:
98
- self.warning(
99
- "Cloud logging is not configured. Will not add cloud logging handler"
100
- )
101
-
102
- # Define aggregate log directory
103
- if aggregate_file_name is not None:
104
- if not aggregate_file_name.endswith(".log"):
105
- aggregate_file_name += ".log"
106
- log_filename = os.path.join(self._log_dir, "aggregate", aggregate_file_name)
107
-
108
- # File handler
109
- file_handler = logging.FileHandler(log_filename, mode="a")
110
- file_handler.setFormatter(
111
- logging.Formatter(
112
- "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
113
- )
114
- )
115
- self.addHandler(file_handler)
116
-
117
- if inidividual_log:
118
- # Define log directory
119
- if self._type == LoggerType.CLIENT:
120
- log_dir = f"{self._type}/{self._client_key}"
121
- else:
122
- log_dir = f"{self._type}"
123
- self._log_dir = os.path.join(dir, log_dir)
124
- os.makedirs(self._log_dir, exist_ok=True)
125
-
126
- # Generate timestamped filename
127
- log_filename = os.path.join(
128
- self._log_dir,
129
- f"{datetime.now(tz=timezone.utc).isoformat(timespec="seconds")}.log",
130
- )
131
-
132
- # File handler
133
- file_handler = logging.FileHandler(log_filename, mode="a")
134
- file_handler.setFormatter(
135
- logging.Formatter(
136
- "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
137
- )
138
- )
139
- self.addHandler(file_handler)
140
-
141
- @property
142
- def type(self) -> str:
143
- return self._type
144
-
145
- @property
146
- def location(self) -> str:
147
- return self._log_dir
148
-
149
- @property
150
- def environment(self) -> Environment:
151
- return self._environment
152
-
153
- @property
154
- def service(self) -> str:
155
- return self._service_key
156
-
157
- @property
158
- def client(self) -> OptionalString:
159
- return self._client_key
160
-
161
- @property
162
- def identity(self) -> str:
163
- return self._name
164
-
165
- @property
166
- def labels(self) -> Labels:
167
- return self._labels
168
-
169
- def dispose(self):
170
- """Dispose of the logger by removing all handlers."""
171
- for handler in list(self.handlers):
172
- self.removeHandler(handler)
173
- handler.close()
174
- self.handlers.clear()
175
-
176
-
177
- class Application(Base):
178
- def __init__(
179
- self,
180
- dir: str,
181
- environment: Optional[Environment] = None,
182
- service_key: Optional[Key] = None,
183
- level: Level = Level.INFO,
184
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
185
- labels: OptionalStringToStringDict = None,
186
- aggregate_file_name: OptionalString = None,
187
- inidividual_log: bool = True,
188
- ):
189
- super().__init__(
190
- dir=dir,
191
- type=LoggerType.APPLICATION,
192
- environment=environment,
193
- service_key=service_key,
194
- client_key=None,
195
- level=level,
196
- google_cloud_logging=google_cloud_logging,
197
- labels=labels,
198
- aggregate_file_name=aggregate_file_name,
199
- inidividual_log=inidividual_log,
200
- )
201
-
202
-
203
- class Cache(Base):
204
- def __init__(
205
- self,
206
- dir: str,
207
- environment: Optional[Environment] = None,
208
- service_key: Optional[Key] = None,
209
- level: Level = Level.INFO,
210
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
211
- labels: OptionalStringToStringDict = None,
212
- aggregate_file_name: OptionalString = None,
213
- inidividual_log: bool = True,
214
- ):
215
- super().__init__(
216
- dir=dir,
217
- type=LoggerType.CACHE,
218
- environment=environment,
219
- service_key=service_key,
220
- client_key=None,
221
- level=level,
222
- google_cloud_logging=google_cloud_logging,
223
- labels=labels,
224
- aggregate_file_name=aggregate_file_name,
225
- inidividual_log=inidividual_log,
226
- )
227
-
228
-
229
- class Client(Base):
230
- def __init__(
231
- self,
232
- dir: str,
233
- client_key: str,
234
- environment: Optional[Environment] = None,
235
- service_key: Optional[Key] = None,
236
- level: Level = Level.INFO,
237
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
238
- labels: OptionalStringToStringDict = None,
239
- aggregate_file_name: OptionalString = None,
240
- inidividual_log: bool = True,
241
- ):
242
- super().__init__(
243
- dir=dir,
244
- type=LoggerType.CLIENT,
245
- environment=environment,
246
- service_key=service_key,
247
- client_key=client_key,
248
- level=level,
249
- google_cloud_logging=google_cloud_logging,
250
- labels=labels,
251
- aggregate_file_name=aggregate_file_name,
252
- inidividual_log=inidividual_log,
253
- )
254
-
255
-
256
- class Controller(Base):
257
- def __init__(
258
- self,
259
- dir: str,
260
- environment: Optional[Environment] = None,
261
- service_key: Optional[Key] = None,
262
- level: Level = Level.INFO,
263
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
264
- labels: OptionalStringToStringDict = None,
265
- aggregate_file_name: OptionalString = None,
266
- inidividual_log: bool = True,
267
- ):
268
- super().__init__(
269
- dir=dir,
270
- type=LoggerType.CONTROLLER,
271
- environment=environment,
272
- service_key=service_key,
273
- client_key=None,
274
- level=level,
275
- google_cloud_logging=google_cloud_logging,
276
- labels=labels,
277
- aggregate_file_name=aggregate_file_name,
278
- inidividual_log=inidividual_log,
279
- )
280
-
281
-
282
- class Database(Base):
283
- def __init__(
284
- self,
285
- dir: str,
286
- environment: Optional[Environment] = None,
287
- service_key: Optional[Key] = None,
288
- level=Level.INFO,
289
- google_cloud_logging=None,
290
- labels: OptionalStringToStringDict = None,
291
- aggregate_file_name: OptionalString = None,
292
- inidividual_log: bool = True,
293
- ):
294
- super().__init__(
295
- dir=dir,
296
- type=LoggerType.DATABASE,
297
- environment=environment,
298
- service_key=service_key,
299
- client_key=None,
300
- level=level,
301
- google_cloud_logging=google_cloud_logging,
302
- labels=labels,
303
- aggregate_file_name=aggregate_file_name,
304
- inidividual_log=inidividual_log,
305
- )
306
-
307
-
308
- class Exception(Base):
309
- def __init__(
310
- self,
311
- dir: str,
312
- environment: Optional[Environment] = None,
313
- service_key: Optional[Key] = None,
314
- level=Level.INFO,
315
- google_cloud_logging=None,
316
- labels: OptionalStringToStringDict = None,
317
- aggregate_file_name: OptionalString = None,
318
- inidividual_log: bool = True,
319
- ):
320
- super().__init__(
321
- dir=dir,
322
- type=LoggerType.EXCEPTION,
323
- environment=environment,
324
- service_key=service_key,
325
- client_key=None,
326
- level=level,
327
- google_cloud_logging=google_cloud_logging,
328
- labels=labels,
329
- aggregate_file_name=aggregate_file_name,
330
- inidividual_log=inidividual_log,
331
- )
332
-
333
-
334
- class Middleware(Base):
335
- def __init__(
336
- self,
337
- dir: str,
338
- environment: Optional[Environment] = None,
339
- service_key: Optional[Key] = None,
340
- level=Level.INFO,
341
- google_cloud_logging=None,
342
- labels: OptionalStringToStringDict = None,
343
- aggregate_file_name: OptionalString = None,
344
- inidividual_log: bool = True,
345
- ):
346
- super().__init__(
347
- dir=dir,
348
- type=LoggerType.MIDDLEWARE,
349
- environment=environment,
350
- service_key=service_key,
351
- client_key=None,
352
- level=level,
353
- google_cloud_logging=google_cloud_logging,
354
- labels=labels,
355
- aggregate_file_name=aggregate_file_name,
356
- inidividual_log=inidividual_log,
357
- )
358
-
359
-
360
- class Repository(Base):
361
- def __init__(
362
- self,
363
- dir: str,
364
- environment: Optional[Environment] = None,
365
- service_key: Optional[Key] = None,
366
- level: Level = Level.INFO,
367
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
368
- labels: OptionalStringToStringDict = None,
369
- aggregate_file_name: OptionalString = None,
370
- inidividual_log: bool = True,
371
- ):
372
- super().__init__(
373
- dir=dir,
374
- type=LoggerType.REPOSITORY,
375
- environment=environment,
376
- service_key=service_key,
377
- client_key=None,
378
- level=level,
379
- google_cloud_logging=google_cloud_logging,
380
- labels=labels,
381
- aggregate_file_name=aggregate_file_name,
382
- inidividual_log=inidividual_log,
383
- )
384
-
385
-
386
- class Service(Base):
387
- def __init__(
388
- self,
389
- dir: str,
390
- environment: Optional[Environment] = None,
391
- service_key: Optional[Key] = None,
392
- level: Level = Level.INFO,
393
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
394
- labels: OptionalStringToStringDict = None,
395
- aggregate_file_name: OptionalString = None,
396
- inidividual_log: bool = True,
397
- ):
398
- super().__init__(
399
- dir=dir,
400
- type=LoggerType.SERVICE,
401
- environment=environment,
402
- service_key=service_key,
403
- client_key=None,
404
- level=level,
405
- google_cloud_logging=google_cloud_logging,
406
- labels=labels,
407
- aggregate_file_name=aggregate_file_name,
408
- inidividual_log=inidividual_log,
409
- )
410
-
411
-
412
- @overload
413
- def create(
414
- dir: str,
415
- type: Literal[LoggerType.APPLICATION],
416
- *,
417
- environment: Optional[Environment] = None,
418
- service_key: Optional[Key] = None,
419
- level: Level = Level.INFO,
420
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
421
- labels: OptionalStringToStringDict = None,
422
- aggregate_file_name: OptionalString = None,
423
- inidividual_log: bool = True,
424
- ) -> Application: ...
425
- @overload
426
- def create(
427
- dir: str,
428
- type: Literal[LoggerType.CACHE],
429
- *,
430
- environment: Optional[Environment] = None,
431
- service_key: Optional[Key] = None,
432
- level: Level = Level.INFO,
433
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
434
- labels: OptionalStringToStringDict = None,
435
- aggregate_file_name: OptionalString = None,
436
- inidividual_log: bool = True,
437
- ) -> Cache: ...
438
- @overload
439
- def create(
440
- dir: str,
441
- type: Literal[LoggerType.CLIENT],
442
- *,
443
- environment: Optional[Environment] = None,
444
- service_key: Optional[Key] = None,
445
- client_key: str,
446
- level: Level = Level.INFO,
447
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
448
- labels: OptionalStringToStringDict = None,
449
- aggregate_file_name: OptionalString = None,
450
- inidividual_log: bool = True,
451
- ) -> Client: ...
452
- @overload
453
- def create(
454
- dir: str,
455
- type: Literal[LoggerType.CONTROLLER],
456
- *,
457
- environment: Optional[Environment] = None,
458
- service_key: Optional[Key] = None,
459
- level: Level = Level.INFO,
460
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
461
- labels: OptionalStringToStringDict = None,
462
- aggregate_file_name: OptionalString = None,
463
- inidividual_log: bool = True,
464
- ) -> Controller: ...
465
- @overload
466
- def create(
467
- dir: str,
468
- type: Literal[LoggerType.DATABASE],
469
- *,
470
- environment: Optional[Environment] = None,
471
- service_key: Optional[Key] = None,
472
- level: Level = Level.INFO,
473
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
474
- labels: OptionalStringToStringDict = None,
475
- aggregate_file_name: OptionalString = None,
476
- inidividual_log: bool = True,
477
- ) -> Database: ...
478
- @overload
479
- def create(
480
- dir: str,
481
- type: Literal[LoggerType.MIDDLEWARE],
482
- *,
483
- environment: Optional[Environment] = None,
484
- service_key: Optional[Key] = None,
485
- level: Level = Level.INFO,
486
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
487
- labels: OptionalStringToStringDict = None,
488
- aggregate_file_name: OptionalString = None,
489
- inidividual_log: bool = True,
490
- ) -> Middleware: ...
491
- @overload
492
- def create(
493
- dir: str,
494
- type: Literal[LoggerType.REPOSITORY],
495
- *,
496
- environment: Optional[Environment] = None,
497
- service_key: Optional[Key] = None,
498
- level: Level = Level.INFO,
499
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
500
- labels: OptionalStringToStringDict = None,
501
- aggregate_file_name: OptionalString = None,
502
- inidividual_log: bool = True,
503
- ) -> Repository: ...
504
- @overload
505
- def create(
506
- dir: str,
507
- type: Literal[LoggerType.SERVICE],
508
- *,
509
- environment: Optional[Environment] = None,
510
- service_key: Optional[Key] = None,
511
- level: Level = Level.INFO,
512
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
513
- labels: OptionalStringToStringDict = None,
514
- aggregate_file_name: OptionalString = None,
515
- inidividual_log: bool = True,
516
- ) -> Service: ...
517
- def create(
518
- dir: str,
519
- type: LoggerType = LoggerType.BASE,
520
- *,
521
- environment: Optional[Environment] = None,
522
- service_key: Optional[Key] = None,
523
- client_key: OptionalString = None,
524
- level: Level = Level.INFO,
525
- google_cloud_logging: Optional[GoogleCloudLogging] = None,
526
- labels: OptionalStringToStringDict = None,
527
- aggregate_file_name: OptionalString = None,
528
- inidividual_log: bool = True,
529
- ) -> Union[
530
- Base,
531
- Application,
532
- Cache,
533
- Client,
534
- Controller,
535
- Database,
536
- Exception,
537
- Middleware,
538
- Repository,
539
- Service,
540
- ]:
541
- if type not in LoggerType:
542
- raise ValueError(f"Invalid logger type of '{type}'")
543
-
544
- if type is LoggerType.BASE:
545
- return Base(
546
- type=type,
547
- dir=dir,
548
- environment=environment,
549
- service_key=service_key,
550
- client_key=client_key,
551
- level=level,
552
- google_cloud_logging=google_cloud_logging,
553
- labels=labels,
554
- aggregate_file_name=aggregate_file_name,
555
- inidividual_log=inidividual_log,
556
- )
557
- elif type is LoggerType.APPLICATION:
558
- return Application(
559
- dir=dir,
560
- environment=environment,
561
- service_key=service_key,
562
- level=level,
563
- google_cloud_logging=google_cloud_logging,
564
- labels=labels,
565
- aggregate_file_name=aggregate_file_name,
566
- inidividual_log=inidividual_log,
567
- )
568
- elif type is LoggerType.CACHE:
569
- return Cache(
570
- dir=dir,
571
- environment=environment,
572
- service_key=service_key,
573
- level=level,
574
- google_cloud_logging=google_cloud_logging,
575
- labels=labels,
576
- aggregate_file_name=aggregate_file_name,
577
- inidividual_log=inidividual_log,
578
- )
579
- elif type is LoggerType.CLIENT:
580
- if client_key is None:
581
- raise ValueError(
582
- "Argument 'client_key' can not be None if 'logger_type' is 'client'"
583
- )
584
- return Client(
585
- dir=dir,
586
- client_key=client_key,
587
- environment=environment,
588
- service_key=service_key,
589
- level=level,
590
- google_cloud_logging=google_cloud_logging,
591
- labels=labels,
592
- aggregate_file_name=aggregate_file_name,
593
- inidividual_log=inidividual_log,
594
- )
595
- elif type is LoggerType.CONTROLLER:
596
- return Controller(
597
- dir=dir,
598
- environment=environment,
599
- service_key=service_key,
600
- level=level,
601
- google_cloud_logging=google_cloud_logging,
602
- labels=labels,
603
- aggregate_file_name=aggregate_file_name,
604
- inidividual_log=inidividual_log,
605
- )
606
- elif type is LoggerType.DATABASE:
607
- return Database(
608
- dir=dir,
609
- environment=environment,
610
- service_key=service_key,
611
- level=level,
612
- google_cloud_logging=google_cloud_logging,
613
- labels=labels,
614
- aggregate_file_name=aggregate_file_name,
615
- inidividual_log=inidividual_log,
616
- )
617
- elif type is LoggerType.EXCEPTION:
618
- return Exception(
619
- dir=dir,
620
- environment=environment,
621
- service_key=service_key,
622
- level=level,
623
- google_cloud_logging=google_cloud_logging,
624
- labels=labels,
625
- aggregate_file_name=aggregate_file_name,
626
- inidividual_log=inidividual_log,
627
- )
628
- elif type is LoggerType.MIDDLEWARE:
629
- return Middleware(
630
- dir=dir,
631
- environment=environment,
632
- service_key=service_key,
633
- level=level,
634
- google_cloud_logging=google_cloud_logging,
635
- labels=labels,
636
- aggregate_file_name=aggregate_file_name,
637
- inidividual_log=inidividual_log,
638
- )
639
- elif type is LoggerType.REPOSITORY:
640
- return Repository(
641
- dir=dir,
642
- environment=environment,
643
- service_key=service_key,
644
- level=level,
645
- google_cloud_logging=google_cloud_logging,
646
- labels=labels,
647
- aggregate_file_name=aggregate_file_name,
648
- inidividual_log=inidividual_log,
649
- )
650
- elif type is LoggerType.SERVICE:
651
- return Service(
652
- dir=dir,
653
- environment=environment,
654
- service_key=service_key,
655
- level=level,
656
- google_cloud_logging=google_cloud_logging,
657
- labels=labels,
658
- aggregate_file_name=aggregate_file_name,
659
- inidividual_log=inidividual_log,
660
- )
File without changes
File without changes
File without changes