adapta 3.3.22a532.dev6__py3-none-any.whl → 3.5.13__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.
- adapta/__init__.py +1 -1
- adapta/_version.py +1 -1
- adapta/connectors/__init__.py +1 -1
- adapta/connectors/service_bus/__init__.py +1 -1
- adapta/connectors/service_bus/_connector.py +2 -3
- adapta/logs/__init__.py +1 -1
- adapta/logs/_async_logger.py +34 -23
- adapta/logs/_base.py +21 -21
- adapta/logs/_internal.py +6 -7
- adapta/logs/_internal_logger.py +69 -15
- adapta/logs/_logger_interface.py +9 -10
- adapta/logs/handlers/__init__.py +1 -1
- adapta/logs/handlers/datadog_api_handler.py +7 -7
- adapta/logs/handlers/safe_stream_handler.py +4 -4
- adapta/logs/models/__init__.py +1 -1
- adapta/logs/models/_log_level.py +1 -1
- adapta/logs/models/_logs_metadata.py +4 -5
- adapta/metrics/__init__.py +1 -1
- adapta/metrics/_base.py +14 -15
- adapta/metrics/providers/__init__.py +1 -1
- adapta/metrics/providers/datadog_provider.py +21 -22
- adapta/metrics/providers/void_provider.py +34 -0
- adapta/ml/__init__.py +1 -1
- adapta/ml/_model.py +1 -1
- adapta/ml/mlflow/__init__.py +1 -1
- adapta/ml/mlflow/_client.py +24 -6
- adapta/ml/mlflow/_functions.py +23 -16
- adapta/process_communication/__init__.py +1 -1
- adapta/process_communication/_models.py +7 -6
- adapta/schema_management/README.md +0 -1
- adapta/schema_management/__init__.py +1 -1
- adapta/schema_management/schema_entity.py +3 -3
- adapta/security/__init__.py +1 -1
- adapta/security/clients/__init__.py +1 -1
- adapta/security/clients/_azure_client.py +13 -12
- adapta/security/clients/_base.py +6 -6
- adapta/security/clients/_local_client.py +6 -6
- adapta/security/clients/aws/__init__.py +1 -1
- adapta/security/clients/aws/_aws_client.py +10 -9
- adapta/security/clients/aws/_aws_credentials.py +7 -8
- adapta/security/clients/hashicorp_vault/__init__.py +1 -1
- adapta/security/clients/hashicorp_vault/hashicorp_vault_client.py +5 -5
- adapta/security/clients/hashicorp_vault/kubernetes_client.py +2 -2
- adapta/security/clients/hashicorp_vault/oidc_client.py +2 -2
- adapta/security/clients/hashicorp_vault/token_client.py +2 -2
- adapta/storage/__init__.py +1 -1
- adapta/storage/blob/README.md +14 -10
- adapta/storage/blob/__init__.py +1 -1
- adapta/storage/blob/azure_storage_client.py +15 -14
- adapta/storage/blob/base.py +11 -10
- adapta/storage/blob/local_storage_client.py +11 -10
- adapta/storage/blob/s3_storage_client.py +14 -13
- adapta/storage/cache/__init__.py +1 -1
- adapta/storage/cache/_base.py +5 -5
- adapta/storage/cache/redis_cache.py +5 -5
- adapta/storage/database/__init__.py +1 -1
- adapta/storage/database/v2/__init__.py +1 -1
- adapta/storage/database/v2/azure_sql.py +5 -6
- adapta/storage/database/v2/models/__init__.py +1 -1
- adapta/storage/database/v2/models/_models.py +2 -3
- adapta/storage/database/v2/odbc.py +13 -12
- adapta/storage/database/v2/snowflake_sql.py +12 -12
- adapta/storage/database/v2/trino_sql.py +7 -6
- adapta/storage/database/v3/__init__.py +1 -1
- adapta/storage/database/v3/azure_sql.py +5 -7
- adapta/storage/database/v3/models/__init__.py +1 -1
- adapta/storage/database/v3/models/_models.py +2 -3
- adapta/storage/database/v3/odbc.py +12 -11
- adapta/storage/database/v3/snowflake_sql.py +12 -12
- adapta/storage/database/v3/trino_sql.py +3 -2
- adapta/storage/delta_lake/__init__.py +1 -1
- adapta/storage/delta_lake/v2/__init__.py +1 -1
- adapta/storage/delta_lake/v2/_functions.py +23 -23
- adapta/storage/delta_lake/v2/_models.py +4 -5
- adapta/storage/delta_lake/v3/__init__.py +1 -1
- adapta/storage/delta_lake/v3/_functions.py +23 -23
- adapta/storage/delta_lake/v3/_models.py +4 -5
- adapta/storage/distributed_object_store/__init__.py +1 -1
- adapta/storage/distributed_object_store/v2/__init__.py +1 -1
- adapta/storage/distributed_object_store/v2/datastax_astra/__init__.py +1 -1
- adapta/storage/distributed_object_store/v2/datastax_astra/_models.py +1 -1
- adapta/storage/distributed_object_store/v2/datastax_astra/astra_client.py +52 -51
- adapta/storage/distributed_object_store/v3/__init__.py +1 -1
- adapta/storage/distributed_object_store/v3/datastax_astra/__init__.py +1 -1
- adapta/storage/distributed_object_store/v3/datastax_astra/_model_mappers.py +63 -64
- adapta/storage/distributed_object_store/v3/datastax_astra/_models.py +3 -3
- adapta/storage/distributed_object_store/v3/datastax_astra/astra_client.py +52 -42
- adapta/storage/exceptions.py +1 -1
- adapta/storage/models/__init__.py +1 -1
- adapta/storage/models/_functions.py +5 -32
- adapta/storage/models/astra.py +4 -4
- adapta/storage/models/aws.py +1 -1
- adapta/storage/models/azure.py +2 -3
- adapta/storage/models/base.py +9 -1
- adapta/storage/models/enum.py +2 -0
- adapta/storage/models/filter_expression.py +46 -5
- adapta/storage/models/format.py +16 -355
- adapta/storage/models/formatters/__init__.py +36 -0
- adapta/storage/models/formatters/dict.py +43 -0
- adapta/storage/models/formatters/exceptions.py +7 -0
- adapta/storage/models/formatters/metaframe.py +48 -0
- adapta/storage/models/formatters/pandas.py +139 -0
- adapta/storage/models/formatters/pickle.py +36 -0
- adapta/storage/models/formatters/polars.py +240 -0
- adapta/storage/models/formatters/unit.py +26 -0
- adapta/storage/models/hive.py +5 -6
- adapta/storage/models/local.py +1 -1
- adapta/storage/models/trino.py +56 -0
- adapta/storage/query_enabled_store/__init__.py +6 -1
- adapta/storage/query_enabled_store/_models.py +10 -8
- adapta/storage/query_enabled_store/_qes_astra.py +10 -9
- adapta/storage/query_enabled_store/_qes_delta.py +8 -7
- adapta/storage/query_enabled_store/_qes_local.py +2 -1
- adapta/storage/query_enabled_store/_qes_trino.py +133 -0
- adapta/storage/secrets/__init__.py +1 -1
- adapta/storage/secrets/_base.py +5 -4
- adapta/storage/secrets/azure_secret_client.py +3 -4
- adapta/storage/secrets/hashicorp_vault_secret_storage_client.py +5 -5
- adapta/utils/__init__.py +1 -1
- adapta/utils/_common.py +14 -14
- adapta/utils/_requests.py +2 -3
- adapta/utils/concurrent_task_runner.py +10 -9
- adapta/utils/data_structures/_functions.py +6 -6
- adapta/utils/decorators/_logging.py +3 -3
- adapta/utils/decorators/_rate_limit.py +2 -2
- adapta/utils/metaframe.py +32 -8
- adapta/utils/python_typing/_functions.py +5 -10
- {adapta-3.3.22a532.dev6.dist-info → adapta-3.5.13.dist-info}/METADATA +6 -5
- adapta-3.5.13.dist-info/RECORD +146 -0
- {adapta-3.3.22a532.dev6.dist-info → adapta-3.5.13.dist-info}/WHEEL +1 -1
- adapta-3.3.22a532.dev6.dist-info/RECORD +0 -135
- {adapta-3.3.22a532.dev6.dist-info → adapta-3.5.13.dist-info/licenses}/LICENSE +0 -0
adapta/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Global index.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
# Copyright (c) 2023-
|
|
5
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
6
6
|
#
|
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
8
|
# you may not use this file except in compliance with the License.
|
adapta/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '
|
|
1
|
+
__version__ = '3.5.13'
|
adapta/connectors/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""init file"""
|
|
2
2
|
|
|
3
|
-
# Copyright (c) 2023-
|
|
3
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
4
4
|
#
|
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
6
|
# you may not use this file except in compliance with the License.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Connector for Azure Service Bus.
|
|
3
3
|
"""
|
|
4
|
-
# Copyright (c) 2023-
|
|
4
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
# limitations under the License.
|
|
17
17
|
#
|
|
18
18
|
|
|
19
|
-
from typing import Optional
|
|
20
19
|
import os
|
|
21
20
|
from azure.servicebus import (
|
|
22
21
|
ServiceBusSender,
|
|
@@ -31,7 +30,7 @@ class AzureServiceBusConnector:
|
|
|
31
30
|
Connector for Azure Service Bus.
|
|
32
31
|
"""
|
|
33
32
|
|
|
34
|
-
def __init__(self, conn_str:
|
|
33
|
+
def __init__(self, conn_str: str | None = None, queue_name: str | None = None):
|
|
35
34
|
self.service_bus_client: ServiceBusClient = ServiceBusClient.from_connection_string(
|
|
36
35
|
conn_str=conn_str if conn_str is not None else os.environ["SERVICE_BUS_CONNECTION_STRING"],
|
|
37
36
|
transport_type=TransportType.Amqp,
|
adapta/logs/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Module index.
|
|
3
3
|
"""
|
|
4
|
-
# Copyright (c) 2023-
|
|
4
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
adapta/logs/_async_logger.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
import asyncio
|
|
5
5
|
|
|
6
|
-
# Copyright (c) 2023-
|
|
6
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
7
7
|
#
|
|
8
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
9
|
# you may not use this file except in compliance with the License.
|
|
@@ -19,11 +19,12 @@ import asyncio
|
|
|
19
19
|
#
|
|
20
20
|
|
|
21
21
|
import logging
|
|
22
|
+
import sys
|
|
22
23
|
import threading
|
|
23
24
|
from contextlib import asynccontextmanager
|
|
24
25
|
from logging.handlers import QueueHandler, QueueListener
|
|
25
|
-
from
|
|
26
|
-
from typing import final, TypeVar, Generic
|
|
26
|
+
from queue import Queue
|
|
27
|
+
from typing import final, TypeVar, Generic
|
|
27
28
|
|
|
28
29
|
from adapta.logs._internal import MetadataLogger
|
|
29
30
|
from adapta.logs._internal_logger import _InternalLogger
|
|
@@ -38,11 +39,11 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
38
39
|
Asyncio-safe wrapper for MetadataLogger
|
|
39
40
|
"""
|
|
40
41
|
|
|
41
|
-
def redirect(self, tags:
|
|
42
|
+
def redirect(self, tags: dict[str, str] | None = None, **kwargs):
|
|
42
43
|
return self._redirect(logger=self._logger, tags=tags)
|
|
43
44
|
|
|
44
45
|
@asynccontextmanager
|
|
45
|
-
async def redirect_async(self, tags:
|
|
46
|
+
async def redirect_async(self, tags: dict[str, str] | None = None, **kwargs):
|
|
46
47
|
is_active = False
|
|
47
48
|
tmp_symlink_out = b""
|
|
48
49
|
tmp_symlink_err = b""
|
|
@@ -57,16 +58,26 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
57
58
|
# externally control the flushing process
|
|
58
59
|
while is_active:
|
|
59
60
|
start_position_out = self._flush_and_log(
|
|
60
|
-
pos=start_position_out,
|
|
61
|
+
pos=start_position_out,
|
|
62
|
+
tmp_symlink=tmp_symlink_out,
|
|
63
|
+
logger=self._logger,
|
|
64
|
+
tags=tags,
|
|
65
|
+
channel=sys.stdout,
|
|
61
66
|
)
|
|
62
67
|
start_position_err = self._flush_and_log(
|
|
63
|
-
pos=start_position_err,
|
|
68
|
+
pos=start_position_err,
|
|
69
|
+
tmp_symlink=tmp_symlink_err,
|
|
70
|
+
logger=self._logger,
|
|
71
|
+
tags=tags,
|
|
72
|
+
channel=sys.stderr,
|
|
64
73
|
)
|
|
65
74
|
await asyncio.sleep(0.1)
|
|
66
75
|
|
|
67
76
|
return self._flush_and_log(
|
|
68
|
-
pos=start_position_out, tmp_symlink=tmp_symlink_out, logger=self._logger, tags=tags
|
|
69
|
-
), self._flush_and_log(
|
|
77
|
+
pos=start_position_out, tmp_symlink=tmp_symlink_out, logger=self._logger, tags=tags, channel=sys.stdout
|
|
78
|
+
), self._flush_and_log(
|
|
79
|
+
pos=start_position_err, tmp_symlink=tmp_symlink_err, logger=self._logger, tags=tags, channel=sys.stderr
|
|
80
|
+
)
|
|
70
81
|
|
|
71
82
|
self._handle_unsupported_redirect(tags)
|
|
72
83
|
libc, saved_stdout, saved_stderr, tmp_file_out, tmp_file_err = self._prepare_redirect()
|
|
@@ -86,8 +97,8 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
86
97
|
self,
|
|
87
98
|
name: str,
|
|
88
99
|
min_log_level: LogLevel,
|
|
89
|
-
log_handlers:
|
|
90
|
-
fixed_template:
|
|
100
|
+
log_handlers: list[logging.Handler],
|
|
101
|
+
fixed_template: dict[str, dict[str, str]] | None = None,
|
|
91
102
|
fixed_template_delimiter=", ",
|
|
92
103
|
global_tags: dict[str, str] | None = None,
|
|
93
104
|
):
|
|
@@ -98,14 +109,14 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
98
109
|
self._logger_queue_handler = QueueHandler(self._logger_message_queue)
|
|
99
110
|
self._logger.addHandler(self._logger_queue_handler)
|
|
100
111
|
self._log_handlers = log_handlers
|
|
101
|
-
self._listener:
|
|
112
|
+
self._listener: QueueListener | None = None
|
|
102
113
|
self._is_active: bool = False
|
|
103
114
|
self._lock = threading.RLock()
|
|
104
115
|
|
|
105
116
|
def info(
|
|
106
117
|
self,
|
|
107
118
|
template: str,
|
|
108
|
-
tags:
|
|
119
|
+
tags: dict[str, str] | None = None,
|
|
109
120
|
**kwargs,
|
|
110
121
|
) -> None:
|
|
111
122
|
"""
|
|
@@ -121,8 +132,8 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
121
132
|
def warning(
|
|
122
133
|
self,
|
|
123
134
|
template: str,
|
|
124
|
-
exception:
|
|
125
|
-
tags:
|
|
135
|
+
exception: BaseException | None = None,
|
|
136
|
+
tags: dict[str, str] | None = None,
|
|
126
137
|
**kwargs,
|
|
127
138
|
) -> None:
|
|
128
139
|
"""
|
|
@@ -139,8 +150,8 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
139
150
|
def error(
|
|
140
151
|
self,
|
|
141
152
|
template: str,
|
|
142
|
-
exception:
|
|
143
|
-
tags:
|
|
153
|
+
exception: BaseException | None = None,
|
|
154
|
+
tags: dict[str, str] | None = None,
|
|
144
155
|
**kwargs,
|
|
145
156
|
) -> None:
|
|
146
157
|
"""
|
|
@@ -157,9 +168,9 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
157
168
|
def debug(
|
|
158
169
|
self,
|
|
159
170
|
template: str,
|
|
160
|
-
exception:
|
|
161
|
-
diagnostics:
|
|
162
|
-
tags:
|
|
171
|
+
exception: BaseException | None = None,
|
|
172
|
+
diagnostics: str | None = None, # pylint: disable=R0913
|
|
173
|
+
tags: dict[str, str] | None = None,
|
|
163
174
|
**kwargs,
|
|
164
175
|
) -> None:
|
|
165
176
|
"""
|
|
@@ -206,10 +217,10 @@ class _AsyncLogger(Generic[TLogger], _InternalLogger):
|
|
|
206
217
|
|
|
207
218
|
|
|
208
219
|
def create_async_logger(
|
|
209
|
-
logger_type:
|
|
210
|
-
log_handlers:
|
|
220
|
+
logger_type: type[TLogger],
|
|
221
|
+
log_handlers: list[logging.Handler],
|
|
211
222
|
min_log_level: LogLevel = LogLevel.INFO,
|
|
212
|
-
fixed_template:
|
|
223
|
+
fixed_template: dict[str, dict[str, str]] | None = None,
|
|
213
224
|
fixed_template_delimiter=", ",
|
|
214
225
|
global_tags: dict[str, str] = None,
|
|
215
226
|
) -> _AsyncLogger[TLogger]:
|
adapta/logs/_base.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Adapta Logging Interface.
|
|
3
3
|
"""
|
|
4
|
-
# Copyright (c) 2023-
|
|
4
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import logging
|
|
20
20
|
from logging import Handler, StreamHandler
|
|
21
|
-
from typing import
|
|
21
|
+
from typing import final
|
|
22
22
|
|
|
23
23
|
from adapta.logs._internal_logger import _InternalLogger
|
|
24
24
|
from adapta.logs.models import LogLevel
|
|
@@ -31,10 +31,10 @@ class SemanticLogger(_InternalLogger):
|
|
|
31
31
|
Proxy for a collection of python loggers that use the same formatting interface.
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
async def redirect_async(self, tags:
|
|
34
|
+
async def redirect_async(self, tags: dict[str, str] | None = None, **kwargs):
|
|
35
35
|
raise NotImplementedError("Async operations are not supported by this logger")
|
|
36
36
|
|
|
37
|
-
def redirect(self, tags:
|
|
37
|
+
def redirect(self, tags: dict[str, str] | None = None, log_source_name: str | None = None, **kwargs):
|
|
38
38
|
return self._redirect(logger=self._get_logger(log_source_name), tags=tags)
|
|
39
39
|
|
|
40
40
|
def start(self) -> None:
|
|
@@ -43,7 +43,7 @@ class SemanticLogger(_InternalLogger):
|
|
|
43
43
|
def stop(self) -> None:
|
|
44
44
|
pass
|
|
45
45
|
|
|
46
|
-
def __init__(self, fixed_template:
|
|
46
|
+
def __init__(self, fixed_template: dict[str, dict[str, str]] | None = None, fixed_template_delimiter=", "):
|
|
47
47
|
"""
|
|
48
48
|
Creates a new instance of a SemanticLogger
|
|
49
49
|
|
|
@@ -51,7 +51,7 @@ class SemanticLogger(_InternalLogger):
|
|
|
51
51
|
:param fixed_template_delimiter: Optional delimiter to use when appending fixed templates.
|
|
52
52
|
"""
|
|
53
53
|
super().__init__(fixed_template, fixed_template_delimiter)
|
|
54
|
-
self._loggers:
|
|
54
|
+
self._loggers: dict[str, logging.Logger] = {}
|
|
55
55
|
self._default_log_source = None
|
|
56
56
|
self._fixed_template = fixed_template
|
|
57
57
|
self._fixed_template_delimiter = fixed_template_delimiter
|
|
@@ -62,7 +62,7 @@ class SemanticLogger(_InternalLogger):
|
|
|
62
62
|
*,
|
|
63
63
|
log_source_name: str,
|
|
64
64
|
min_log_level: LogLevel,
|
|
65
|
-
log_handlers:
|
|
65
|
+
log_handlers: list[Handler] | None = None,
|
|
66
66
|
is_default=False,
|
|
67
67
|
) -> "SemanticLogger":
|
|
68
68
|
"""
|
|
@@ -90,13 +90,13 @@ class SemanticLogger(_InternalLogger):
|
|
|
90
90
|
|
|
91
91
|
return self
|
|
92
92
|
|
|
93
|
-
def __getattr__(self, log_source) ->
|
|
93
|
+
def __getattr__(self, log_source) -> logging.Logger | None:
|
|
94
94
|
if log_source in self._loggers:
|
|
95
95
|
return self._loggers[log_source]
|
|
96
96
|
|
|
97
97
|
return None
|
|
98
98
|
|
|
99
|
-
def _get_logger(self, log_source_name:
|
|
99
|
+
def _get_logger(self, log_source_name: str | None = None) -> MetadataLogger:
|
|
100
100
|
"""
|
|
101
101
|
Retrieves a logger by log source name, or a default logger is log source name is not provided.
|
|
102
102
|
|
|
@@ -117,8 +117,8 @@ class SemanticLogger(_InternalLogger):
|
|
|
117
117
|
def info(
|
|
118
118
|
self,
|
|
119
119
|
template: str,
|
|
120
|
-
tags:
|
|
121
|
-
log_source_name:
|
|
120
|
+
tags: dict[str, str] | None = None,
|
|
121
|
+
log_source_name: str | None = None,
|
|
122
122
|
**kwargs,
|
|
123
123
|
) -> None:
|
|
124
124
|
"""
|
|
@@ -136,9 +136,9 @@ class SemanticLogger(_InternalLogger):
|
|
|
136
136
|
def warning(
|
|
137
137
|
self,
|
|
138
138
|
template: str,
|
|
139
|
-
exception:
|
|
140
|
-
tags:
|
|
141
|
-
log_source_name:
|
|
139
|
+
exception: BaseException | None = None,
|
|
140
|
+
tags: dict[str, str] | None = None,
|
|
141
|
+
log_source_name: str | None = None,
|
|
142
142
|
**kwargs,
|
|
143
143
|
) -> None:
|
|
144
144
|
"""
|
|
@@ -157,9 +157,9 @@ class SemanticLogger(_InternalLogger):
|
|
|
157
157
|
def error(
|
|
158
158
|
self,
|
|
159
159
|
template: str,
|
|
160
|
-
exception:
|
|
161
|
-
tags:
|
|
162
|
-
log_source_name:
|
|
160
|
+
exception: BaseException | None = None,
|
|
161
|
+
tags: dict[str, str] | None = None,
|
|
162
|
+
log_source_name: str | None = None,
|
|
163
163
|
**kwargs,
|
|
164
164
|
) -> None:
|
|
165
165
|
"""
|
|
@@ -178,10 +178,10 @@ class SemanticLogger(_InternalLogger):
|
|
|
178
178
|
def debug(
|
|
179
179
|
self,
|
|
180
180
|
template: str,
|
|
181
|
-
exception:
|
|
182
|
-
diagnostics:
|
|
183
|
-
tags:
|
|
184
|
-
log_source_name:
|
|
181
|
+
exception: BaseException | None = None,
|
|
182
|
+
diagnostics: str | None = None, # pylint: disable=R0913
|
|
183
|
+
tags: dict[str, str] | None = None,
|
|
184
|
+
log_source_name: str | None = None,
|
|
185
185
|
**kwargs,
|
|
186
186
|
) -> None:
|
|
187
187
|
"""
|
adapta/logs/_internal.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Classes for internal use by `adapta.logs` module. Should not be imported outside this module"""
|
|
2
|
-
# Copyright (c) 2023-
|
|
2
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
# you may not use this file except in compliance with the License.
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
#
|
|
16
16
|
|
|
17
17
|
import logging
|
|
18
|
-
from typing import Optional, Dict
|
|
19
18
|
|
|
20
19
|
from adapta.logs.models import CompositeLogMetadata, LogLevel
|
|
21
20
|
|
|
@@ -39,11 +38,11 @@ class MetadataLogger(logging.Logger):
|
|
|
39
38
|
log_level: int,
|
|
40
39
|
msg: str,
|
|
41
40
|
template: str,
|
|
42
|
-
tags:
|
|
43
|
-
diagnostics:
|
|
41
|
+
tags: dict[str, str] | None,
|
|
42
|
+
diagnostics: str | None,
|
|
44
43
|
stack_info: bool,
|
|
45
|
-
metadata_fields:
|
|
46
|
-
exception:
|
|
44
|
+
metadata_fields: dict[str, str] | None,
|
|
45
|
+
exception: BaseException | None,
|
|
47
46
|
):
|
|
48
47
|
"""
|
|
49
48
|
Creates log entry with metadata from Composite Logger
|
|
@@ -77,7 +76,7 @@ class MetadataLogger(logging.Logger):
|
|
|
77
76
|
)
|
|
78
77
|
|
|
79
78
|
|
|
80
|
-
def from_log_level(log_level:
|
|
79
|
+
def from_log_level(log_level: LogLevel | None) -> int | None:
|
|
81
80
|
"""
|
|
82
81
|
Converts adapta log level to logging log level
|
|
83
82
|
"""
|
adapta/logs/_internal_logger.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
import ctypes
|
|
5
5
|
|
|
6
|
-
# Copyright (c) 2023-
|
|
6
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
7
7
|
#
|
|
8
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
9
|
# you may not use this file except in compliance with the License.
|
|
@@ -28,7 +28,7 @@ from abc import ABC
|
|
|
28
28
|
from contextlib import contextmanager
|
|
29
29
|
from threading import Thread
|
|
30
30
|
from time import sleep
|
|
31
|
-
from typing import Any
|
|
31
|
+
from typing import Any, TextIO
|
|
32
32
|
|
|
33
33
|
from adapta.logs._internal import MetadataLogger, from_log_level
|
|
34
34
|
from adapta.logs._logger_interface import LoggerInterface
|
|
@@ -65,6 +65,17 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
65
65
|
|
|
66
66
|
return fixed_args
|
|
67
67
|
|
|
68
|
+
def _get_format_args(self, **kwargs) -> tuple[dict, dict]:
|
|
69
|
+
base_args = self._get_fixed_args()
|
|
70
|
+
duplicates = {}
|
|
71
|
+
for arg_name, arg_value in kwargs.items():
|
|
72
|
+
if arg_name in base_args:
|
|
73
|
+
duplicates[arg_name] = arg_value
|
|
74
|
+
else:
|
|
75
|
+
base_args[arg_name] = arg_value
|
|
76
|
+
|
|
77
|
+
return base_args, duplicates
|
|
78
|
+
|
|
68
79
|
def _get_template(self, template) -> str:
|
|
69
80
|
return (
|
|
70
81
|
self._fixed_template_delimiter.join([template, ", ".join(self._fixed_template.keys())])
|
|
@@ -72,6 +83,30 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
72
83
|
else template
|
|
73
84
|
)
|
|
74
85
|
|
|
86
|
+
def _log_malformed_template(
|
|
87
|
+
self,
|
|
88
|
+
logger: MetadataLogger,
|
|
89
|
+
duplicates: dict[str, str],
|
|
90
|
+
tags: dict[str, str] = None,
|
|
91
|
+
**kwargs,
|
|
92
|
+
) -> None:
|
|
93
|
+
dup_template = " ".join(
|
|
94
|
+
[
|
|
95
|
+
"Duplicated log properties provided:",
|
|
96
|
+
", ".join(map(lambda key: "".join(["{", key, "}"]), duplicates.keys())),
|
|
97
|
+
]
|
|
98
|
+
)
|
|
99
|
+
logger.log_with_metadata(
|
|
100
|
+
logging.WARN,
|
|
101
|
+
msg=dup_template.format(**duplicates),
|
|
102
|
+
template=dup_template,
|
|
103
|
+
tags=(tags or {}) | self._global_tags,
|
|
104
|
+
diagnostics=None,
|
|
105
|
+
stack_info=False,
|
|
106
|
+
exception=None,
|
|
107
|
+
metadata_fields=self._get_metadata_fields(kwargs),
|
|
108
|
+
)
|
|
109
|
+
|
|
75
110
|
def _meta_info(
|
|
76
111
|
self,
|
|
77
112
|
template: str,
|
|
@@ -88,7 +123,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
88
123
|
:param kwargs: Templated arguments (key=value).
|
|
89
124
|
:return:
|
|
90
125
|
"""
|
|
91
|
-
|
|
126
|
+
log_args, duplicates = self._get_format_args(**kwargs)
|
|
127
|
+
msg = self._get_template(template).format(**log_args)
|
|
92
128
|
logger.log_with_metadata(
|
|
93
129
|
logging.INFO,
|
|
94
130
|
msg=msg,
|
|
@@ -99,6 +135,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
99
135
|
exception=None,
|
|
100
136
|
metadata_fields=self._get_metadata_fields(kwargs),
|
|
101
137
|
)
|
|
138
|
+
if len(duplicates) > 0:
|
|
139
|
+
self._log_malformed_template(logger, duplicates, tags, **kwargs)
|
|
102
140
|
|
|
103
141
|
def _meta_warning(
|
|
104
142
|
self,
|
|
@@ -118,7 +156,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
118
156
|
:param kwargs: Templated arguments (key=value).
|
|
119
157
|
:return:
|
|
120
158
|
"""
|
|
121
|
-
|
|
159
|
+
log_args, duplicates = self._get_format_args(**kwargs)
|
|
160
|
+
msg = self._get_template(template).format(**log_args)
|
|
122
161
|
logger.log_with_metadata(
|
|
123
162
|
logging.WARN,
|
|
124
163
|
msg=msg,
|
|
@@ -129,6 +168,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
129
168
|
exception=exception,
|
|
130
169
|
metadata_fields=self._get_metadata_fields(kwargs),
|
|
131
170
|
)
|
|
171
|
+
if len(duplicates) > 0:
|
|
172
|
+
self._log_malformed_template(logger, duplicates, tags, **kwargs)
|
|
132
173
|
|
|
133
174
|
def _meta_error(
|
|
134
175
|
self,
|
|
@@ -148,7 +189,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
148
189
|
:param kwargs: Templated arguments (key=value).
|
|
149
190
|
:return:
|
|
150
191
|
"""
|
|
151
|
-
|
|
192
|
+
log_args, duplicates = self._get_format_args(**kwargs)
|
|
193
|
+
msg = self._get_template(template).format(**log_args)
|
|
152
194
|
logger.log_with_metadata(
|
|
153
195
|
logging.ERROR,
|
|
154
196
|
msg=msg,
|
|
@@ -159,6 +201,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
159
201
|
exception=exception,
|
|
160
202
|
metadata_fields=self._get_metadata_fields(kwargs),
|
|
161
203
|
)
|
|
204
|
+
if len(duplicates) > 0:
|
|
205
|
+
self._log_malformed_template(logger, duplicates, tags, **kwargs)
|
|
162
206
|
|
|
163
207
|
def _meta_debug(
|
|
164
208
|
self,
|
|
@@ -179,7 +223,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
179
223
|
:param kwargs: Templated arguments (key=value).
|
|
180
224
|
:return:
|
|
181
225
|
"""
|
|
182
|
-
|
|
226
|
+
log_args, duplicates = self._get_format_args(**kwargs)
|
|
227
|
+
msg = self._get_template(template).format(**log_args)
|
|
183
228
|
logger.log_with_metadata(
|
|
184
229
|
logging.DEBUG,
|
|
185
230
|
msg=msg,
|
|
@@ -190,6 +235,8 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
190
235
|
exception=exception,
|
|
191
236
|
metadata_fields=self._get_metadata_fields(kwargs),
|
|
192
237
|
)
|
|
238
|
+
if len(duplicates) > 0:
|
|
239
|
+
self._log_malformed_template(logger, duplicates, tags, **kwargs)
|
|
193
240
|
|
|
194
241
|
def _log_redirect_message(
|
|
195
242
|
self,
|
|
@@ -255,20 +302,23 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
255
302
|
pos: int,
|
|
256
303
|
tmp_symlink: bytes,
|
|
257
304
|
logger: MetadataLogger,
|
|
305
|
+
channel: TextIO,
|
|
258
306
|
tags: dict[str, str] | None = None,
|
|
259
307
|
log_level: LogLevel | None = None,
|
|
260
308
|
) -> int:
|
|
261
|
-
|
|
262
|
-
with open(tmp_symlink,
|
|
309
|
+
channel.flush()
|
|
310
|
+
with open(tmp_symlink, encoding="utf-8") as output:
|
|
263
311
|
output.seek(pos)
|
|
264
312
|
for line in output.readlines():
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
313
|
+
clean_line = line.strip("\n")
|
|
314
|
+
if clean_line:
|
|
315
|
+
self._log_redirect_message(
|
|
316
|
+
logger,
|
|
317
|
+
base_template="Redirected output: {message}",
|
|
318
|
+
message=clean_line,
|
|
319
|
+
tags=(tags or {}) | self._global_tags,
|
|
320
|
+
log_level=log_level,
|
|
321
|
+
)
|
|
272
322
|
return output.tell()
|
|
273
323
|
|
|
274
324
|
def _handle_unsupported_redirect(
|
|
@@ -309,6 +359,7 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
309
359
|
logger=logger,
|
|
310
360
|
tags=(tags or {}) | self._global_tags,
|
|
311
361
|
log_level=log_level,
|
|
362
|
+
channel=sys.stdout,
|
|
312
363
|
)
|
|
313
364
|
start_position_err = self._flush_and_log(
|
|
314
365
|
pos=start_position_err,
|
|
@@ -316,6 +367,7 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
316
367
|
logger=logger,
|
|
317
368
|
tags=(tags or {}) | self._global_tags,
|
|
318
369
|
log_level=log_level,
|
|
370
|
+
channel=sys.stderr,
|
|
319
371
|
)
|
|
320
372
|
sleep(0.1)
|
|
321
373
|
|
|
@@ -325,12 +377,14 @@ class _InternalLogger(LoggerInterface, ABC):
|
|
|
325
377
|
logger=logger,
|
|
326
378
|
tags=(tags or {}) | self._global_tags,
|
|
327
379
|
log_level=log_level,
|
|
380
|
+
channel=sys.stdout,
|
|
328
381
|
), self._flush_and_log(
|
|
329
382
|
pos=start_position_err,
|
|
330
383
|
tmp_symlink=tmp_symlink_err,
|
|
331
384
|
logger=logger,
|
|
332
385
|
tags=(tags or {}) | self._global_tags,
|
|
333
386
|
log_level=log_level,
|
|
387
|
+
channel=sys.stderr,
|
|
334
388
|
)
|
|
335
389
|
|
|
336
390
|
self._handle_unsupported_redirect(tags)
|
adapta/logs/_logger_interface.py
CHANGED
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
"""
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from contextlib import contextmanager, asynccontextmanager
|
|
6
|
-
from typing import Optional, Dict
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
# Copyright (c) 2023-
|
|
8
|
+
# Copyright (c) 2023-2026. ECCO Data & AI and other project contributors.
|
|
10
9
|
#
|
|
11
10
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
11
|
# you may not use this file except in compliance with the License.
|
|
@@ -28,14 +27,14 @@ class LoggerInterface(ABC):
|
|
|
28
27
|
"""
|
|
29
28
|
|
|
30
29
|
@abstractmethod
|
|
31
|
-
def info(self, template: str, tags:
|
|
30
|
+
def info(self, template: str, tags: dict[str, str] | None = None, **kwargs):
|
|
32
31
|
"""
|
|
33
32
|
Logs a message on INFO level
|
|
34
33
|
"""
|
|
35
34
|
|
|
36
35
|
@abstractmethod
|
|
37
36
|
def warning(
|
|
38
|
-
self, template: str, exception:
|
|
37
|
+
self, template: str, exception: BaseException | None = None, tags: dict[str, str] | None = None, **kwargs
|
|
39
38
|
):
|
|
40
39
|
"""
|
|
41
40
|
Logs a message on WARN level
|
|
@@ -43,7 +42,7 @@ class LoggerInterface(ABC):
|
|
|
43
42
|
|
|
44
43
|
@abstractmethod
|
|
45
44
|
def error(
|
|
46
|
-
self, template: str, exception:
|
|
45
|
+
self, template: str, exception: BaseException | None = None, tags: dict[str, str] | None = None, **kwargs
|
|
47
46
|
):
|
|
48
47
|
"""
|
|
49
48
|
Logs a message on ERROR level
|
|
@@ -53,9 +52,9 @@ class LoggerInterface(ABC):
|
|
|
53
52
|
def debug(
|
|
54
53
|
self,
|
|
55
54
|
template: str,
|
|
56
|
-
exception:
|
|
57
|
-
diagnostics:
|
|
58
|
-
tags:
|
|
55
|
+
exception: BaseException | None = None,
|
|
56
|
+
diagnostics: str | None = None,
|
|
57
|
+
tags: dict[str, str] | None = None,
|
|
59
58
|
**kwargs
|
|
60
59
|
):
|
|
61
60
|
"""
|
|
@@ -76,7 +75,7 @@ class LoggerInterface(ABC):
|
|
|
76
75
|
|
|
77
76
|
@contextmanager
|
|
78
77
|
@abstractmethod
|
|
79
|
-
def redirect(self, tags:
|
|
78
|
+
def redirect(self, tags: dict[str, str] | None = None, **kwargs):
|
|
80
79
|
"""
|
|
81
80
|
Redirects stdout to a temporary file and dumps its contents as INFO messages
|
|
82
81
|
once the wrapped code block finishes execution. Stdout is restored after the block completes execution.
|
|
@@ -101,7 +100,7 @@ class LoggerInterface(ABC):
|
|
|
101
100
|
|
|
102
101
|
@asynccontextmanager
|
|
103
102
|
@abstractmethod
|
|
104
|
-
async def redirect_async(self, tags:
|
|
103
|
+
async def redirect_async(self, tags: dict[str, str] | None = None, **kwargs):
|
|
105
104
|
"""
|
|
106
105
|
Async version of a redirect. Not supported in sync client
|
|
107
106
|
"""
|
adapta/logs/handlers/__init__.py
CHANGED