provide-foundation 0.0.0.dev2__py3-none-any.whl → 0.0.0.dev3__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/foundation/__init__.py +20 -20
- provide/foundation/archive/__init__.py +1 -1
- provide/foundation/archive/base.py +15 -14
- provide/foundation/archive/bzip2.py +40 -40
- provide/foundation/archive/gzip.py +42 -42
- provide/foundation/archive/operations.py +90 -91
- provide/foundation/archive/tar.py +33 -31
- provide/foundation/archive/zip.py +52 -50
- provide/foundation/asynctools/__init__.py +20 -0
- provide/foundation/asynctools/core.py +126 -0
- provide/foundation/cli/__init__.py +2 -2
- provide/foundation/cli/commands/deps.py +4 -4
- provide/foundation/cli/commands/logs/__init__.py +2 -2
- provide/foundation/cli/commands/logs/generate.py +2 -2
- provide/foundation/cli/commands/logs/query.py +3 -3
- provide/foundation/cli/commands/logs/send.py +2 -2
- provide/foundation/cli/commands/logs/tail.py +2 -2
- provide/foundation/cli/decorators.py +0 -1
- provide/foundation/cli/testing.py +0 -5
- provide/foundation/cli/utils.py +1 -2
- provide/foundation/config/__init__.py +19 -19
- provide/foundation/config/base.py +2 -2
- provide/foundation/config/converters.py +81 -83
- provide/foundation/config/defaults.py +1 -1
- provide/foundation/config/env.py +2 -1
- provide/foundation/config/loader.py +1 -1
- provide/foundation/config/sync.py +8 -6
- provide/foundation/config/types.py +5 -5
- provide/foundation/config/validators.py +4 -4
- provide/foundation/console/output.py +7 -7
- provide/foundation/context/core.py +19 -17
- provide/foundation/crypto/certificates/__init__.py +9 -5
- provide/foundation/crypto/certificates/base.py +2 -2
- provide/foundation/crypto/certificates/certificate.py +48 -19
- provide/foundation/crypto/certificates/factory.py +26 -18
- provide/foundation/crypto/certificates/generator.py +24 -23
- provide/foundation/crypto/certificates/loader.py +24 -16
- provide/foundation/crypto/certificates/operations.py +17 -10
- provide/foundation/crypto/certificates/trust.py +21 -21
- provide/foundation/env/__init__.py +28 -0
- provide/foundation/env/core.py +218 -0
- provide/foundation/errors/__init__.py +3 -2
- provide/foundation/errors/decorators.py +0 -3
- provide/foundation/errors/types.py +0 -1
- provide/foundation/eventsets/display.py +13 -14
- provide/foundation/eventsets/registry.py +61 -31
- provide/foundation/eventsets/resolver.py +50 -46
- provide/foundation/eventsets/sets/das.py +8 -8
- provide/foundation/eventsets/sets/database.py +14 -14
- provide/foundation/eventsets/sets/http.py +21 -21
- provide/foundation/eventsets/sets/llm.py +16 -16
- provide/foundation/eventsets/sets/task_queue.py +13 -13
- provide/foundation/eventsets/types.py +7 -7
- provide/foundation/file/directory.py +1 -1
- provide/foundation/file/lock.py +2 -3
- provide/foundation/hub/components.py +19 -21
- provide/foundation/hub/config.py +25 -19
- provide/foundation/hub/discovery.py +5 -4
- provide/foundation/hub/handlers.py +13 -5
- provide/foundation/hub/lifecycle.py +10 -9
- provide/foundation/hub/manager.py +3 -0
- provide/foundation/hub/processors.py +8 -3
- provide/foundation/integrations/__init__.py +1 -1
- provide/foundation/integrations/openobserve/client.py +2 -2
- provide/foundation/integrations/openobserve/commands.py +9 -9
- provide/foundation/integrations/openobserve/config.py +2 -2
- provide/foundation/integrations/openobserve/otlp.py +2 -2
- provide/foundation/integrations/openobserve/search.py +1 -2
- provide/foundation/integrations/openobserve/streaming.py +1 -1
- provide/foundation/logger/__init__.py +0 -1
- provide/foundation/logger/config/base.py +1 -1
- provide/foundation/logger/config/logging.py +19 -19
- provide/foundation/logger/config/telemetry.py +11 -13
- provide/foundation/logger/factories.py +2 -2
- provide/foundation/logger/processors/main.py +12 -10
- provide/foundation/logger/ratelimit/limiters.py +4 -4
- provide/foundation/logger/ratelimit/processor.py +1 -1
- provide/foundation/logger/setup/coordinator.py +38 -24
- provide/foundation/logger/setup/processors.py +3 -3
- provide/foundation/logger/setup/testing.py +14 -0
- provide/foundation/logger/trace.py +5 -5
- provide/foundation/metrics/__init__.py +1 -1
- provide/foundation/metrics/otel.py +3 -1
- provide/foundation/observability/__init__.py +1 -1
- provide/foundation/process/__init__.py +1 -1
- provide/foundation/process/exit.py +6 -5
- provide/foundation/process/lifecycle.py +41 -18
- provide/foundation/resilience/__init__.py +6 -5
- provide/foundation/resilience/circuit.py +32 -30
- provide/foundation/resilience/decorators.py +58 -42
- provide/foundation/resilience/fallback.py +55 -40
- provide/foundation/resilience/retry.py +67 -65
- provide/foundation/serialization/__init__.py +16 -0
- provide/foundation/serialization/core.py +70 -0
- provide/foundation/streams/config.py +8 -9
- provide/foundation/streams/console.py +3 -3
- provide/foundation/streams/core.py +2 -2
- provide/foundation/streams/file.py +1 -1
- provide/foundation/testing/__init__.py +22 -7
- provide/foundation/testing/archive/__init__.py +7 -7
- provide/foundation/testing/archive/fixtures.py +58 -54
- provide/foundation/testing/cli.py +3 -6
- provide/foundation/testing/common/__init__.py +13 -13
- provide/foundation/testing/common/fixtures.py +27 -30
- provide/foundation/testing/file/__init__.py +15 -15
- provide/foundation/testing/file/content_fixtures.py +65 -92
- provide/foundation/testing/file/directory_fixtures.py +19 -19
- provide/foundation/testing/file/fixtures.py +14 -17
- provide/foundation/testing/file/special_fixtures.py +34 -42
- provide/foundation/testing/logger.py +28 -23
- provide/foundation/testing/mocking/__init__.py +21 -21
- provide/foundation/testing/mocking/fixtures.py +80 -67
- provide/foundation/testing/process/__init__.py +23 -23
- provide/foundation/testing/process/async_fixtures.py +89 -80
- provide/foundation/testing/process/fixtures.py +11 -13
- provide/foundation/testing/process/subprocess_fixtures.py +41 -40
- provide/foundation/testing/threading/__init__.py +17 -17
- provide/foundation/testing/threading/basic_fixtures.py +21 -17
- provide/foundation/testing/threading/data_fixtures.py +18 -16
- provide/foundation/testing/threading/execution_fixtures.py +67 -52
- provide/foundation/testing/threading/fixtures.py +10 -14
- provide/foundation/testing/threading/sync_fixtures.py +21 -18
- provide/foundation/testing/time/__init__.py +11 -11
- provide/foundation/testing/time/fixtures.py +91 -79
- provide/foundation/testing/transport/__init__.py +9 -9
- provide/foundation/testing/transport/fixtures.py +54 -54
- provide/foundation/time/__init__.py +18 -0
- provide/foundation/time/core.py +63 -0
- provide/foundation/tools/__init__.py +2 -2
- provide/foundation/tools/base.py +68 -67
- provide/foundation/tools/cache.py +62 -69
- provide/foundation/tools/downloader.py +51 -56
- provide/foundation/tools/installer.py +51 -57
- provide/foundation/tools/registry.py +38 -45
- provide/foundation/tools/resolver.py +70 -68
- provide/foundation/tools/verifier.py +39 -50
- provide/foundation/tracer/spans.py +1 -13
- provide/foundation/transport/__init__.py +26 -33
- provide/foundation/transport/base.py +32 -30
- provide/foundation/transport/client.py +44 -49
- provide/foundation/transport/config.py +11 -13
- provide/foundation/transport/errors.py +13 -27
- provide/foundation/transport/http.py +69 -55
- provide/foundation/transport/middleware.py +86 -81
- provide/foundation/transport/registry.py +29 -27
- provide/foundation/transport/types.py +6 -6
- provide/foundation/utils/deps.py +3 -2
- provide/foundation/utils/parsing.py +7 -7
- {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/METADATA +2 -2
- provide_foundation-0.0.0.dev3.dist-info/RECORD +233 -0
- provide_foundation-0.0.0.dev2.dist-info/RECORD +0 -225
- {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/WHEEL +0 -0
- {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/entry_points.txt +0 -0
- {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/licenses/LICENSE +0 -0
- {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/top_level.txt +0 -0
@@ -15,14 +15,19 @@ log = get_logger(__name__)
|
|
15
15
|
|
16
16
|
def _get_registry_and_lock():
|
17
17
|
"""Get registry and lock from components module."""
|
18
|
-
from provide.foundation.hub.components import
|
18
|
+
from provide.foundation.hub.components import (
|
19
|
+
ComponentCategory,
|
20
|
+
_registry_lock,
|
21
|
+
get_component_registry,
|
22
|
+
)
|
23
|
+
|
19
24
|
return get_component_registry(), _registry_lock, ComponentCategory
|
20
25
|
|
21
26
|
|
22
27
|
def get_handlers_for_exception(exception: Exception) -> list[RegistryEntry]:
|
23
28
|
"""Get error handlers that can handle the given exception type."""
|
24
29
|
registry, registry_lock, ComponentCategory = _get_registry_and_lock()
|
25
|
-
|
30
|
+
|
26
31
|
with registry_lock:
|
27
32
|
# Get all error handlers
|
28
33
|
all_entries = list(registry)
|
@@ -53,7 +58,10 @@ def get_handlers_for_exception(exception: Exception) -> list[RegistryEntry]:
|
|
53
58
|
|
54
59
|
@with_error_handling(
|
55
60
|
fallback=None,
|
56
|
-
context_provider=lambda: {
|
61
|
+
context_provider=lambda: {
|
62
|
+
"function": "execute_error_handlers",
|
63
|
+
"module": "hub.handlers",
|
64
|
+
},
|
57
65
|
)
|
58
66
|
def execute_error_handlers(
|
59
67
|
exception: Exception, context: dict[str, Any]
|
@@ -76,6 +84,6 @@ def execute_error_handlers(
|
|
76
84
|
|
77
85
|
|
78
86
|
__all__ = [
|
79
|
-
"get_handlers_for_exception",
|
80
87
|
"execute_error_handlers",
|
81
|
-
|
88
|
+
"get_handlers_for_exception",
|
89
|
+
]
|
@@ -17,17 +17,18 @@ log = get_logger(__name__)
|
|
17
17
|
def _get_registry_and_globals():
|
18
18
|
"""Get registry, lock, and initialized components from components module."""
|
19
19
|
from provide.foundation.hub.components import (
|
20
|
-
|
21
|
-
_registry_lock,
|
22
|
-
|
20
|
+
_initialized_components,
|
21
|
+
_registry_lock,
|
22
|
+
get_component_registry,
|
23
23
|
)
|
24
|
+
|
24
25
|
return get_component_registry(), _registry_lock, _initialized_components
|
25
26
|
|
26
27
|
|
27
28
|
def get_or_initialize_component(name: str, dimension: str) -> Any:
|
28
29
|
"""Get component, initializing lazily if needed."""
|
29
30
|
registry, registry_lock, initialized_components = _get_registry_and_globals()
|
30
|
-
|
31
|
+
|
31
32
|
with registry_lock:
|
32
33
|
key = (name, dimension)
|
33
34
|
|
@@ -75,7 +76,7 @@ def get_or_initialize_component(name: str, dimension: str) -> Any:
|
|
75
76
|
async def initialize_async_component(name: str, dimension: str) -> Any:
|
76
77
|
"""Initialize component asynchronously."""
|
77
78
|
registry, registry_lock, initialized_components = _get_registry_and_globals()
|
78
|
-
|
79
|
+
|
79
80
|
with registry_lock:
|
80
81
|
key = (name, dimension)
|
81
82
|
|
@@ -122,7 +123,7 @@ async def initialize_async_component(name: str, dimension: str) -> Any:
|
|
122
123
|
def cleanup_all_components(dimension: str | None = None) -> None:
|
123
124
|
"""Clean up all components in dimension."""
|
124
125
|
registry, registry_lock, _ = _get_registry_and_globals()
|
125
|
-
|
126
|
+
|
126
127
|
with registry_lock:
|
127
128
|
if dimension:
|
128
129
|
entries = [entry for entry in registry if entry.dimension == dimension]
|
@@ -187,8 +188,8 @@ async def initialize_all_async_components() -> None:
|
|
187
188
|
|
188
189
|
|
189
190
|
__all__ = [
|
190
|
-
"get_or_initialize_component",
|
191
|
-
"initialize_async_component",
|
192
191
|
"cleanup_all_components",
|
192
|
+
"get_or_initialize_component",
|
193
193
|
"initialize_all_async_components",
|
194
|
-
|
194
|
+
"initialize_async_component",
|
195
|
+
]
|
@@ -433,6 +433,9 @@ def get_hub() -> Hub:
|
|
433
433
|
# Double-check after acquiring lock
|
434
434
|
if _global_hub is None:
|
435
435
|
_global_hub = Hub()
|
436
|
+
# Bootstrap foundation components now that hub is ready
|
437
|
+
from provide.foundation.hub.components import bootstrap_foundation
|
438
|
+
bootstrap_foundation()
|
436
439
|
|
437
440
|
return _global_hub
|
438
441
|
|
@@ -10,14 +10,19 @@ from provide.foundation.hub.registry import RegistryEntry
|
|
10
10
|
|
11
11
|
def _get_registry_and_lock():
|
12
12
|
"""Get registry and lock from components module."""
|
13
|
-
from provide.foundation.hub.components import
|
13
|
+
from provide.foundation.hub.components import (
|
14
|
+
ComponentCategory,
|
15
|
+
_registry_lock,
|
16
|
+
get_component_registry,
|
17
|
+
)
|
18
|
+
|
14
19
|
return get_component_registry(), _registry_lock, ComponentCategory
|
15
20
|
|
16
21
|
|
17
22
|
def get_processor_pipeline() -> list[RegistryEntry]:
|
18
23
|
"""Get log processors ordered by priority."""
|
19
24
|
registry, registry_lock, ComponentCategory = _get_registry_and_lock()
|
20
|
-
|
25
|
+
|
21
26
|
with registry_lock:
|
22
27
|
# Get all processors
|
23
28
|
all_entries = list(registry)
|
@@ -41,4 +46,4 @@ def get_processors_for_stage(stage: str) -> list[RegistryEntry]:
|
|
41
46
|
__all__ = [
|
42
47
|
"get_processor_pipeline",
|
43
48
|
"get_processors_for_stage",
|
44
|
-
]
|
49
|
+
]
|
@@ -11,7 +11,6 @@ import requests
|
|
11
11
|
from requests.adapters import HTTPAdapter
|
12
12
|
from urllib3.util.retry import Retry
|
13
13
|
|
14
|
-
from provide.foundation.logger import get_logger
|
15
14
|
from provide.foundation.integrations.openobserve.auth import (
|
16
15
|
get_auth_headers,
|
17
16
|
validate_credentials,
|
@@ -27,6 +26,7 @@ from provide.foundation.integrations.openobserve.models import (
|
|
27
26
|
StreamInfo,
|
28
27
|
parse_relative_time,
|
29
28
|
)
|
29
|
+
from provide.foundation.logger import get_logger
|
30
30
|
|
31
31
|
log = get_logger(__name__)
|
32
32
|
|
@@ -42,7 +42,7 @@ class OpenObserveClient:
|
|
42
42
|
organization: str = "default",
|
43
43
|
timeout: int = 30,
|
44
44
|
max_retries: int = 3,
|
45
|
-
):
|
45
|
+
) -> None:
|
46
46
|
"""Initialize OpenObserve client.
|
47
47
|
|
48
48
|
Args:
|
@@ -27,7 +27,7 @@ if _HAS_CLICK:
|
|
27
27
|
|
28
28
|
@click.group("openobserve", help="Query and manage OpenObserve logs")
|
29
29
|
@click.pass_context
|
30
|
-
def openobserve_group(ctx):
|
30
|
+
def openobserve_group(ctx: click.Context) -> None:
|
31
31
|
"""OpenObserve log querying and streaming commands."""
|
32
32
|
# Initialize client and store in context
|
33
33
|
try:
|
@@ -75,7 +75,7 @@ if _HAS_CLICK:
|
|
75
75
|
help="Pretty print JSON output",
|
76
76
|
)
|
77
77
|
@click.pass_obj
|
78
|
-
def query_command(client, sql, start, end, size, format, pretty):
|
78
|
+
def query_command(client: "OpenObserveClient | None", sql: str, start: str, end: str, size: int, format: str, pretty: bool) -> int | None:
|
79
79
|
"""Execute SQL query against OpenObserve logs."""
|
80
80
|
if client is None:
|
81
81
|
click.echo(
|
@@ -134,7 +134,7 @@ if _HAS_CLICK:
|
|
134
134
|
help="Output format",
|
135
135
|
)
|
136
136
|
@click.pass_obj
|
137
|
-
def tail_command(client, stream, filter_sql, lines, follow, format):
|
137
|
+
def tail_command(client: "OpenObserveClient | None", stream: str, filter_sql: str | None, lines: int, follow: bool, format: str) -> int | None:
|
138
138
|
"""Tail logs from OpenObserve (like 'tail -f')."""
|
139
139
|
if client is None:
|
140
140
|
click.echo(
|
@@ -191,7 +191,7 @@ if _HAS_CLICK:
|
|
191
191
|
help="Output format",
|
192
192
|
)
|
193
193
|
@click.pass_obj
|
194
|
-
def errors_command(client, stream, start, size, format):
|
194
|
+
def errors_command(client: "OpenObserveClient | None", stream: str, start: str, size: int, format: str) -> int | None:
|
195
195
|
"""Search for error logs."""
|
196
196
|
if client is None:
|
197
197
|
click.echo("OpenObserve not configured.", err=True)
|
@@ -233,7 +233,7 @@ if _HAS_CLICK:
|
|
233
233
|
help="Output format",
|
234
234
|
)
|
235
235
|
@click.pass_obj
|
236
|
-
def trace_command(client, trace_id, stream, format):
|
236
|
+
def trace_command(client: "OpenObserveClient | None", trace_id: str, stream: str, format: str) -> int | None:
|
237
237
|
"""Search for logs by trace ID."""
|
238
238
|
if client is None:
|
239
239
|
click.echo("OpenObserve not configured.", err=True)
|
@@ -260,7 +260,7 @@ if _HAS_CLICK:
|
|
260
260
|
|
261
261
|
@openobserve_group.command("streams")
|
262
262
|
@click.pass_obj
|
263
|
-
def streams_command(client):
|
263
|
+
def streams_command(client: "OpenObserveClient | None") -> int | None:
|
264
264
|
"""List available streams."""
|
265
265
|
if client is None:
|
266
266
|
click.echo("OpenObserve not configured.", err=True)
|
@@ -297,7 +297,7 @@ if _HAS_CLICK:
|
|
297
297
|
help="Filter by stream name",
|
298
298
|
)
|
299
299
|
@click.pass_obj
|
300
|
-
def history_command(client, size, stream):
|
300
|
+
def history_command(client: "OpenObserveClient | None", size: int, stream: str | None) -> int | None:
|
301
301
|
"""View search history."""
|
302
302
|
if client is None:
|
303
303
|
click.echo("OpenObserve not configured.", err=True)
|
@@ -326,7 +326,7 @@ if _HAS_CLICK:
|
|
326
326
|
|
327
327
|
@openobserve_group.command("test")
|
328
328
|
@click.pass_obj
|
329
|
-
def test_command(client):
|
329
|
+
def test_command(client: "OpenObserveClient | None") -> int | None:
|
330
330
|
"""Test connection to OpenObserve."""
|
331
331
|
if client is None:
|
332
332
|
click.echo("OpenObserve not configured.", err=True)
|
@@ -347,7 +347,7 @@ if _HAS_CLICK:
|
|
347
347
|
|
348
348
|
else:
|
349
349
|
# Stub when click is not available
|
350
|
-
def openobserve_group(*args, **kwargs):
|
350
|
+
def openobserve_group(*args: object, **kwargs: object) -> None:
|
351
351
|
"""OpenObserve command stub when click is not available."""
|
352
352
|
raise ImportError(
|
353
353
|
"CLI commands require optional dependencies. "
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
from attrs import define
|
4
4
|
|
5
|
-
from provide.foundation.config.env import RuntimeConfig
|
6
5
|
from provide.foundation.config.base import field
|
6
|
+
from provide.foundation.config.env import RuntimeConfig
|
7
7
|
|
8
8
|
|
9
9
|
@define(slots=True, repr=False)
|
@@ -34,4 +34,4 @@ class OpenObserveConfig(RuntimeConfig):
|
|
34
34
|
default=None,
|
35
35
|
env_var="OPENOBSERVE_STREAM",
|
36
36
|
description="OpenObserve stream name",
|
37
|
-
)
|
37
|
+
)
|
@@ -6,8 +6,8 @@ from datetime import datetime
|
|
6
6
|
import json
|
7
7
|
from typing import Any
|
8
8
|
|
9
|
-
from provide.foundation.logger import get_logger
|
10
9
|
from provide.foundation.integrations.openobserve.client import OpenObserveClient
|
10
|
+
from provide.foundation.logger import get_logger
|
11
11
|
|
12
12
|
log = get_logger(__name__)
|
13
13
|
|
@@ -15,7 +15,7 @@ log = get_logger(__name__)
|
|
15
15
|
try:
|
16
16
|
from opentelemetry import trace
|
17
17
|
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
|
18
|
-
from opentelemetry.sdk._logs import LoggerProvider
|
18
|
+
from opentelemetry.sdk._logs import LoggerProvider
|
19
19
|
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
|
20
20
|
from opentelemetry.sdk.resources import Resource
|
21
21
|
from opentelemetry.semconv.resource import ResourceAttributes
|
@@ -2,10 +2,9 @@
|
|
2
2
|
Search operations for OpenObserve.
|
3
3
|
"""
|
4
4
|
|
5
|
-
|
6
|
-
from provide.foundation.logger import get_logger
|
7
5
|
from provide.foundation.integrations.openobserve.client import OpenObserveClient
|
8
6
|
from provide.foundation.integrations.openobserve.models import SearchResponse
|
7
|
+
from provide.foundation.logger import get_logger
|
9
8
|
|
10
9
|
log = get_logger(__name__)
|
11
10
|
|
@@ -9,13 +9,13 @@ from typing import Any
|
|
9
9
|
|
10
10
|
import requests
|
11
11
|
|
12
|
-
from provide.foundation.logger import get_logger
|
13
12
|
from provide.foundation.integrations.openobserve.auth import get_auth_headers
|
14
13
|
from provide.foundation.integrations.openobserve.client import OpenObserveClient
|
15
14
|
from provide.foundation.integrations.openobserve.exceptions import (
|
16
15
|
OpenObserveStreamingError,
|
17
16
|
)
|
18
17
|
from provide.foundation.integrations.openobserve.models import parse_relative_time
|
18
|
+
from provide.foundation.logger import get_logger
|
19
19
|
|
20
20
|
log = get_logger(__name__)
|
21
21
|
|
@@ -8,7 +8,6 @@ Re-exports key components related to logging functionality.
|
|
8
8
|
|
9
9
|
# Import trace module early to ensure PrintLogger gets patched
|
10
10
|
from provide.foundation.logger import trace # noqa: F401
|
11
|
-
|
12
11
|
from provide.foundation.logger.base import (
|
13
12
|
FoundationLogger, # Class definition
|
14
13
|
get_logger, # Factory function
|
@@ -9,22 +9,7 @@ from pathlib import Path
|
|
9
9
|
|
10
10
|
from attrs import define
|
11
11
|
|
12
|
-
from provide.foundation.config.env import RuntimeConfig
|
13
12
|
from provide.foundation.config.base import field
|
14
|
-
from provide.foundation.config.defaults import (
|
15
|
-
DEFAULT_LOG_LEVEL,
|
16
|
-
DEFAULT_CONSOLE_FORMATTER,
|
17
|
-
DEFAULT_LOGGER_NAME_EMOJI_ENABLED,
|
18
|
-
DEFAULT_DAS_EMOJI_ENABLED,
|
19
|
-
DEFAULT_OMIT_TIMESTAMP,
|
20
|
-
DEFAULT_FOUNDATION_SETUP_LOG_LEVEL,
|
21
|
-
DEFAULT_FOUNDATION_LOG_OUTPUT,
|
22
|
-
DEFAULT_RATE_LIMIT_ENABLED,
|
23
|
-
DEFAULT_RATE_LIMIT_EMIT_WARNINGS,
|
24
|
-
DEFAULT_RATE_LIMIT_GLOBAL,
|
25
|
-
DEFAULT_RATE_LIMIT_GLOBAL_CAPACITY,
|
26
|
-
DEFAULT_RATE_LIMIT_OVERFLOW_POLICY,
|
27
|
-
)
|
28
13
|
from provide.foundation.config.converters import (
|
29
14
|
parse_bool_extended,
|
30
15
|
parse_console_formatter,
|
@@ -34,10 +19,24 @@ from provide.foundation.config.converters import (
|
|
34
19
|
parse_module_levels,
|
35
20
|
parse_rate_limits,
|
36
21
|
validate_log_level,
|
37
|
-
validate_non_negative,
|
38
22
|
validate_overflow_policy,
|
39
23
|
validate_positive,
|
40
24
|
)
|
25
|
+
from provide.foundation.config.defaults import (
|
26
|
+
DEFAULT_CONSOLE_FORMATTER,
|
27
|
+
DEFAULT_DAS_EMOJI_ENABLED,
|
28
|
+
DEFAULT_FOUNDATION_LOG_OUTPUT,
|
29
|
+
DEFAULT_FOUNDATION_SETUP_LOG_LEVEL,
|
30
|
+
DEFAULT_LOG_LEVEL,
|
31
|
+
DEFAULT_LOGGER_NAME_EMOJI_ENABLED,
|
32
|
+
DEFAULT_OMIT_TIMESTAMP,
|
33
|
+
DEFAULT_RATE_LIMIT_EMIT_WARNINGS,
|
34
|
+
DEFAULT_RATE_LIMIT_ENABLED,
|
35
|
+
DEFAULT_RATE_LIMIT_GLOBAL,
|
36
|
+
DEFAULT_RATE_LIMIT_GLOBAL_CAPACITY,
|
37
|
+
DEFAULT_RATE_LIMIT_OVERFLOW_POLICY,
|
38
|
+
)
|
39
|
+
from provide.foundation.config.env import RuntimeConfig
|
41
40
|
from provide.foundation.types import (
|
42
41
|
ConsoleFormatterStr,
|
43
42
|
LogLevelStr,
|
@@ -90,7 +89,7 @@ class LoggingConfig(RuntimeConfig):
|
|
90
89
|
default=None,
|
91
90
|
env_var="PROVIDE_LOG_FILE",
|
92
91
|
converter=lambda x: Path(x) if x else None,
|
93
|
-
description="Path to log file"
|
92
|
+
description="Path to log file",
|
94
93
|
)
|
95
94
|
foundation_setup_log_level: LogLevelStr = field(
|
96
95
|
default=DEFAULT_FOUNDATION_SETUP_LOG_LEVEL,
|
@@ -138,7 +137,9 @@ class LoggingConfig(RuntimeConfig):
|
|
138
137
|
rate_limit_summary_interval: float = field(
|
139
138
|
default=DEFAULT_RATE_LIMIT_GLOBAL,
|
140
139
|
env_var="PROVIDE_LOG_RATE_LIMIT_SUMMARY_INTERVAL",
|
141
|
-
converter=lambda x: parse_float_with_validation(x, min_val=0.0)
|
140
|
+
converter=lambda x: parse_float_with_validation(x, min_val=0.0)
|
141
|
+
if x
|
142
|
+
else DEFAULT_RATE_LIMIT_GLOBAL,
|
142
143
|
validator=validate_positive,
|
143
144
|
description="Seconds between rate limit summary reports",
|
144
145
|
)
|
@@ -161,4 +162,3 @@ class LoggingConfig(RuntimeConfig):
|
|
161
162
|
validator=validate_overflow_policy,
|
162
163
|
description="Policy when queue is full: drop_oldest, drop_newest, or block",
|
163
164
|
)
|
164
|
-
|
@@ -5,24 +5,25 @@
|
|
5
5
|
TelemetryConfig class for Foundation telemetry configuration.
|
6
6
|
"""
|
7
7
|
|
8
|
+
import os
|
9
|
+
|
8
10
|
from attrs import define
|
9
11
|
|
10
|
-
from provide.foundation.config.env import RuntimeConfig
|
11
12
|
from provide.foundation.config.base import field
|
12
|
-
from provide.foundation.config.defaults import (
|
13
|
-
DEFAULT_TELEMETRY_GLOBALLY_DISABLED,
|
14
|
-
DEFAULT_TRACING_ENABLED,
|
15
|
-
DEFAULT_METRICS_ENABLED,
|
16
|
-
DEFAULT_OTLP_PROTOCOL,
|
17
|
-
DEFAULT_TRACE_SAMPLE_RATE,
|
18
|
-
)
|
19
|
-
import os
|
20
13
|
from provide.foundation.config.converters import (
|
21
14
|
parse_bool_extended,
|
22
15
|
parse_headers,
|
23
16
|
parse_sample_rate,
|
24
17
|
validate_sample_rate,
|
25
18
|
)
|
19
|
+
from provide.foundation.config.defaults import (
|
20
|
+
DEFAULT_METRICS_ENABLED,
|
21
|
+
DEFAULT_OTLP_PROTOCOL,
|
22
|
+
DEFAULT_TELEMETRY_GLOBALLY_DISABLED,
|
23
|
+
DEFAULT_TRACE_SAMPLE_RATE,
|
24
|
+
DEFAULT_TRACING_ENABLED,
|
25
|
+
)
|
26
|
+
from provide.foundation.config.env import RuntimeConfig
|
26
27
|
from provide.foundation.logger.config.logging import LoggingConfig
|
27
28
|
|
28
29
|
|
@@ -45,8 +46,7 @@ class TelemetryConfig(RuntimeConfig):
|
|
45
46
|
description="Service version for telemetry",
|
46
47
|
)
|
47
48
|
logging: LoggingConfig = field(
|
48
|
-
factory=lambda: LoggingConfig.from_env(),
|
49
|
-
description="Logging configuration"
|
49
|
+
factory=lambda: LoggingConfig.from_env(), description="Logging configuration"
|
50
50
|
)
|
51
51
|
globally_disabled: bool = field(
|
52
52
|
default=DEFAULT_TELEMETRY_GLOBALLY_DISABLED,
|
@@ -97,8 +97,6 @@ class TelemetryConfig(RuntimeConfig):
|
|
97
97
|
description="Sampling rate for traces (0.0 to 1.0)",
|
98
98
|
)
|
99
99
|
|
100
|
-
|
101
|
-
|
102
100
|
def get_otlp_headers_dict(self) -> dict[str, str]:
|
103
101
|
"""Get OTLP headers dictionary.
|
104
102
|
|
@@ -13,7 +13,7 @@ from provide.foundation.logger.core import logger
|
|
13
13
|
def get_logger(
|
14
14
|
name: str | None = None,
|
15
15
|
emoji: str | None = None,
|
16
|
-
emoji_hierarchy: dict[str, str] | None = None
|
16
|
+
emoji_hierarchy: dict[str, str] | None = None,
|
17
17
|
) -> Any:
|
18
18
|
"""
|
19
19
|
Get a logger instance with the given name and optional emoji customization.
|
@@ -30,7 +30,7 @@ def get_logger(
|
|
30
30
|
"""
|
31
31
|
# Emoji hierarchy removed - using event sets now
|
32
32
|
# emoji and emoji_hierarchy parameters are deprecated
|
33
|
-
|
33
|
+
|
34
34
|
return logger.get_logger(name)
|
35
35
|
|
36
36
|
|
@@ -7,7 +7,7 @@ Structlog processors for Foundation Telemetry.
|
|
7
7
|
|
8
8
|
import json
|
9
9
|
import logging as stdlib_logging
|
10
|
-
from typing import
|
10
|
+
from typing import Any, TextIO, cast
|
11
11
|
|
12
12
|
import structlog
|
13
13
|
|
@@ -26,7 +26,6 @@ from provide.foundation.types import (
|
|
26
26
|
LogLevelStr,
|
27
27
|
)
|
28
28
|
|
29
|
-
|
30
29
|
_LEVEL_TO_NUMERIC: dict[LogLevelStr, int] = {
|
31
30
|
"CRITICAL": stdlib_logging.CRITICAL,
|
32
31
|
"ERROR": stdlib_logging.ERROR,
|
@@ -70,24 +69,29 @@ def _config_create_timestamp_processors(
|
|
70
69
|
|
71
70
|
|
72
71
|
def _config_create_event_enrichment_processors(
|
73
|
-
logging_config: LoggingConfig
|
72
|
+
logging_config: LoggingConfig,
|
74
73
|
) -> list[StructlogProcessor]:
|
75
74
|
processors: list[StructlogProcessor] = []
|
76
75
|
if logging_config.logger_name_emoji_prefix_enabled:
|
77
76
|
processors.append(cast(StructlogProcessor, add_logger_name_emoji_prefix))
|
78
77
|
if logging_config.das_emoji_prefix_enabled:
|
78
|
+
|
79
79
|
def add_event_enrichment_processor(
|
80
80
|
_logger: Any, _method_name: str, event_dict: structlog.types.EventDict
|
81
81
|
) -> structlog.types.EventDict:
|
82
82
|
# Lazy import to avoid circular dependency
|
83
|
-
from provide.foundation.eventsets.resolver import get_resolver
|
84
83
|
from provide.foundation.eventsets.registry import discover_event_sets
|
85
|
-
|
84
|
+
from provide.foundation.eventsets.resolver import get_resolver
|
85
|
+
|
86
86
|
# Initialize on first use
|
87
|
-
if not hasattr(add_event_enrichment_processor,
|
87
|
+
if not hasattr(add_event_enrichment_processor, "_initialized"):
|
88
|
+
from provide.foundation.logger.setup.coordinator import create_foundation_internal_logger
|
89
|
+
setup_logger = create_foundation_internal_logger()
|
90
|
+
setup_logger.trace("Initializing event enrichment processor")
|
88
91
|
discover_event_sets()
|
89
92
|
add_event_enrichment_processor._initialized = True
|
90
|
-
|
93
|
+
setup_logger.trace("Event enrichment processor initialized")
|
94
|
+
|
91
95
|
resolver = get_resolver()
|
92
96
|
return resolver.enrich_event(event_dict)
|
93
97
|
|
@@ -95,9 +99,7 @@ def _config_create_event_enrichment_processors(
|
|
95
99
|
return processors
|
96
100
|
|
97
101
|
|
98
|
-
def _build_core_processors_list(
|
99
|
-
config: TelemetryConfig
|
100
|
-
) -> list[StructlogProcessor]:
|
102
|
+
def _build_core_processors_list(config: TelemetryConfig) -> list[StructlogProcessor]:
|
101
103
|
log_cfg = config.logging
|
102
104
|
processors: list[StructlogProcessor] = [
|
103
105
|
structlog.contextvars.merge_contextvars,
|
@@ -17,7 +17,7 @@ class SyncRateLimiter:
|
|
17
17
|
Thread-safe implementation suitable for synchronous logging operations.
|
18
18
|
"""
|
19
19
|
|
20
|
-
def __init__(self, capacity: float, refill_rate: float):
|
20
|
+
def __init__(self, capacity: float, refill_rate: float) -> None:
|
21
21
|
"""
|
22
22
|
Initialize the rate limiter.
|
23
23
|
|
@@ -87,7 +87,7 @@ class AsyncRateLimiter:
|
|
87
87
|
Uses asyncio.Lock for thread safety in async contexts.
|
88
88
|
"""
|
89
89
|
|
90
|
-
def __init__(self, capacity: float, refill_rate: float):
|
90
|
+
def __init__(self, capacity: float, refill_rate: float) -> None:
|
91
91
|
"""
|
92
92
|
Initialize the async rate limiter.
|
93
93
|
|
@@ -160,7 +160,7 @@ class GlobalRateLimiter:
|
|
160
160
|
_instance = None
|
161
161
|
_lock = threading.Lock()
|
162
162
|
|
163
|
-
def __new__(cls):
|
163
|
+
def __new__(cls) -> "GlobalRateLimiter":
|
164
164
|
if cls._instance is None:
|
165
165
|
with cls._lock:
|
166
166
|
if cls._instance is None:
|
@@ -168,7 +168,7 @@ class GlobalRateLimiter:
|
|
168
168
|
cls._instance._initialized = False
|
169
169
|
return cls._instance
|
170
170
|
|
171
|
-
def __init__(self):
|
171
|
+
def __init__(self) -> None:
|
172
172
|
if self._initialized:
|
173
173
|
return
|
174
174
|
|
@@ -107,7 +107,7 @@ class RateLimiterProcessor:
|
|
107
107
|
stats = self.rate_limiter.get_stats()
|
108
108
|
|
109
109
|
# Check if there's been any rate limiting activity
|
110
|
-
global_stats = stats.get("global"
|
110
|
+
global_stats = stats.get("global") or {}
|
111
111
|
total_denied = global_stats.get("total_denied", 0)
|
112
112
|
|
113
113
|
if not self.suppressed_counts and total_denied == 0:
|