chalkpy 2.95.2__py3-none-any.whl → 2.95.4__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.
- chalk/_version.py +1 -1
- chalk/features/feature_set_decorator.py +10 -1
- chalk/sql/_internal/integrations/mssql.py +95 -9
- chalk/utils/missing_dependency.py +5 -4
- chalk/utils/tracing.py +116 -69
- {chalkpy-2.95.2.dist-info → chalkpy-2.95.4.dist-info}/METADATA +1 -1
- {chalkpy-2.95.2.dist-info → chalkpy-2.95.4.dist-info}/RECORD +10 -10
- {chalkpy-2.95.2.dist-info → chalkpy-2.95.4.dist-info}/WHEEL +0 -0
- {chalkpy-2.95.2.dist-info → chalkpy-2.95.4.dist-info}/entry_points.txt +0 -0
- {chalkpy-2.95.2.dist-info → chalkpy-2.95.4.dist-info}/top_level.txt +0 -0
chalk/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.95.
|
|
1
|
+
__version__ = "2.95.4"
|
|
@@ -1311,7 +1311,7 @@ def _process_class(
|
|
|
1311
1311
|
)
|
|
1312
1312
|
cls_cast = cast(Type, cls)
|
|
1313
1313
|
if not f_i.is_typ_set():
|
|
1314
|
-
f_i.typ = ParsedAnnotation(cls_cast, f.
|
|
1314
|
+
f_i.typ = ParsedAnnotation(cls_cast, f.attribute_name)
|
|
1315
1315
|
|
|
1316
1316
|
f_i.features_cls = cls_cast
|
|
1317
1317
|
f_i.attribute_name = f"{f.attribute_name}_v{i}"
|
|
@@ -1329,9 +1329,18 @@ def _process_class(
|
|
|
1329
1329
|
class_cache_strategy=cache_strategy,
|
|
1330
1330
|
error_builder=error_builder,
|
|
1331
1331
|
)
|
|
1332
|
+
|
|
1333
|
+
# copy over expressions for default version
|
|
1334
|
+
if i == f.version.default:
|
|
1335
|
+
if f.underscore_expression is None and f_i.underscore_expression is not None:
|
|
1336
|
+
f.underscore_expression = f_i.underscore_expression
|
|
1337
|
+
if f.offline_underscore_expression is None and f_i.offline_underscore_expression is not None:
|
|
1338
|
+
f.offline_underscore_expression = f_i.offline_underscore_expression
|
|
1339
|
+
|
|
1332
1340
|
f.version.reference[i] = f_i
|
|
1333
1341
|
# The default feature already exists.
|
|
1334
1342
|
f_i.no_display = i == f.version.default
|
|
1343
|
+
cls_fields.append(f_i)
|
|
1335
1344
|
continue
|
|
1336
1345
|
|
|
1337
1346
|
for i in range(1, f.version.maximum + 1):
|
|
@@ -2,15 +2,19 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import struct
|
|
5
|
-
from typing import TYPE_CHECKING, Any, Dict, Mapping, Optional, Union
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Dict, Iterable, Mapping, Optional, Union
|
|
6
6
|
|
|
7
7
|
from chalk.integrations.named import create_integration_variable, load_integration_variable
|
|
8
|
+
from chalk.sql._internal.query_execution_parameters import QueryExecutionParameters
|
|
8
9
|
from chalk.sql._internal.sql_source import BaseSQLSource, SQLSourceKind, TableIngestMixIn
|
|
10
|
+
from chalk.sql.finalized_query import FinalizedChalkQuery
|
|
9
11
|
from chalk.sql.protocols import SQLSourceWithTableIngestProtocol
|
|
12
|
+
from chalk.utils.environment_parsing import env_var_bool
|
|
10
13
|
from chalk.utils.missing_dependency import missing_dependency_exception
|
|
11
14
|
|
|
12
15
|
if TYPE_CHECKING:
|
|
13
|
-
|
|
16
|
+
import pyarrow as pa
|
|
17
|
+
from sqlalchemy.engine import URL, Connection
|
|
14
18
|
|
|
15
19
|
_MSSQL_HOST_NAME = "MSSQL_HOST"
|
|
16
20
|
_MSSQL_TCP_PORT_NAME = "MSSQL_TCP_PORT"
|
|
@@ -42,8 +46,8 @@ class MSSQLSourceImpl(BaseSQLSource, TableIngestMixIn, SQLSourceWithTableIngestP
|
|
|
42
46
|
):
|
|
43
47
|
try:
|
|
44
48
|
import pyodbc
|
|
45
|
-
except ImportError:
|
|
46
|
-
raise missing_dependency_exception("chalkpy[mssql]")
|
|
49
|
+
except ImportError as e:
|
|
50
|
+
raise missing_dependency_exception("chalkpy[mssql]", original_error=e)
|
|
47
51
|
del pyodbc
|
|
48
52
|
|
|
49
53
|
self.name = name
|
|
@@ -142,9 +146,17 @@ class MSSQLSourceImpl(BaseSQLSource, TableIngestMixIn, SQLSourceWithTableIngestP
|
|
|
142
146
|
def local_engine_url(self) -> "URL":
|
|
143
147
|
from sqlalchemy.engine.url import URL
|
|
144
148
|
|
|
149
|
+
trust_server_cert = env_var_bool("CHALK_MSSQL_TRUST_SERVER_CERTIFICATE", default=False)
|
|
150
|
+
|
|
145
151
|
if self.client_id and self.client_secret and self.tenant_id:
|
|
146
152
|
# Service Principal authentication
|
|
147
153
|
# Use pyodbc driver for Azure AD support
|
|
154
|
+
query_params = {
|
|
155
|
+
"driver": "ODBC Driver 18 for SQL Server",
|
|
156
|
+
"Authentication": "ActiveDirectoryServicePrincipal",
|
|
157
|
+
}
|
|
158
|
+
if trust_server_cert:
|
|
159
|
+
query_params["TrustServerCertificate"] = "yes"
|
|
148
160
|
return URL.create(
|
|
149
161
|
drivername="mssql+pyodbc",
|
|
150
162
|
username=self.client_id,
|
|
@@ -152,13 +164,13 @@ class MSSQLSourceImpl(BaseSQLSource, TableIngestMixIn, SQLSourceWithTableIngestP
|
|
|
152
164
|
host=self.host,
|
|
153
165
|
port=self.port,
|
|
154
166
|
database=self.db,
|
|
155
|
-
query=
|
|
156
|
-
"driver": "ODBC Driver 18 for SQL Server",
|
|
157
|
-
"Authentication": "ActiveDirectoryServicePrincipal",
|
|
158
|
-
},
|
|
167
|
+
query=query_params,
|
|
159
168
|
)
|
|
160
169
|
elif self.user and self.password:
|
|
161
170
|
# SQL authentication
|
|
171
|
+
query_params = {"driver": "ODBC Driver 18 for SQL Server"}
|
|
172
|
+
if trust_server_cert:
|
|
173
|
+
query_params["TrustServerCertificate"] = "yes"
|
|
162
174
|
return URL.create(
|
|
163
175
|
drivername="mssql+pyodbc",
|
|
164
176
|
username=self.user,
|
|
@@ -166,13 +178,15 @@ class MSSQLSourceImpl(BaseSQLSource, TableIngestMixIn, SQLSourceWithTableIngestP
|
|
|
166
178
|
host=self.host,
|
|
167
179
|
port=self.port,
|
|
168
180
|
database=self.db,
|
|
169
|
-
query=
|
|
181
|
+
query=query_params,
|
|
170
182
|
)
|
|
171
183
|
else:
|
|
172
184
|
# Managed Identity: token injected via event listener
|
|
173
185
|
connection_string = (
|
|
174
186
|
f"DRIVER={{ODBC Driver 18 for SQL Server}};SERVER={self.host},{self.port};DATABASE={self.db}"
|
|
175
187
|
)
|
|
188
|
+
if trust_server_cert:
|
|
189
|
+
connection_string += ";TrustServerCertificate=yes"
|
|
176
190
|
return URL.create(
|
|
177
191
|
drivername="mssql+pyodbc",
|
|
178
192
|
query={"odbc_connect": connection_string},
|
|
@@ -193,3 +207,75 @@ class MSSQLSourceImpl(BaseSQLSource, TableIngestMixIn, SQLSourceWithTableIngestP
|
|
|
193
207
|
]
|
|
194
208
|
if v is not None
|
|
195
209
|
}
|
|
210
|
+
|
|
211
|
+
def execute_query_efficient_raw(
|
|
212
|
+
self,
|
|
213
|
+
finalized_query: FinalizedChalkQuery,
|
|
214
|
+
expected_output_schema: "pa.Schema",
|
|
215
|
+
connection: Optional["Connection"],
|
|
216
|
+
query_execution_parameters: QueryExecutionParameters,
|
|
217
|
+
) -> Iterable["pa.RecordBatch"]:
|
|
218
|
+
"""Execute query efficiently for MSSQL and return raw PyArrow RecordBatches."""
|
|
219
|
+
import contextlib
|
|
220
|
+
|
|
221
|
+
import pyarrow as pa
|
|
222
|
+
import pyarrow.compute as pc
|
|
223
|
+
|
|
224
|
+
# Get the compiled query
|
|
225
|
+
_, _, _ = self.compile_query(finalized_query)
|
|
226
|
+
|
|
227
|
+
# Use existing connection or create new one
|
|
228
|
+
with (self.get_engine().connect() if connection is None else contextlib.nullcontext(connection)) as cnx:
|
|
229
|
+
with cnx.begin():
|
|
230
|
+
# Handle temp tables
|
|
231
|
+
with contextlib.ExitStack() as exit_stack:
|
|
232
|
+
for (
|
|
233
|
+
_,
|
|
234
|
+
temp_value,
|
|
235
|
+
create_temp_table,
|
|
236
|
+
temp_table,
|
|
237
|
+
drop_temp_table,
|
|
238
|
+
) in finalized_query.temp_tables.values():
|
|
239
|
+
exit_stack.enter_context(
|
|
240
|
+
self._create_temp_table(create_temp_table, temp_table, drop_temp_table, cnx, temp_value)
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Execute query
|
|
244
|
+
result = cnx.execute(finalized_query.query, finalized_query.params)
|
|
245
|
+
|
|
246
|
+
# Convert result to PyArrow
|
|
247
|
+
rows = result.fetchall()
|
|
248
|
+
column_names = result.keys()
|
|
249
|
+
|
|
250
|
+
if not rows:
|
|
251
|
+
# Return empty batch with expected schema
|
|
252
|
+
arrays = [pa.nulls(0, field.type) for field in expected_output_schema]
|
|
253
|
+
batch = pa.RecordBatch.from_arrays(arrays, schema=expected_output_schema)
|
|
254
|
+
if query_execution_parameters.yield_empty_batches:
|
|
255
|
+
yield batch
|
|
256
|
+
return
|
|
257
|
+
|
|
258
|
+
# Convert rows to column arrays
|
|
259
|
+
data: dict[str, list[Any]] = {}
|
|
260
|
+
for i, col_name in enumerate(column_names):
|
|
261
|
+
col_data = [row[i] for row in rows]
|
|
262
|
+
data[col_name] = col_data
|
|
263
|
+
|
|
264
|
+
# Create PyArrow table
|
|
265
|
+
table = pa.table(data)
|
|
266
|
+
|
|
267
|
+
# Map columns to expected schema
|
|
268
|
+
arrays: list[pa.Array] = []
|
|
269
|
+
for field in expected_output_schema:
|
|
270
|
+
if field.name in table.column_names:
|
|
271
|
+
col = table.column(field.name)
|
|
272
|
+
# Cast to expected type if needed
|
|
273
|
+
if col.type != field.type:
|
|
274
|
+
col = pc.cast(col, field.type)
|
|
275
|
+
arrays.append(col)
|
|
276
|
+
else:
|
|
277
|
+
# Column not found, create null array
|
|
278
|
+
arrays.append(pa.nulls(len(table), field.type))
|
|
279
|
+
|
|
280
|
+
batch = pa.RecordBatch.from_arrays(arrays, schema=expected_output_schema)
|
|
281
|
+
yield batch
|
|
@@ -5,7 +5,8 @@ class MissingDependencyException(ImportError):
|
|
|
5
5
|
...
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def missing_dependency_exception(name: str):
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
def missing_dependency_exception(name: str, original_error: Exception | None = None):
|
|
9
|
+
msg = f"Missing pip dependency '{name}' for chalkpy=={chalk.__version__}. Please add this to your requirements.txt file and pip install."
|
|
10
|
+
if original_error:
|
|
11
|
+
msg += f"\n\n{original_error}"
|
|
12
|
+
return MissingDependencyException(msg)
|
chalk/utils/tracing.py
CHANGED
|
@@ -5,7 +5,7 @@ import os
|
|
|
5
5
|
import threading
|
|
6
6
|
import time
|
|
7
7
|
import types
|
|
8
|
-
from typing import TYPE_CHECKING, Any, Mapping, Union, cast
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Callable, Mapping, Union, cast
|
|
9
9
|
|
|
10
10
|
from chalk.utils._ddtrace_version import can_use_datadog_statsd, can_use_ddtrace
|
|
11
11
|
from chalk.utils._otel_version import can_use_otel_trace
|
|
@@ -16,6 +16,41 @@ if TYPE_CHECKING:
|
|
|
16
16
|
import ddtrace.context
|
|
17
17
|
from opentelemetry import trace as otel_trace
|
|
18
18
|
|
|
19
|
+
|
|
20
|
+
class Once:
|
|
21
|
+
"""Execute a function exactly once and block all callers until the function returns
|
|
22
|
+
|
|
23
|
+
Same as golang's `sync.Once <https://pkg.go.dev/sync#Once>`_
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
self._lock = threading.Lock()
|
|
28
|
+
self._done = False
|
|
29
|
+
super().__init__()
|
|
30
|
+
|
|
31
|
+
def do_once(self, func: Callable[[], None]) -> bool:
|
|
32
|
+
"""Execute ``func`` if it hasn't been executed or return.
|
|
33
|
+
|
|
34
|
+
Will block until ``func`` has been called by one thread.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Whether or not ``func`` was executed in this call
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
# fast path, try to avoid locking
|
|
41
|
+
if self._done:
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
with self._lock:
|
|
45
|
+
if not self._done:
|
|
46
|
+
func()
|
|
47
|
+
self._done = True
|
|
48
|
+
return True
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
_TRACING_CONFIGURED = Once()
|
|
53
|
+
|
|
19
54
|
_logger = get_logger(__name__)
|
|
20
55
|
|
|
21
56
|
if can_use_otel_trace:
|
|
@@ -27,6 +62,7 @@ if can_use_otel_trace:
|
|
|
27
62
|
|
|
28
63
|
@contextlib.contextmanager
|
|
29
64
|
def safe_trace(span_id: str, attributes: Mapping[str, str] | None = None): # pyright: ignore[reportRedeclaration]
|
|
65
|
+
configure_tracing("chalkpy")
|
|
30
66
|
if attributes is None:
|
|
31
67
|
attributes = {}
|
|
32
68
|
attributes = dict(attributes)
|
|
@@ -36,14 +72,17 @@ if can_use_otel_trace:
|
|
|
36
72
|
yield span
|
|
37
73
|
|
|
38
74
|
def safe_add_metrics(metrics: Mapping[str, Union[int, float]]): # pyright: ignore[reportRedeclaration]
|
|
75
|
+
configure_tracing("chalkpy")
|
|
39
76
|
current_span = otel_trace.get_current_span()
|
|
40
77
|
current_span.set_attributes(dict(metrics))
|
|
41
78
|
|
|
42
79
|
def safe_add_tags(tags: Mapping[str, str]):
|
|
80
|
+
configure_tracing("chalkpy")
|
|
43
81
|
current_span = otel_trace.get_current_span()
|
|
44
82
|
current_span.set_attributes(dict(tags))
|
|
45
83
|
|
|
46
84
|
def safe_current_trace_context() -> ddtrace.context.Context | otel_trace.SpanContext | None: # pyright: ignore[reportRedeclaration]
|
|
85
|
+
configure_tracing("chalkpy")
|
|
47
86
|
return otel_trace.get_current_span().get_span_context()
|
|
48
87
|
|
|
49
88
|
@contextlib.contextmanager
|
|
@@ -53,6 +92,7 @@ if can_use_otel_trace:
|
|
|
53
92
|
| otel_trace.SpanContext
|
|
54
93
|
| None, # pyright: ignore[reportPrivateImportUsage]
|
|
55
94
|
):
|
|
95
|
+
configure_tracing("chalkpy")
|
|
56
96
|
if isinstance(ctx, otel_trace.SpanContext):
|
|
57
97
|
new_span = otel_trace.NonRecordingSpan(ctx)
|
|
58
98
|
new_context = otel_trace.set_span_in_context(new_span)
|
|
@@ -65,6 +105,7 @@ if can_use_otel_trace:
|
|
|
65
105
|
def add_trace_headers( # pyright: ignore[reportRedeclaration]
|
|
66
106
|
input_headers: None | dict[str, str]
|
|
67
107
|
) -> dict[str, str]:
|
|
108
|
+
configure_tracing("chalkpy")
|
|
68
109
|
current_span_ctx = otel_trace.get_current_span().get_span_context()
|
|
69
110
|
new_span_ctx = otel_trace.SpanContext(
|
|
70
111
|
trace_id=current_span_ctx.trace_id,
|
|
@@ -86,6 +127,7 @@ elif can_use_ddtrace:
|
|
|
86
127
|
|
|
87
128
|
@contextlib.contextmanager
|
|
88
129
|
def safe_trace(span_id: str, attributes: Mapping[str, str] | None = None): # pyright: ignore[reportRedeclaration]
|
|
130
|
+
configure_tracing("chalkpy")
|
|
89
131
|
if not ddtrace.tracer.enabled:
|
|
90
132
|
yield
|
|
91
133
|
return
|
|
@@ -106,16 +148,19 @@ elif can_use_ddtrace:
|
|
|
106
148
|
yield
|
|
107
149
|
|
|
108
150
|
def safe_add_metrics(metrics: Mapping[str, Union[int, float]]): # pyright: ignore[reportRedeclaration]
|
|
151
|
+
configure_tracing("chalkpy")
|
|
109
152
|
span = ddtrace.tracer.current_span()
|
|
110
153
|
if span:
|
|
111
154
|
span.set_metrics(cast(Any, metrics))
|
|
112
155
|
|
|
113
156
|
def safe_add_tags(tags: Mapping[str, str]): # pyright: ignore[reportRedeclaration]
|
|
157
|
+
configure_tracing("chalkpy")
|
|
114
158
|
span = ddtrace.tracer.current_span()
|
|
115
159
|
if span:
|
|
116
160
|
span.set_tags(cast(Any, tags))
|
|
117
161
|
|
|
118
162
|
def safe_current_trace_context() -> ddtrace.context.Context | otel_trace.SpanContext | None: # pyright: ignore[reportRedeclaration]
|
|
163
|
+
configure_tracing("chalkpy")
|
|
119
164
|
return ddtrace.tracer.current_trace_context()
|
|
120
165
|
|
|
121
166
|
@contextlib.contextmanager
|
|
@@ -125,6 +170,7 @@ elif can_use_ddtrace:
|
|
|
125
170
|
| otel_trace.SpanContext
|
|
126
171
|
| None, # pyright: ignore[reportPrivateImportUsage]
|
|
127
172
|
):
|
|
173
|
+
configure_tracing("chalkpy")
|
|
128
174
|
if isinstance(ctx, ddtrace.context.Context) or isinstance(ctx, ddtrace.Span):
|
|
129
175
|
ddtrace.tracer.context_provider.activate(ctx)
|
|
130
176
|
yield
|
|
@@ -132,6 +178,7 @@ elif can_use_ddtrace:
|
|
|
132
178
|
def add_trace_headers( # pyright: ignore[reportRedeclaration]
|
|
133
179
|
input_headers: None | dict[str, str]
|
|
134
180
|
) -> dict[str, str]:
|
|
181
|
+
configure_tracing("chalkpy")
|
|
135
182
|
headers: dict[str, str] = dict(input_headers if input_headers is not None else {})
|
|
136
183
|
span = ddtrace.tracer.current_span()
|
|
137
184
|
if span:
|
|
@@ -223,74 +270,74 @@ class PerfTimer:
|
|
|
223
270
|
|
|
224
271
|
|
|
225
272
|
def configure_tracing(default_service_name: str):
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
otel_trace.set_tracer_provider(provider)
|
|
243
|
-
|
|
244
|
-
elif can_use_ddtrace:
|
|
245
|
-
import ddtrace
|
|
246
|
-
from ddtrace.filters import FilterRequestsOnUrl
|
|
247
|
-
|
|
248
|
-
if ddtrace.config.service is None:
|
|
249
|
-
ddtrace.config.service = default_service_name
|
|
250
|
-
# Re-configuring the global tracer to capture any setting changes from environs from a .dotenv file
|
|
251
|
-
# which might be loaded after the first ddtrace import
|
|
252
|
-
|
|
253
|
-
ddtrace.tracer.configure(
|
|
254
|
-
enabled=None if "DD_TRACE_ENABLED" not in os.environ else env_var_bool("DD_TRACE_ENABLED"),
|
|
255
|
-
hostname=os.getenv("DD_AGENT_HOST") or os.getenv("DD_TRACE_AGENT_URL"),
|
|
256
|
-
uds_path=os.getenv("DD_TRACE_AGENT_URL"),
|
|
257
|
-
dogstatsd_url=os.getenv("DD_DOGSTATSD_URL"),
|
|
258
|
-
api_version=os.getenv("DD_TRACE_API_VERSION"),
|
|
259
|
-
compute_stats_enabled=env_var_bool("DD_TRACE_COMPUTE_STATS"),
|
|
260
|
-
iast_enabled=None if "DD_IAST_ENABLED" not in os.environ else env_var_bool("DD_IAST_ENABLED"),
|
|
261
|
-
# exclude healthcheck url from apm trace collection
|
|
262
|
-
settings={
|
|
263
|
-
"FILTERS": [
|
|
264
|
-
FilterRequestsOnUrl(
|
|
265
|
-
[
|
|
266
|
-
r"^http://.*/healthcheck$",
|
|
267
|
-
r"^http://.*/ready$",
|
|
268
|
-
r"^http://[^/]*/$", # exclude "/"
|
|
269
|
-
]
|
|
270
|
-
)
|
|
271
|
-
]
|
|
272
|
-
},
|
|
273
|
-
)
|
|
274
|
-
if ddtrace.tracer.enabled:
|
|
275
|
-
ddtrace.patch(
|
|
276
|
-
asyncio=True,
|
|
277
|
-
databricks=False,
|
|
278
|
-
fastapi=True,
|
|
279
|
-
futures=True,
|
|
280
|
-
httplib=True,
|
|
281
|
-
httpx=True,
|
|
282
|
-
psycopg=True,
|
|
283
|
-
redis=True,
|
|
284
|
-
requests=True,
|
|
285
|
-
sqlalchemy=False,
|
|
286
|
-
urllib3=True,
|
|
273
|
+
def do_configure_tracing():
|
|
274
|
+
from chalk.utils.log_with_context import get_logger
|
|
275
|
+
|
|
276
|
+
_logger = get_logger(__name__)
|
|
277
|
+
|
|
278
|
+
if can_use_otel_trace:
|
|
279
|
+
from opentelemetry import trace as otel_trace
|
|
280
|
+
from opentelemetry.sdk.resources import Resource
|
|
281
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
282
|
+
|
|
283
|
+
provider = TracerProvider(
|
|
284
|
+
resource=Resource.create(
|
|
285
|
+
{
|
|
286
|
+
"service.name": default_service_name,
|
|
287
|
+
}
|
|
288
|
+
),
|
|
287
289
|
)
|
|
290
|
+
otel_trace.set_tracer_provider(provider)
|
|
291
|
+
|
|
292
|
+
elif can_use_ddtrace:
|
|
293
|
+
import ddtrace
|
|
294
|
+
from ddtrace.filters import FilterRequestsOnUrl
|
|
295
|
+
|
|
296
|
+
if ddtrace.config.service is None:
|
|
297
|
+
ddtrace.config.service = default_service_name
|
|
298
|
+
# Re-configuring the global tracer to capture any setting changes from environs from a .dotenv file
|
|
299
|
+
# which might be loaded after the first ddtrace import
|
|
300
|
+
|
|
301
|
+
ddtrace.tracer.configure(
|
|
302
|
+
enabled=None if "DD_TRACE_ENABLED" not in os.environ else env_var_bool("DD_TRACE_ENABLED"),
|
|
303
|
+
hostname=os.getenv("DD_AGENT_HOST") or os.getenv("DD_TRACE_AGENT_URL"),
|
|
304
|
+
uds_path=os.getenv("DD_TRACE_AGENT_URL"),
|
|
305
|
+
dogstatsd_url=os.getenv("DD_DOGSTATSD_URL"),
|
|
306
|
+
api_version=os.getenv("DD_TRACE_API_VERSION"),
|
|
307
|
+
compute_stats_enabled=env_var_bool("DD_TRACE_COMPUTE_STATS"),
|
|
308
|
+
iast_enabled=None if "DD_IAST_ENABLED" not in os.environ else env_var_bool("DD_IAST_ENABLED"),
|
|
309
|
+
# exclude healthcheck url from apm trace collection
|
|
310
|
+
settings={
|
|
311
|
+
"FILTERS": [
|
|
312
|
+
FilterRequestsOnUrl(
|
|
313
|
+
[
|
|
314
|
+
r"^http://.*/healthcheck$",
|
|
315
|
+
r"^http://.*/ready$",
|
|
316
|
+
r"^http://[^/]*/$", # exclude "/"
|
|
317
|
+
]
|
|
318
|
+
)
|
|
319
|
+
]
|
|
320
|
+
},
|
|
321
|
+
)
|
|
322
|
+
if ddtrace.tracer.enabled:
|
|
323
|
+
ddtrace.patch(
|
|
324
|
+
asyncio=True,
|
|
325
|
+
databricks=False,
|
|
326
|
+
fastapi=True,
|
|
327
|
+
futures=True,
|
|
328
|
+
httplib=True,
|
|
329
|
+
httpx=True,
|
|
330
|
+
psycopg=True,
|
|
331
|
+
redis=True,
|
|
332
|
+
requests=True,
|
|
333
|
+
sqlalchemy=False,
|
|
334
|
+
urllib3=True,
|
|
335
|
+
)
|
|
288
336
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
337
|
+
_logger.info(
|
|
338
|
+
f"Configuring DDtrace tracing: enabled={ddtrace.tracer.enabled}, service={ddtrace.config.service}, env={ddtrace.config.env}, trace_agent_url: {ddtrace.config._trace_agent_url}, effective trace agent: {ddtrace.tracer._agent_url}" # pyright: ignore [reportAttributeAccessIssue, reportPrivateUsage]
|
|
339
|
+
)
|
|
340
|
+
else:
|
|
341
|
+
_logger.warning("neither opentelemetry nor ddtrace are installed")
|
|
295
342
|
|
|
296
|
-
|
|
343
|
+
_TRACING_CONFIGURED.do_once(do_configure_tracing)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
chalk/__init__.py,sha256=vKsx9-cl5kImlVWGHVRYO6bweBm79NAzGs3l36u71wM,2657
|
|
2
|
-
chalk/_version.py,sha256=
|
|
2
|
+
chalk/_version.py,sha256=806ZJ4Nmzvk8iZwepGS8Gxx4y0klotQk8lkbn8S8CIo,23
|
|
3
3
|
chalk/cli.py,sha256=ckqqfOI-A2mT23-rnZzDMmblYj-2x1VBX8ebHlIEn9A,5873
|
|
4
4
|
chalk/importer.py,sha256=m4lMn1lSYj_euDq8CS7LYTBnek9JOcjGJf9-82dJHbA,64441
|
|
5
5
|
chalk/prompts.py,sha256=2H9UomLAamdfRTNUdKs9i3VTpiossuyRhntqsAXUhhg,16117
|
|
@@ -641,7 +641,7 @@ chalk/features/_vector.py,sha256=jtJmUTtCaUFru4Fw17PYWozl3pPEdIOCYAuZOqIaN3Y,720
|
|
|
641
641
|
chalk/features/feature_cache_strategy.py,sha256=bXV-tjHfPzUotMpZ3h_D9Xxq-V1CLj_UcVtGIGMpMkI,4942
|
|
642
642
|
chalk/features/feature_field.py,sha256=x-B8CIt086xMOjtfpRMGcmfysS6G2vA_whsLZgGQeqI,93759
|
|
643
643
|
chalk/features/feature_set.py,sha256=yNi0_J4CylAVkVp1Y67qV6i8vHMdE0p99DnyLPABPHI,12406
|
|
644
|
-
chalk/features/feature_set_decorator.py,sha256=
|
|
644
|
+
chalk/features/feature_set_decorator.py,sha256=u92jAk0iVqdy3u-h_t6ieMDYpF-AWZRVpHaNrC33iqQ,65594
|
|
645
645
|
chalk/features/feature_time.py,sha256=iUk8NDelig81jP7QT3tguyzx5eOZ-YC84OVgJRRKVwo,1639
|
|
646
646
|
chalk/features/feature_wrapper.py,sha256=OolNWGGX67IAEMHCObFvOCpH5EmwjbMvMygRSBJJtu0,19259
|
|
647
647
|
chalk/features/filter.py,sha256=2ldMbqvXC-nJ0jc-OZ36qHtrej-Jkx4TNQ1W_NZodAs,11177
|
|
@@ -756,7 +756,7 @@ chalk/sql/_internal/integrations/cloudsql.py,sha256=bkYELyBwgWzd5Fw9gDZ6L7FR2KR1
|
|
|
756
756
|
chalk/sql/_internal/integrations/databricks.py,sha256=Nz2tOGzxkrJIXkCGWz631T7XRn2wKTj8zRXpCyHq9DI,18045
|
|
757
757
|
chalk/sql/_internal/integrations/duckdb.py,sha256=PYAdEQgLGsV-ugRkNOK_61S0H1mGev7g5s6Y4OemrGM,5658
|
|
758
758
|
chalk/sql/_internal/integrations/dynamodb.py,sha256=MHJryj6xJ9B72spofeTpCE86pC7ZduRux14jzkKsBc0,8747
|
|
759
|
-
chalk/sql/_internal/integrations/mssql.py,sha256=
|
|
759
|
+
chalk/sql/_internal/integrations/mssql.py,sha256=gZfAb_b6eVpTUkcFMeORF9edbpsvpvvi-VW_kJXwH6I,11938
|
|
760
760
|
chalk/sql/_internal/integrations/mysql.py,sha256=RjIc0TaQceZrZ-q5AIGExbH5VHirbscZqXII1Ht7M0I,8696
|
|
761
761
|
chalk/sql/_internal/integrations/postgres.py,sha256=bwxwEeJYH5-A7S22YumukwX6aN6c_B_MOOnrmJuTZyI,29169
|
|
762
762
|
chalk/sql/_internal/integrations/redshift.py,sha256=0f_h5Lnigth3O5BG16a967JokHCZfl4i2kWbb134-6Q,22872
|
|
@@ -804,7 +804,7 @@ chalk/utils/job_log_display.py,sha256=wIw3CA2FRHpaEDFMBsk24dUeiSp9NmCFWWL1fXilHp
|
|
|
804
804
|
chalk/utils/json.py,sha256=tqYK1l5Bk6GXK-i0PIuyNHYtq9HyaMry7TqHWw62pjY,1522
|
|
805
805
|
chalk/utils/log_with_context.py,sha256=HYB0mv8CL-dclCyneOAL-FkVSgJjq_PGGWwRTEdr6u8,10880
|
|
806
806
|
chalk/utils/metaprogramming.py,sha256=NVlgUt27prSiVjAypPzdxP--ZyWiVLZXQ8gr_BBzoys,622
|
|
807
|
-
chalk/utils/missing_dependency.py,sha256=
|
|
807
|
+
chalk/utils/missing_dependency.py,sha256=lBu7qyMZwVOC2BplyhKMiw2tTgXAqsfNyvQYNTHkzm8,405
|
|
808
808
|
chalk/utils/notebook.py,sha256=4H3QiSuxM8rbwmWJVMdIcAsZpHxZKLHDylalPqmlLbY,13631
|
|
809
809
|
chalk/utils/object_inspect.py,sha256=0jJCjvw6I7didagguXarjLjxXAmoBC5XjoLisdpGsTs,467
|
|
810
810
|
chalk/utils/paths.py,sha256=iozeVah79pbNjjvy59IA2JByB1V8Plg7B68Fj4qlZzM,1258
|
|
@@ -814,12 +814,12 @@ chalk/utils/storage_client.py,sha256=cK5KH8DVAt4Okk3X4jNMCkMiZgfUJE9Sq3zn4HkaBQo
|
|
|
814
814
|
chalk/utils/string.py,sha256=mHciu1FR1NdXiE0GjiCOOs_Q3JBVpaNnjUQPorE5cJg,4268
|
|
815
815
|
chalk/utils/stubgen.py,sha256=-mKIWFeiZojtfPwaTd9o3h4m4RvTmMTk6i-bI9JpU6c,21580
|
|
816
816
|
chalk/utils/threading.py,sha256=dacvfFCpDs9GDWdRrE2mmM3Ex5DKOIaj5rCYDTqGshk,5305
|
|
817
|
-
chalk/utils/tracing.py,sha256=
|
|
817
|
+
chalk/utils/tracing.py,sha256=qAyMRdFBkL4Q2_Bn-C31atDfJirUtBvcSjkYC2R51sM,13005
|
|
818
818
|
chalk/utils/weak_set_by_identity.py,sha256=VmikA_laYwFeOphCwXJIuyOIkrdlQe0bSzaXq7onoQw,953
|
|
819
819
|
chalk/utils/pydanticutil/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
820
820
|
chalk/utils/pydanticutil/pydantic_compat.py,sha256=O575lLYJ5GvZC4HMzR9yATxf9XwjC6NrDUXbNwZidlE,3031
|
|
821
|
-
chalkpy-2.95.
|
|
822
|
-
chalkpy-2.95.
|
|
823
|
-
chalkpy-2.95.
|
|
824
|
-
chalkpy-2.95.
|
|
825
|
-
chalkpy-2.95.
|
|
821
|
+
chalkpy-2.95.4.dist-info/METADATA,sha256=KWZ99My6RPafBho_fntwsoMUHCFT5oaLH2qaD6zDVm0,27494
|
|
822
|
+
chalkpy-2.95.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
823
|
+
chalkpy-2.95.4.dist-info/entry_points.txt,sha256=Vg23sd8icwq-morJrljVFr-kQnMbm95rZfZj5wsZGis,42
|
|
824
|
+
chalkpy-2.95.4.dist-info/top_level.txt,sha256=1Q6_19IGYfNxSw50W8tYKEJ2t5HKQ3W9Wiw4ia5yg2c,6
|
|
825
|
+
chalkpy-2.95.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|