provide-foundation 0.0.0.dev0__py3-none-any.whl
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.
- provide/__init__.py +15 -0
- provide/foundation/__init__.py +155 -0
- provide/foundation/_version.py +58 -0
- provide/foundation/cli/__init__.py +67 -0
- provide/foundation/cli/commands/__init__.py +3 -0
- provide/foundation/cli/commands/deps.py +71 -0
- provide/foundation/cli/commands/logs/__init__.py +63 -0
- provide/foundation/cli/commands/logs/generate.py +357 -0
- provide/foundation/cli/commands/logs/generate_old.py +569 -0
- provide/foundation/cli/commands/logs/query.py +174 -0
- provide/foundation/cli/commands/logs/send.py +166 -0
- provide/foundation/cli/commands/logs/tail.py +112 -0
- provide/foundation/cli/decorators.py +262 -0
- provide/foundation/cli/main.py +65 -0
- provide/foundation/cli/testing.py +220 -0
- provide/foundation/cli/utils.py +210 -0
- provide/foundation/config/__init__.py +106 -0
- provide/foundation/config/base.py +295 -0
- provide/foundation/config/env.py +369 -0
- provide/foundation/config/loader.py +311 -0
- provide/foundation/config/manager.py +387 -0
- provide/foundation/config/schema.py +284 -0
- provide/foundation/config/sync.py +281 -0
- provide/foundation/config/types.py +78 -0
- provide/foundation/config/validators.py +80 -0
- provide/foundation/console/__init__.py +29 -0
- provide/foundation/console/input.py +364 -0
- provide/foundation/console/output.py +178 -0
- provide/foundation/context/__init__.py +12 -0
- provide/foundation/context/core.py +356 -0
- provide/foundation/core.py +20 -0
- provide/foundation/crypto/__init__.py +182 -0
- provide/foundation/crypto/algorithms.py +111 -0
- provide/foundation/crypto/certificates.py +896 -0
- provide/foundation/crypto/checksums.py +301 -0
- provide/foundation/crypto/constants.py +57 -0
- provide/foundation/crypto/hashing.py +265 -0
- provide/foundation/crypto/keys.py +188 -0
- provide/foundation/crypto/signatures.py +144 -0
- provide/foundation/crypto/utils.py +164 -0
- provide/foundation/errors/__init__.py +96 -0
- provide/foundation/errors/auth.py +73 -0
- provide/foundation/errors/base.py +81 -0
- provide/foundation/errors/config.py +103 -0
- provide/foundation/errors/context.py +299 -0
- provide/foundation/errors/decorators.py +484 -0
- provide/foundation/errors/handlers.py +360 -0
- provide/foundation/errors/integration.py +105 -0
- provide/foundation/errors/platform.py +37 -0
- provide/foundation/errors/process.py +140 -0
- provide/foundation/errors/resources.py +133 -0
- provide/foundation/errors/runtime.py +160 -0
- provide/foundation/errors/safe_decorators.py +133 -0
- provide/foundation/errors/types.py +276 -0
- provide/foundation/file/__init__.py +79 -0
- provide/foundation/file/atomic.py +157 -0
- provide/foundation/file/directory.py +134 -0
- provide/foundation/file/formats.py +236 -0
- provide/foundation/file/lock.py +175 -0
- provide/foundation/file/safe.py +179 -0
- provide/foundation/file/utils.py +170 -0
- provide/foundation/hub/__init__.py +88 -0
- provide/foundation/hub/click_builder.py +310 -0
- provide/foundation/hub/commands.py +42 -0
- provide/foundation/hub/components.py +640 -0
- provide/foundation/hub/decorators.py +244 -0
- provide/foundation/hub/info.py +32 -0
- provide/foundation/hub/manager.py +446 -0
- provide/foundation/hub/registry.py +279 -0
- provide/foundation/hub/type_mapping.py +54 -0
- provide/foundation/hub/types.py +28 -0
- provide/foundation/logger/__init__.py +41 -0
- provide/foundation/logger/base.py +22 -0
- provide/foundation/logger/config/__init__.py +16 -0
- provide/foundation/logger/config/base.py +40 -0
- provide/foundation/logger/config/logging.py +394 -0
- provide/foundation/logger/config/telemetry.py +188 -0
- provide/foundation/logger/core.py +239 -0
- provide/foundation/logger/custom_processors.py +172 -0
- provide/foundation/logger/emoji/__init__.py +44 -0
- provide/foundation/logger/emoji/matrix.py +209 -0
- provide/foundation/logger/emoji/sets.py +458 -0
- provide/foundation/logger/emoji/types.py +56 -0
- provide/foundation/logger/factories.py +56 -0
- provide/foundation/logger/processors/__init__.py +13 -0
- provide/foundation/logger/processors/main.py +254 -0
- provide/foundation/logger/processors/trace.py +113 -0
- provide/foundation/logger/ratelimit/__init__.py +31 -0
- provide/foundation/logger/ratelimit/limiters.py +294 -0
- provide/foundation/logger/ratelimit/processor.py +203 -0
- provide/foundation/logger/ratelimit/queue_limiter.py +305 -0
- provide/foundation/logger/setup/__init__.py +29 -0
- provide/foundation/logger/setup/coordinator.py +138 -0
- provide/foundation/logger/setup/emoji_resolver.py +64 -0
- provide/foundation/logger/setup/processors.py +85 -0
- provide/foundation/logger/setup/testing.py +39 -0
- provide/foundation/logger/trace.py +38 -0
- provide/foundation/metrics/__init__.py +119 -0
- provide/foundation/metrics/otel.py +122 -0
- provide/foundation/metrics/simple.py +165 -0
- provide/foundation/observability/__init__.py +53 -0
- provide/foundation/observability/openobserve/__init__.py +79 -0
- provide/foundation/observability/openobserve/auth.py +72 -0
- provide/foundation/observability/openobserve/client.py +307 -0
- provide/foundation/observability/openobserve/commands.py +357 -0
- provide/foundation/observability/openobserve/exceptions.py +41 -0
- provide/foundation/observability/openobserve/formatters.py +298 -0
- provide/foundation/observability/openobserve/models.py +134 -0
- provide/foundation/observability/openobserve/otlp.py +320 -0
- provide/foundation/observability/openobserve/search.py +222 -0
- provide/foundation/observability/openobserve/streaming.py +235 -0
- provide/foundation/platform/__init__.py +44 -0
- provide/foundation/platform/detection.py +193 -0
- provide/foundation/platform/info.py +157 -0
- provide/foundation/process/__init__.py +39 -0
- provide/foundation/process/async_runner.py +373 -0
- provide/foundation/process/lifecycle.py +406 -0
- provide/foundation/process/runner.py +390 -0
- provide/foundation/setup/__init__.py +101 -0
- provide/foundation/streams/__init__.py +44 -0
- provide/foundation/streams/console.py +57 -0
- provide/foundation/streams/core.py +65 -0
- provide/foundation/streams/file.py +104 -0
- provide/foundation/testing/__init__.py +166 -0
- provide/foundation/testing/cli.py +227 -0
- provide/foundation/testing/crypto.py +163 -0
- provide/foundation/testing/fixtures.py +49 -0
- provide/foundation/testing/hub.py +23 -0
- provide/foundation/testing/logger.py +106 -0
- provide/foundation/testing/streams.py +54 -0
- provide/foundation/tracer/__init__.py +49 -0
- provide/foundation/tracer/context.py +115 -0
- provide/foundation/tracer/otel.py +135 -0
- provide/foundation/tracer/spans.py +174 -0
- provide/foundation/types.py +32 -0
- provide/foundation/utils/__init__.py +97 -0
- provide/foundation/utils/deps.py +195 -0
- provide/foundation/utils/env.py +491 -0
- provide/foundation/utils/formatting.py +483 -0
- provide/foundation/utils/parsing.py +235 -0
- provide/foundation/utils/rate_limiting.py +112 -0
- provide/foundation/utils/streams.py +67 -0
- provide/foundation/utils/timing.py +93 -0
- provide_foundation-0.0.0.dev0.dist-info/METADATA +469 -0
- provide_foundation-0.0.0.dev0.dist-info/RECORD +149 -0
- provide_foundation-0.0.0.dev0.dist-info/WHEEL +5 -0
- provide_foundation-0.0.0.dev0.dist-info/entry_points.txt +2 -0
- provide_foundation-0.0.0.dev0.dist-info/licenses/LICENSE +201 -0
- provide_foundation-0.0.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,279 @@
|
|
1
|
+
"""Registry management for the foundation.
|
2
|
+
|
3
|
+
Provides both generic multi-dimensional registry functionality and
|
4
|
+
specialized command registry management.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from collections import defaultdict
|
8
|
+
from collections.abc import Iterator
|
9
|
+
import threading
|
10
|
+
from typing import Any
|
11
|
+
|
12
|
+
from attrs import define, field
|
13
|
+
|
14
|
+
from provide.foundation.errors.resources import AlreadyExistsError
|
15
|
+
from provide.foundation.logger import get_logger
|
16
|
+
|
17
|
+
log = get_logger(__name__)
|
18
|
+
|
19
|
+
|
20
|
+
@define(frozen=True, slots=True)
|
21
|
+
class RegistryEntry:
|
22
|
+
"""A single entry in the registry."""
|
23
|
+
|
24
|
+
name: str
|
25
|
+
dimension: str
|
26
|
+
value: Any
|
27
|
+
metadata: dict[str, Any] = field(factory=lambda: {})
|
28
|
+
|
29
|
+
@property
|
30
|
+
def key(self) -> tuple[str, str]:
|
31
|
+
"""Get the registry key for this entry."""
|
32
|
+
return (self.dimension, self.name)
|
33
|
+
|
34
|
+
|
35
|
+
class Registry:
|
36
|
+
"""
|
37
|
+
Multi-dimensional registry for storing and retrieving objects.
|
38
|
+
|
39
|
+
Supports hierarchical organization by dimension (component, command, etc.)
|
40
|
+
and name within each dimension. This is a generic registry that can be
|
41
|
+
used for any type of object storage and retrieval.
|
42
|
+
|
43
|
+
Thread-safe: All operations are protected by an RLock for safe concurrent access.
|
44
|
+
"""
|
45
|
+
|
46
|
+
def __init__(self) -> None:
|
47
|
+
"""Initialize an empty registry."""
|
48
|
+
self._lock = threading.RLock() # Reentrant lock for thread safety
|
49
|
+
self._registry: dict[str, dict[str, RegistryEntry]] = defaultdict(dict)
|
50
|
+
self._aliases: dict[str, tuple[str, str]] = {}
|
51
|
+
|
52
|
+
def register(
|
53
|
+
self,
|
54
|
+
name: str,
|
55
|
+
value: Any,
|
56
|
+
dimension: str = "default",
|
57
|
+
metadata: dict[str, Any] | None = None,
|
58
|
+
aliases: list[str] | None = None,
|
59
|
+
replace: bool = False,
|
60
|
+
) -> RegistryEntry:
|
61
|
+
"""
|
62
|
+
Register an item in the registry.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
name: Unique name within the dimension
|
66
|
+
value: The item to register
|
67
|
+
dimension: Registry dimension for categorization
|
68
|
+
metadata: Optional metadata about the item
|
69
|
+
aliases: Optional list of aliases for this item
|
70
|
+
replace: Whether to replace existing entries
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
The created registry entry
|
74
|
+
|
75
|
+
Raises:
|
76
|
+
ValueError: If name already exists and replace=False
|
77
|
+
"""
|
78
|
+
with self._lock:
|
79
|
+
if not replace and name in self._registry[dimension]:
|
80
|
+
raise AlreadyExistsError(
|
81
|
+
f"Item '{name}' already registered in dimension '{dimension}'. "
|
82
|
+
"Use replace=True to override.",
|
83
|
+
code="REGISTRY_ITEM_EXISTS",
|
84
|
+
item_name=name,
|
85
|
+
dimension=dimension,
|
86
|
+
)
|
87
|
+
|
88
|
+
entry = RegistryEntry(
|
89
|
+
name=name,
|
90
|
+
dimension=dimension,
|
91
|
+
value=value,
|
92
|
+
metadata=metadata or {},
|
93
|
+
)
|
94
|
+
|
95
|
+
self._registry[dimension][name] = entry
|
96
|
+
|
97
|
+
if aliases:
|
98
|
+
for alias in aliases:
|
99
|
+
self._aliases[alias] = (dimension, name)
|
100
|
+
|
101
|
+
log.debug(
|
102
|
+
"Registered item",
|
103
|
+
name=name,
|
104
|
+
dimension=dimension,
|
105
|
+
has_metadata=bool(metadata),
|
106
|
+
aliases=aliases,
|
107
|
+
)
|
108
|
+
|
109
|
+
return entry
|
110
|
+
|
111
|
+
def get(
|
112
|
+
self,
|
113
|
+
name: str,
|
114
|
+
dimension: str | None = None,
|
115
|
+
) -> Any | None:
|
116
|
+
"""
|
117
|
+
Get an item from the registry.
|
118
|
+
|
119
|
+
Args:
|
120
|
+
name: Name or alias of the item
|
121
|
+
dimension: Optional dimension to search in
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
The registered value or None if not found
|
125
|
+
"""
|
126
|
+
with self._lock:
|
127
|
+
if dimension is not None:
|
128
|
+
entry = self._registry[dimension].get(name)
|
129
|
+
if entry:
|
130
|
+
return entry.value
|
131
|
+
|
132
|
+
if name in self._aliases:
|
133
|
+
dim_key, real_name = self._aliases[name]
|
134
|
+
if dimension is None or dim_key == dimension:
|
135
|
+
entry = self._registry[dim_key].get(real_name)
|
136
|
+
if entry:
|
137
|
+
return entry.value
|
138
|
+
|
139
|
+
if dimension is None:
|
140
|
+
for dim_registry in self._registry.values():
|
141
|
+
if name in dim_registry:
|
142
|
+
return dim_registry[name].value
|
143
|
+
|
144
|
+
return None
|
145
|
+
|
146
|
+
def get_entry(
|
147
|
+
self,
|
148
|
+
name: str,
|
149
|
+
dimension: str | None = None,
|
150
|
+
) -> RegistryEntry | None:
|
151
|
+
"""Get the full registry entry."""
|
152
|
+
with self._lock:
|
153
|
+
if dimension is not None:
|
154
|
+
return self._registry[dimension].get(name)
|
155
|
+
|
156
|
+
if name in self._aliases:
|
157
|
+
dim_key, real_name = self._aliases[name]
|
158
|
+
if dimension is None or dim_key == dimension:
|
159
|
+
return self._registry[dim_key].get(real_name)
|
160
|
+
|
161
|
+
if dimension is None:
|
162
|
+
for dim_registry in self._registry.values():
|
163
|
+
if name in dim_registry:
|
164
|
+
return dim_registry[name]
|
165
|
+
|
166
|
+
return None
|
167
|
+
|
168
|
+
def list_dimension(
|
169
|
+
self,
|
170
|
+
dimension: str,
|
171
|
+
) -> list[str]:
|
172
|
+
"""List all names in a dimension."""
|
173
|
+
with self._lock:
|
174
|
+
return list(self._registry[dimension].keys())
|
175
|
+
|
176
|
+
def list_all(self) -> dict[str, list[str]]:
|
177
|
+
"""List all dimensions and their items."""
|
178
|
+
with self._lock:
|
179
|
+
return {
|
180
|
+
dimension: list(items.keys())
|
181
|
+
for dimension, items in self._registry.items()
|
182
|
+
}
|
183
|
+
|
184
|
+
def remove(
|
185
|
+
self,
|
186
|
+
name: str,
|
187
|
+
dimension: str | None = None,
|
188
|
+
) -> bool:
|
189
|
+
"""
|
190
|
+
Remove an item from the registry.
|
191
|
+
|
192
|
+
Returns:
|
193
|
+
True if item was removed, False if not found
|
194
|
+
"""
|
195
|
+
with self._lock:
|
196
|
+
if dimension is not None:
|
197
|
+
if name in self._registry[dimension]:
|
198
|
+
del self._registry[dimension][name]
|
199
|
+
|
200
|
+
aliases_to_remove = [
|
201
|
+
alias
|
202
|
+
for alias, (dim, n) in self._aliases.items()
|
203
|
+
if dim == dimension and n == name
|
204
|
+
]
|
205
|
+
for alias in aliases_to_remove:
|
206
|
+
del self._aliases[alias]
|
207
|
+
|
208
|
+
log.debug("Removed item", name=name, dimension=dimension)
|
209
|
+
return True
|
210
|
+
else:
|
211
|
+
for dim_key, dim_registry in self._registry.items():
|
212
|
+
if name in dim_registry:
|
213
|
+
del dim_registry[name]
|
214
|
+
|
215
|
+
aliases_to_remove = [
|
216
|
+
alias
|
217
|
+
for alias, (d, n) in self._aliases.items()
|
218
|
+
if d == dim_key and n == name
|
219
|
+
]
|
220
|
+
for alias in aliases_to_remove:
|
221
|
+
del self._aliases[alias]
|
222
|
+
|
223
|
+
log.debug("Removed item", name=name, dimension=dim_key)
|
224
|
+
return True
|
225
|
+
|
226
|
+
return False
|
227
|
+
|
228
|
+
def clear(self, dimension: str | None = None) -> None:
|
229
|
+
"""Clear the registry or a specific dimension."""
|
230
|
+
with self._lock:
|
231
|
+
if dimension is not None:
|
232
|
+
self._registry[dimension].clear()
|
233
|
+
|
234
|
+
aliases_to_remove = [
|
235
|
+
alias
|
236
|
+
for alias, (dim, _) in self._aliases.items()
|
237
|
+
if dim == dimension
|
238
|
+
]
|
239
|
+
for alias in aliases_to_remove:
|
240
|
+
del self._aliases[alias]
|
241
|
+
else:
|
242
|
+
self._registry.clear()
|
243
|
+
self._aliases.clear()
|
244
|
+
|
245
|
+
def __contains__(self, key: str | tuple[str, str]) -> bool:
|
246
|
+
"""Check if an item exists in the registry."""
|
247
|
+
with self._lock:
|
248
|
+
if isinstance(key, tuple):
|
249
|
+
dimension, name = key
|
250
|
+
return name in self._registry[dimension]
|
251
|
+
else:
|
252
|
+
return any(key in dim_reg for dim_reg in self._registry.values())
|
253
|
+
|
254
|
+
def __iter__(self) -> Iterator[RegistryEntry]:
|
255
|
+
"""Iterate over all registry entries."""
|
256
|
+
with self._lock:
|
257
|
+
# Create a snapshot to avoid holding lock during iteration
|
258
|
+
entries = []
|
259
|
+
for dim_registry in self._registry.values():
|
260
|
+
entries.extend(dim_registry.values())
|
261
|
+
# Yield outside the lock
|
262
|
+
yield from entries
|
263
|
+
|
264
|
+
def __len__(self) -> int:
|
265
|
+
"""Get total number of registered items."""
|
266
|
+
with self._lock:
|
267
|
+
return sum(len(dim_reg) for dim_reg in self._registry.values())
|
268
|
+
|
269
|
+
|
270
|
+
# Global registry for commands
|
271
|
+
_command_registry = Registry()
|
272
|
+
|
273
|
+
|
274
|
+
def get_command_registry() -> Registry:
|
275
|
+
"""Get the global command registry."""
|
276
|
+
return _command_registry
|
277
|
+
|
278
|
+
|
279
|
+
__all__ = ["Registry", "RegistryEntry", "get_command_registry"]
|
@@ -0,0 +1,54 @@
|
|
1
|
+
"""Type system and Click type mapping utilities."""
|
2
|
+
|
3
|
+
import types
|
4
|
+
import typing
|
5
|
+
from typing import Any, get_args, get_origin
|
6
|
+
|
7
|
+
|
8
|
+
def extract_click_type(annotation: Any) -> type:
|
9
|
+
"""
|
10
|
+
Extract a Click-compatible type from a Python type annotation.
|
11
|
+
|
12
|
+
Handles:
|
13
|
+
- Union types (str | None, Union[str, None])
|
14
|
+
- Optional types (Optional[str])
|
15
|
+
- Regular types (str, int, bool)
|
16
|
+
|
17
|
+
Args:
|
18
|
+
annotation: Type annotation from function signature
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
A type that Click can understand
|
22
|
+
"""
|
23
|
+
# Handle None type
|
24
|
+
if annotation is type(None):
|
25
|
+
return str
|
26
|
+
|
27
|
+
# Get the origin and args for generic types
|
28
|
+
origin = get_origin(annotation)
|
29
|
+
args = get_args(annotation)
|
30
|
+
|
31
|
+
# Handle Union types (including Optional which is Union[T, None])
|
32
|
+
if origin is typing.Union or (
|
33
|
+
hasattr(types, "UnionType") and isinstance(annotation, types.UnionType)
|
34
|
+
):
|
35
|
+
# For Python 3.10+ union syntax (str | None)
|
36
|
+
if hasattr(annotation, "__args__"):
|
37
|
+
args = annotation.__args__
|
38
|
+
|
39
|
+
# Filter out None type to get the actual type
|
40
|
+
non_none_types = [t for t in args if t is not type(None)]
|
41
|
+
|
42
|
+
if non_none_types:
|
43
|
+
# Return the first non-None type
|
44
|
+
# Could be enhanced to handle Union[str, int] etc.
|
45
|
+
return non_none_types[0]
|
46
|
+
else:
|
47
|
+
# If only None, default to str
|
48
|
+
return str
|
49
|
+
|
50
|
+
# For non-generic types, return as-is
|
51
|
+
return annotation
|
52
|
+
|
53
|
+
|
54
|
+
__all__ = ["extract_click_type"]
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"""Type definitions for the hub module."""
|
2
|
+
|
3
|
+
from typing import Any, Protocol
|
4
|
+
|
5
|
+
from attrs import define, field
|
6
|
+
|
7
|
+
|
8
|
+
@define(frozen=True, slots=True)
|
9
|
+
class RegistryEntry:
|
10
|
+
"""A single entry in the registry."""
|
11
|
+
|
12
|
+
name: str
|
13
|
+
dimension: str
|
14
|
+
value: Any
|
15
|
+
metadata: dict[str, Any] = field(factory=lambda: {})
|
16
|
+
|
17
|
+
@property
|
18
|
+
def key(self) -> tuple[str, str]:
|
19
|
+
"""Get the registry key for this entry."""
|
20
|
+
return (self.dimension, self.name)
|
21
|
+
|
22
|
+
|
23
|
+
class Registrable(Protocol):
|
24
|
+
"""Protocol for objects that can be registered."""
|
25
|
+
|
26
|
+
__registry_name__: str
|
27
|
+
__registry_dimension__: str
|
28
|
+
__registry_metadata__: dict[str, Any]
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# __init__.py
|
3
|
+
#
|
4
|
+
"""
|
5
|
+
Foundation Telemetry Logger Sub-package.
|
6
|
+
Re-exports key components related to logging functionality.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from provide.foundation.logger.base import (
|
10
|
+
FoundationLogger, # Class definition
|
11
|
+
get_logger, # Factory function
|
12
|
+
logger, # Global instance
|
13
|
+
setup_logger, # Setup function (consistent naming)
|
14
|
+
setup_logging, # Setup function (backward compatibility)
|
15
|
+
)
|
16
|
+
from provide.foundation.logger.config import (
|
17
|
+
LoggingConfig,
|
18
|
+
TelemetryConfig,
|
19
|
+
)
|
20
|
+
from provide.foundation.logger.emoji.matrix import (
|
21
|
+
PRIMARY_EMOJI, # Core domain emojis
|
22
|
+
SECONDARY_EMOJI, # Core action emojis
|
23
|
+
TERTIARY_EMOJI, # Core status emojis
|
24
|
+
show_emoji_matrix, # Utility to display emoji configurations
|
25
|
+
)
|
26
|
+
|
27
|
+
__all__ = [
|
28
|
+
"PRIMARY_EMOJI",
|
29
|
+
"SECONDARY_EMOJI",
|
30
|
+
"TERTIARY_EMOJI",
|
31
|
+
"FoundationLogger",
|
32
|
+
"LoggingConfig",
|
33
|
+
"TelemetryConfig",
|
34
|
+
"get_logger",
|
35
|
+
"logger",
|
36
|
+
"setup_logger", # Consistent naming
|
37
|
+
"setup_logging", # Backward compatibility
|
38
|
+
"show_emoji_matrix",
|
39
|
+
]
|
40
|
+
|
41
|
+
# 🐍📝
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# base.py
|
3
|
+
#
|
4
|
+
"""
|
5
|
+
Foundation Logger - Main Interface.
|
6
|
+
|
7
|
+
Re-exports the core logger components.
|
8
|
+
"""
|
9
|
+
|
10
|
+
from provide.foundation.logger.core import FoundationLogger, logger
|
11
|
+
from provide.foundation.logger.factories import get_logger, setup_logging
|
12
|
+
|
13
|
+
# Alias for consistent naming convention
|
14
|
+
setup_logger = setup_logging
|
15
|
+
|
16
|
+
__all__ = [
|
17
|
+
"FoundationLogger",
|
18
|
+
"get_logger",
|
19
|
+
"logger",
|
20
|
+
"setup_logger", # New consistent naming
|
21
|
+
"setup_logging", # Keep for backward compatibility
|
22
|
+
]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#
|
2
|
+
# __init__.py
|
3
|
+
#
|
4
|
+
"""
|
5
|
+
Foundation Logger Configuration Module.
|
6
|
+
|
7
|
+
Re-exports all configuration classes for convenient importing.
|
8
|
+
"""
|
9
|
+
|
10
|
+
from provide.foundation.logger.config.logging import LoggingConfig
|
11
|
+
from provide.foundation.logger.config.telemetry import TelemetryConfig
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"LoggingConfig",
|
15
|
+
"TelemetryConfig",
|
16
|
+
]
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# base.py
|
3
|
+
#
|
4
|
+
"""
|
5
|
+
Base configuration utilities for Foundation logger.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import sys
|
10
|
+
|
11
|
+
|
12
|
+
def get_config_logger():
|
13
|
+
"""Get logger for config warnings that respects FOUNDATION_LOG_OUTPUT."""
|
14
|
+
import structlog
|
15
|
+
|
16
|
+
from provide.foundation.utils.streams import get_foundation_log_stream
|
17
|
+
|
18
|
+
try:
|
19
|
+
foundation_output = os.getenv("FOUNDATION_LOG_OUTPUT", "stderr").lower()
|
20
|
+
output_stream = get_foundation_log_stream(foundation_output)
|
21
|
+
except Exception:
|
22
|
+
output_stream = sys.stderr
|
23
|
+
|
24
|
+
try:
|
25
|
+
config = structlog.get_config()
|
26
|
+
structlog.configure(
|
27
|
+
processors=config.get("processors", [structlog.dev.ConsoleRenderer()]),
|
28
|
+
logger_factory=structlog.PrintLoggerFactory(file=output_stream),
|
29
|
+
wrapper_class=config.get("wrapper_class", structlog.BoundLogger),
|
30
|
+
cache_logger_on_first_use=config.get("cache_logger_on_first_use", True),
|
31
|
+
)
|
32
|
+
except Exception:
|
33
|
+
structlog.configure(
|
34
|
+
processors=[structlog.dev.ConsoleRenderer()],
|
35
|
+
logger_factory=structlog.PrintLoggerFactory(file=output_stream),
|
36
|
+
wrapper_class=structlog.BoundLogger,
|
37
|
+
cache_logger_on_first_use=True,
|
38
|
+
)
|
39
|
+
|
40
|
+
return structlog.get_logger("provide.foundation.logger.config")
|