jaylog 0.2.0__tar.gz → 0.2.2__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.3
2
2
  Name: jaylog
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Customized Python logging library with file rotation and HTTP forwarding
5
5
  Author: Gpocas
6
6
  Author-email: Gpocas <gpocas01@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "jaylog"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "Customized Python logging library with file rotation and HTTP forwarding"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -13,14 +13,39 @@ from jaylog.settings import JaylogSettings
13
13
  # Registry: name -> (logger, listener) so callers can shut down cleanly
14
14
  _registry: dict[str, tuple[logging.Logger, QueueListener]] = {}
15
15
  _shutdown_registered = False
16
- _default_settings: JaylogSettings | None = None
16
+ # name (== app_name) -> settings registrada via configure()
17
+ _settings_registry: dict[str, JaylogSettings] = {}
17
18
 
18
19
 
19
- def configure(settings: JaylogSettings) -> None:
20
- """Configure as settings padrão globais usadas por get_logger()."""
21
- global _default_settings
22
- _default_settings = settings
20
+ def configure(settings: JaylogSettings | list[JaylogSettings]) -> None:
21
+ """
22
+ Registra uma ou mais configurações de logger.
23
+
24
+ Aceita uma única ``JaylogSettings`` ou uma lista delas. Cada configuração é
25
+ registrada sob o seu próprio ``app_name``, permitindo vários loggers com
26
+ configurações diferentes no mesmo projeto::
27
+
28
+ configure(settings_order)
29
+ configure([settings_order, settings_billing])
30
+
31
+ Cada chamada é a "fonte da verdade" do conjunto de loggers: derruba os
32
+ loggers registrados anteriormente e registra apenas os informados aqui.
33
+ Levanta ``ValueError`` se a lista contiver ``app_name`` duplicado.
34
+ """
35
+ items = [settings] if isinstance(settings, JaylogSettings) else list(settings)
36
+
37
+ seen: set[str] = set()
38
+ for item in items:
39
+ if item.app_name in seen:
40
+ raise ValueError(
41
+ f"app_name duplicado em configure(): '{item.app_name}'"
42
+ )
43
+ seen.add(item.app_name)
44
+
23
45
  shutdown()
46
+ _settings_registry.clear()
47
+ for item in items:
48
+ _settings_registry[item.app_name] = item
24
49
 
25
50
 
26
51
  def _register_shutdown_hooks() -> None:
@@ -39,13 +64,14 @@ def _register_shutdown_hooks() -> None:
39
64
  signal.signal(signal.SIGTERM, _sigterm_handler)
40
65
 
41
66
 
42
- def get_logger() -> logging.Logger:
67
+ def get_logger(name: str | None = None) -> logging.Logger:
43
68
  """
44
69
  Return a configured logger.
45
70
 
46
- The logger name is read from JAYLOG_LOGGER_NAME (default: "jaylog").
47
- Calling this multiple times with the same logger name returns the **same**
48
- logger without re-attaching handlers.
71
+ O ``name`` deve ser exatamente o ``app_name`` de uma configuração registrada
72
+ via ``configure()``. Quando omitido, retorna o logger da **primeira**
73
+ configuração registrada. Chamadas repetidas com o mesmo nome retornam o
74
+ **mesmo** logger, sem re-anexar handlers.
49
75
 
50
76
  Architecture:
51
77
  logger → QueueHandler → Queue → QueueListener → [FileHandler, HttpHandler?]
@@ -53,12 +79,22 @@ def get_logger() -> logging.Logger:
53
79
  The QueueListener runs in a background thread so `emit()` never blocks the
54
80
  calling thread.
55
81
  """
56
- if _default_settings is None:
57
- settings = JaylogSettings() # ty:ignore[missing-argument]
58
- else:
59
- settings = _default_settings
82
+ if not _settings_registry:
83
+ raise Exception(
84
+ 'Não é possivel retornar uma instancia de logger sem configuração\n'
85
+ 'use jaylog.configure() antes de jaylog.get_logger()'
86
+ )
87
+
88
+ if name is None:
89
+ name = next(iter(_settings_registry))
90
+ elif name not in _settings_registry:
91
+ disponiveis = ', '.join(_settings_registry) or '(nenhum)'
92
+ raise KeyError(
93
+ f"Nenhuma configuração registrada para '{name}'. "
94
+ f"Nomes disponíveis: {disponiveis}"
95
+ )
60
96
 
61
- name = settings.app_name
97
+ settings = _settings_registry[name]
62
98
 
63
99
  configure_screenshot(settings.log_screenshot_enabled)
64
100
 
@@ -17,11 +17,17 @@ class JaylogSettings(BaseSettings):
17
17
  )
18
18
 
19
19
  _env_file: str | tuple | None = None
20
+ _secrets_dir: str | None = None
20
21
 
21
- def __init__(self, _env_file=None, **data):
22
- _env_file = self.model_config.get('env_file') if _env_file is None else _env_file
23
- super().__init__(_env_file=_env_file, **data)
22
+ def __init__(
23
+ self,
24
+ _env_file=model_config.get('env_file'),
25
+ _secrets_dir=model_config.get('secrets_dir'),
26
+ **data
27
+ ):
28
+ super().__init__(_env_file=_env_file, _secrets_dir=_secrets_dir, **data)
24
29
  object.__setattr__(self, '_env_file', _env_file)
30
+ object.__setattr__(self, '_secrets_dir', _secrets_dir)
25
31
 
26
32
  # App identity
27
33
  app_name: str
@@ -60,6 +66,12 @@ class JaylogSettings(BaseSettings):
60
66
  if self.secrets_dir:
61
67
  if not self.secrets_dir.exists() or not self.secrets_dir.is_dir:
62
68
  raise ValueError('SECRETS_DIR is not valid directory')
69
+
70
+ elif self._secrets_dir != self.model_config.get('secrets_dir'):
71
+ raise SyntaxError(
72
+ 'Não é possivel usar `reload_secrets` caso o valor de _secrets_dir foi sobrescrito'
73
+ )
74
+
63
75
 
64
76
 
65
77
  return JaylogSettings(
File without changes
File without changes
File without changes
File without changes
File without changes