|
12 | 12 | from posthog.capture_compression import CaptureCompression as CaptureCompression |
13 | 13 | from posthog.capture_mode import CaptureMode as CaptureMode |
14 | 14 | from posthog.client import Client |
| 15 | +from posthog.tracing.span import Span |
15 | 16 | from posthog.async_client import AsyncClient as AsyncClient |
16 | 17 | from posthog.async_client import AsyncPosthog as AsyncPosthog |
17 | 18 | from posthog.exception_capture import ExceptionCapture |
@@ -340,6 +341,20 @@ def get_tags() -> Dict[str, Any]: |
340 | 341 | ``service_version``, ``environment``, ``flush_interval``, ...). Applied |
341 | 342 | when ``setup()`` builds the global client, or on a later ``setup()`` |
342 | 343 | call if the metrics API hasn't been used yet. |
| 344 | + traces: Config dict for distributed tracing: ``service_name``, |
| 345 | + ``service_version``, ``environment``, ``resource_attributes``, |
| 346 | + ``flush_interval`` (5 s), ``max_queue_size`` (2048), |
| 347 | + ``max_export_batch_size`` (512), ``max_live_spans`` (10000), |
| 348 | + ``max_span_age`` (3600 s), ``max_attributes_per_span`` (128), |
| 349 | + ``max_events_per_span`` (128), ``max_attribute_value_length`` (8192). |
| 350 | + ``before_span_send`` is a callable, or a list run in order, |
| 351 | + that receives each finished span as a dict (``trace_id``, ``span_id`` |
| 352 | + and ``parent_span_id`` are read-only) and returns it, edited, or |
| 353 | + ``None`` to drop it; a hook that raises drops the span. Tracing is off |
| 354 | + until set. Spans export on a background timer even with ``sync_mode``; |
| 355 | + serverless handlers should call ``flush()`` before returning. Applied |
| 356 | + when ``setup()`` builds the global client, or on a later ``setup()`` |
| 357 | + call if no span has been started yet. |
343 | 358 | enable_exception_autocapture: Automatically capture uncaught exceptions. |
344 | 359 | log_captured_exceptions: Also log exceptions captured by error tracking. |
345 | 360 | project_root: Root path used to determine in-app exception stack frames. |
@@ -396,6 +411,7 @@ def get_tags() -> Dict[str, Any]: |
396 | 411 | feature_flags_request_max_retries = 1 # type: int |
397 | 412 | super_properties = None # type: Optional[Dict] |
398 | 413 | metrics = None # type: Optional[Dict] |
| 414 | +traces = None # type: Optional[Dict] |
399 | 415 | enable_exception_autocapture = False # type: bool |
400 | 416 | log_captured_exceptions = False # type: bool |
401 | 417 | # Used to determine in app paths for exception autocapture. Defaults to the current working directory |
@@ -1197,6 +1213,83 @@ def join() -> None: |
1197 | 1213 | _proxy("join") |
1198 | 1214 |
|
1199 | 1215 |
|
| 1216 | +def start_span( |
| 1217 | + name: str, |
| 1218 | + *, |
| 1219 | + kind: Optional[str] = None, |
| 1220 | + attributes: Optional[Mapping[str, Any]] = None, |
| 1221 | + parent: Union[Span, str, None] = None, |
| 1222 | + tracestate: Optional[str] = None, |
| 1223 | + start_time: Union[datetime.datetime, float, None] = None, |
| 1224 | +) -> Span: |
| 1225 | + """ |
| 1226 | + Start a span for distributed tracing. Alpha. |
| 1227 | +
|
| 1228 | + Returns a span handle. Use it as a context manager to make it the active |
| 1229 | + span for the block and end it on exit (recording a raised exception on the |
| 1230 | + way out); or call ``end()`` yourself for a span that cannot wrap a block. |
| 1231 | + Spans started inside the block nest under it automatically. Always returns |
| 1232 | + a usable handle, even when tracing is off, so calling code never branches. |
| 1233 | +
|
| 1234 | + Args: |
| 1235 | + name: A low-cardinality operation name, e.g. ``GET /users/:id``. |
| 1236 | + Variable values belong in attributes, not the name. |
| 1237 | + kind: ``internal`` (default), ``server``, ``client``, ``producer`` or |
| 1238 | + ``consumer``. |
| 1239 | + attributes: Initial attributes. |
| 1240 | + parent: A span handle, or an inbound W3C ``traceparent`` header value |
| 1241 | + to continue a remote trace. Defaults to the active span. |
| 1242 | + tracestate: The inbound ``tracestate`` header accompanying a |
| 1243 | + ``traceparent`` string ``parent``; preserved and propagated. |
| 1244 | + start_time: A ``datetime`` or epoch seconds, to backdate the span. |
| 1245 | +
|
| 1246 | + Examples: |
| 1247 | + ```python |
| 1248 | + import posthog |
| 1249 | + posthog.traces = {"service_name": "checkout-api"} |
| 1250 | +
|
| 1251 | + with posthog.start_span("POST /checkout", parent=request.headers.get("traceparent")) as span: |
| 1252 | + span.set_attribute("plan", user.plan) |
| 1253 | + with posthog.start_span("db.query", kind="client"): |
| 1254 | + ... |
| 1255 | + outgoing_headers = {"traceparent": span.traceparent()} |
| 1256 | + ``` |
| 1257 | +
|
| 1258 | + Category: |
| 1259 | + Tracing |
| 1260 | + """ |
| 1261 | + return _proxy( |
| 1262 | + "start_span", |
| 1263 | + name, |
| 1264 | + kind=kind, |
| 1265 | + attributes=attributes, |
| 1266 | + parent=parent, |
| 1267 | + tracestate=tracestate, |
| 1268 | + start_time=start_time, |
| 1269 | + ) |
| 1270 | + |
| 1271 | + |
| 1272 | +def get_active_span() -> Optional[Span]: |
| 1273 | + """ |
| 1274 | + The span that is active in the current context, or ``None``. Alpha. |
| 1275 | +
|
| 1276 | + Only entering a span (``with posthog.start_span(...) as span:``) makes it |
| 1277 | + active; a span started manually is not. Use it to propagate the trace to |
| 1278 | + the next service: ``span.traceparent()`` is the header value. |
| 1279 | +
|
| 1280 | + Examples: |
| 1281 | + ```python |
| 1282 | + span = posthog.get_active_span() |
| 1283 | + if span is not None: |
| 1284 | + headers["traceparent"] = span.traceparent() |
| 1285 | + ``` |
| 1286 | +
|
| 1287 | + Category: |
| 1288 | + Tracing |
| 1289 | + """ |
| 1290 | + return _proxy("get_active_span") |
| 1291 | + |
| 1292 | + |
1200 | 1293 | def shutdown() -> None: |
1201 | 1294 | """ |
1202 | 1295 | Flush all messages and cleanly shutdown the client. |
@@ -1259,6 +1352,7 @@ def setup() -> Client: |
1259 | 1352 | feature_flags_request_max_retries=feature_flags_request_max_retries, |
1260 | 1353 | super_properties=super_properties, |
1261 | 1354 | metrics=metrics, |
| 1355 | + traces=traces, |
1262 | 1356 | # TODO: Currently this monitoring begins only when the Client is initialised (which happens when you do something with the SDK) |
1263 | 1357 | # This kind of initialisation is very annoying for exception capture. We need to figure out a way around this, |
1264 | 1358 | # or deprecate this proxy option fully (it's already in the process of deprecation, no new clients should be using this method since like 5-6 months) |
@@ -1299,6 +1393,8 @@ def setup() -> Client: |
1299 | 1393 | # already forced setup()) still applies until the metrics API is first used. |
1300 | 1394 | if default_client._metrics is None: |
1301 | 1395 | default_client._metrics_config = metrics |
| 1396 | + if default_client._traces is None: |
| 1397 | + default_client._traces_config = traces |
1302 | 1398 |
|
1303 | 1399 | return default_client |
1304 | 1400 |
|
|
0 commit comments