chalkpy 2.95.3__py3-none-any.whl → 2.95.5__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/utils/tracing.py +116 -69
- {chalkpy-2.95.3.dist-info → chalkpy-2.95.5.dist-info}/METADATA +1 -1
- {chalkpy-2.95.3.dist-info → chalkpy-2.95.5.dist-info}/RECORD +8 -8
- {chalkpy-2.95.3.dist-info → chalkpy-2.95.5.dist-info}/WHEEL +0 -0
- {chalkpy-2.95.3.dist-info → chalkpy-2.95.5.dist-info}/entry_points.txt +0 -0
- {chalkpy-2.95.3.dist-info → chalkpy-2.95.5.dist-info}/top_level.txt +0 -0
chalk/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.95.
|
|
1
|
+
__version__ = "2.95.5"
|
|
@@ -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):
|
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=X0JYW1UywEt-kT_7bf_FTkwKKO4BoePYAdFMs1Rc3Bk,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
|
|
@@ -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.5.dist-info/METADATA,sha256=HHEOdnjv-mDKwViOnW6xWCO9vvOEvUY_m0_vP_Ub5xI,27494
|
|
822
|
+
chalkpy-2.95.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
823
|
+
chalkpy-2.95.5.dist-info/entry_points.txt,sha256=Vg23sd8icwq-morJrljVFr-kQnMbm95rZfZj5wsZGis,42
|
|
824
|
+
chalkpy-2.95.5.dist-info/top_level.txt,sha256=1Q6_19IGYfNxSw50W8tYKEJ2t5HKQ3W9Wiw4ia5yg2c,6
|
|
825
|
+
chalkpy-2.95.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|