scale-gp-beta 0.1.0a16__tar.gz → 0.1.0a18__tar.gz
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.
- scale_gp_beta-0.1.0a18/.release-please-manifest.json +3 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/CHANGELOG.md +21 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/PKG-INFO +1 -1
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/api.md +3 -1
- scale_gp_beta-0.1.0a18/examples/tracing/0_primitives_fibonacci.py +44 -0
- scale_gp_beta-0.1.0a18/examples/tracing/1_explicit_use_case.py +49 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/pyproject.toml +1 -1
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_version.py +1 -1
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/__init__.py +4 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/exceptions.py +5 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/scope.py +104 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/span.py +217 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/trace.py +118 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/trace_exporter.py +88 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/trace_queue_manager.py +181 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/tracing.py +180 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/types.py +40 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/lib/tracing/util.py +68 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/spans.py +331 -1
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/__init__.py +4 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/types/span_search_params.py +77 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/types/span_search_response.py +27 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/types/span_upsert_batch_params.py +78 -0
- scale_gp_beta-0.1.0a18/src/scale_gp_beta/types/span_upsert_batch_response.py +15 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_spans.py +194 -1
- scale_gp_beta-0.1.0a18/tests/lib/test_span.py +330 -0
- scale_gp_beta-0.1.0a18/tests/lib/test_trace.py +257 -0
- scale_gp_beta-0.1.0a18/tests/lib/test_trace_exporter.py +259 -0
- scale_gp_beta-0.1.0a18/tests/lib/test_tracing.py +325 -0
- scale_gp_beta-0.1.0a16/.release-please-manifest.json +0 -3
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/.gitignore +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/CONTRIBUTING.md +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/LICENSE +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/README.md +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/SECURITY.md +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/bin/check-release-environment +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/bin/publish-pypi +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/examples/.keep +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/mypy.ini +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/noxfile.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/release-please-config.json +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/requirements-dev.lock +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/requirements.lock +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp/lib/.keep +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_base_client.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_client.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_compat.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_constants.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_exceptions.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_files.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_models.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_qs.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_resource.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_streaming.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_types.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_logs.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_proxy.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_reflection.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_resources_proxy.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_streams.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_sync.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_transform.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_typing.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/_utils/_utils.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/lib/.keep +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/pagination.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/py.typed +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/chat/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/chat/chat.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/chat/completions.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/completions.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/dataset_items.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/datasets.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/evaluation_items.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/evaluations.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/files/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/files/content.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/files/files.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/inference.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/resources/models.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/chat_completion.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/chat_completion_chunk.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/completion_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/completion_create_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/completion_models_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/completion_models_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/chat/model_definition.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/completion.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/completion_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/component.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/component_param.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/container.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/container_param.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_delete_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item_batch_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item_batch_create_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item_delete_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item_list_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item_retrieve_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_item_update_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_list_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_retrieve_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/dataset_update_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_delete_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_item.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_item_list_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_item_retrieve_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_list_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_retrieve_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_task.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_task_param.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/evaluation_update_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/file.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/file_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/file_delete_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/file_list.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/file_list_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/file_update_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/files/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/inference_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/inference_create_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/inference_model.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/inference_model_list.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/inference_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/inference_response_chunk.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/item_locator.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/item_locator_template.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/model_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/model_delete_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/model_list_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/model_update_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/span.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/span_batch_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/span_batch_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/span_create_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/scale_gp_beta/types/span_update_params.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/src/sgp_dev/lib/.keep +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/chat/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/chat/test_completions.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/files/__init__.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/files/test_content.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_completions.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_dataset_items.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_datasets.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_evaluation_items.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_evaluations.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_files.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_inference.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/api_resources/test_models.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/conftest.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/sample_file.txt +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_client.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_deepcopy.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_extract_files.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_files.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_models.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_qs.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_required_args.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_response.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_streaming.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_transform.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_utils/test_proxy.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/test_utils/test_typing.py +0 -0
- {scale_gp_beta-0.1.0a16 → scale_gp_beta-0.1.0a18}/tests/utils.py +0 -0
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.18 (2025-06-11)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v0.1.0-alpha.17...v0.1.0-alpha.18](https://github.com/scaleapi/sgp-python-beta/compare/v0.1.0-alpha.17...v0.1.0-alpha.18)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* use upsert endpoint and report span start as well as end. ([3f8c073](https://github.com/scaleapi/sgp-python-beta/commit/3f8c073e8c1d97b2d7f2aced5558918bfd526de6))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* new endpoints change ([8ccdf28](https://github.com/scaleapi/sgp-python-beta/commit/8ccdf28885781f1a1689c62616220a07aaea4a6c))
|
|
15
|
+
|
|
16
|
+
## 0.1.0-alpha.17 (2025-06-11)
|
|
17
|
+
|
|
18
|
+
Full Changelog: [v0.1.0-alpha.16...v0.1.0-alpha.17](https://github.com/scaleapi/sgp-python-beta/compare/v0.1.0-alpha.16...v0.1.0-alpha.17)
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **api:** Added Span upsert batch and search endpoints ([f109f69](https://github.com/scaleapi/sgp-python-beta/commit/f109f6919886874122f541bf3bc8bb7d690648f1))
|
|
23
|
+
|
|
3
24
|
## 0.1.0-alpha.16 (2025-06-10)
|
|
4
25
|
|
|
5
26
|
Full Changelog: [v0.1.0-alpha.15...v0.1.0-alpha.16](https://github.com/scaleapi/sgp-python-beta/compare/v0.1.0-alpha.15...v0.1.0-alpha.16)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: scale-gp-beta
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a18
|
|
4
4
|
Summary: The official Python library for the Scale GP API
|
|
5
5
|
Project-URL: Homepage, https://github.com/scaleapi/sgp-python-beta
|
|
6
6
|
Project-URL: Repository, https://github.com/scaleapi/sgp-python-beta
|
|
@@ -157,7 +157,7 @@ Methods:
|
|
|
157
157
|
Types:
|
|
158
158
|
|
|
159
159
|
```python
|
|
160
|
-
from scale_gp_beta.types import Span, SpanBatchResponse
|
|
160
|
+
from scale_gp_beta.types import Span, SpanBatchResponse, SpanSearchResponse, SpanUpsertBatchResponse
|
|
161
161
|
```
|
|
162
162
|
|
|
163
163
|
Methods:
|
|
@@ -166,3 +166,5 @@ Methods:
|
|
|
166
166
|
- <code title="get /v5/spans/{span_id}">client.spans.<a href="./src/scale_gp_beta/resources/spans.py">retrieve</a>(span_id) -> <a href="./src/scale_gp_beta/types/span.py">Span</a></code>
|
|
167
167
|
- <code title="patch /v5/spans/{span_id}">client.spans.<a href="./src/scale_gp_beta/resources/spans.py">update</a>(span_id, \*\*<a href="src/scale_gp_beta/types/span_update_params.py">params</a>) -> <a href="./src/scale_gp_beta/types/span.py">Span</a></code>
|
|
168
168
|
- <code title="post /v5/spans/batch">client.spans.<a href="./src/scale_gp_beta/resources/spans.py">batch</a>(\*\*<a href="src/scale_gp_beta/types/span_batch_params.py">params</a>) -> <a href="./src/scale_gp_beta/types/span_batch_response.py">SpanBatchResponse</a></code>
|
|
169
|
+
- <code title="post /v5/spans/search">client.spans.<a href="./src/scale_gp_beta/resources/spans.py">search</a>(\*\*<a href="src/scale_gp_beta/types/span_search_params.py">params</a>) -> <a href="./src/scale_gp_beta/types/span_search_response.py">SpanSearchResponse</a></code>
|
|
170
|
+
- <code title="put /v5/spans/batch">client.spans.<a href="./src/scale_gp_beta/resources/spans.py">upsert_batch</a>(\*\*<a href="src/scale_gp_beta/types/span_upsert_batch_params.py">params</a>) -> <a href="./src/scale_gp_beta/types/span_upsert_batch_response.py">SpanUpsertBatchResponse</a></code>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple fibonacci tracing example. To run, first fill-in account_id and api key.
|
|
3
|
+
|
|
4
|
+
Using low-level Trace and Span objects.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
import scale_gp_beta.lib.tracing as tracing
|
|
10
|
+
from scale_gp_beta import SGPClient
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fibonacci(curr: int) -> int:
|
|
14
|
+
with tracing.create_span("fibonacci", input={"curr": curr}) as span:
|
|
15
|
+
time.sleep(0.1)
|
|
16
|
+
if curr < 2:
|
|
17
|
+
span.output = {"res": curr}
|
|
18
|
+
return curr
|
|
19
|
+
|
|
20
|
+
res = fibonacci(curr - 1) + fibonacci(curr - 2)
|
|
21
|
+
span.output = {"res": res}
|
|
22
|
+
return res
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main() -> None:
|
|
26
|
+
# create traces and spans with create_trace and create_span
|
|
27
|
+
# can act directly or use context managers
|
|
28
|
+
with tracing.create_trace("my_trace"):
|
|
29
|
+
span = tracing.create_span("main", input={}, metadata={"env": "local"})
|
|
30
|
+
span.start()
|
|
31
|
+
|
|
32
|
+
fib = fibonacci(5)
|
|
33
|
+
|
|
34
|
+
span.output = {"result": fib}
|
|
35
|
+
span.end()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if __name__ == "__main__":
|
|
39
|
+
api_key = "XXX"
|
|
40
|
+
account_id = "XXX"
|
|
41
|
+
|
|
42
|
+
# Initialise with a working client, can omit if two appropriate ENV VARs are set
|
|
43
|
+
tracing.init(SGPClient(api_key=api_key, account_id=account_id), disabled=False)
|
|
44
|
+
main()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple mock database query.
|
|
3
|
+
|
|
4
|
+
Explicit control example - no explicit traces just manually passing a trace_id.
|
|
5
|
+
"""
|
|
6
|
+
import time
|
|
7
|
+
import uuid
|
|
8
|
+
import random
|
|
9
|
+
from typing import Any, Dict
|
|
10
|
+
|
|
11
|
+
import scale_gp_beta.lib.tracing as tracing
|
|
12
|
+
from scale_gp_beta import SGPClient
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MockDatabase:
|
|
16
|
+
"""A mock database class to simulate queries."""
|
|
17
|
+
def __init__(self) -> None:
|
|
18
|
+
self._data = {
|
|
19
|
+
"SELECT * FROM users WHERE id = 1;": {"id": 1, "name": "Alice"},
|
|
20
|
+
"SELECT * FROM users WHERE id = 2;": {"id": 2, "name": "Bob"},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def execute_query(self, query: str, trace_id: str) -> Dict[str, Any]:
|
|
24
|
+
with tracing.create_span("db_query", input={"query": query}, trace=trace_id) as span:
|
|
25
|
+
# simulate delay
|
|
26
|
+
time.sleep(random.uniform(0.1, 0.3))
|
|
27
|
+
|
|
28
|
+
result = self._data.get(query, {})
|
|
29
|
+
span.output = {"result": result}
|
|
30
|
+
return result
|
|
31
|
+
|
|
32
|
+
def get_user_from_db(db: MockDatabase, user_id: int, trace_id: str) -> Dict[str, Any]:
|
|
33
|
+
with tracing.create_span("get_user_from_db", input={"user_id": user_id}, trace=trace_id):
|
|
34
|
+
query = f"SELECT * FROM users WHERE id = {user_id};"
|
|
35
|
+
|
|
36
|
+
return db.execute_query(query, trace_id)
|
|
37
|
+
|
|
38
|
+
def main() -> None:
|
|
39
|
+
db = MockDatabase()
|
|
40
|
+
trace_id = str(uuid.uuid4())
|
|
41
|
+
with tracing.create_span("main", metadata={"env": "local"}, trace=trace_id):
|
|
42
|
+
user = get_user_from_db(db, 1, trace_id)
|
|
43
|
+
print(f"Retrieved user: {user.get('name')}")
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
api_key = "xxx"
|
|
47
|
+
account_id = "xxx"
|
|
48
|
+
tracing.init(SGPClient(api_key=api_key, account_id=account_id), disabled=False)
|
|
49
|
+
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import contextvars
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from .span import BaseSpan
|
|
6
|
+
from .trace import BaseTrace
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
_current_span: contextvars.ContextVar["BaseSpan | None"] = contextvars.ContextVar("current_span", default=None)
|
|
10
|
+
|
|
11
|
+
_current_trace: contextvars.ContextVar["BaseTrace | None"] = contextvars.ContextVar("current_trace", default=None)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Scope:
|
|
15
|
+
"""
|
|
16
|
+
Manages the currently active span and trace within a context.
|
|
17
|
+
|
|
18
|
+
This class provides methods to get, set, and reset the current `BaseSpan`
|
|
19
|
+
and `BaseTrace` using `contextvars`. This allows for context-local
|
|
20
|
+
storage of the active span and trace.
|
|
21
|
+
|
|
22
|
+
Both traces and spans are managed in a way that allows for nesting.
|
|
23
|
+
While traces are not typically expected to be nested, this class handles
|
|
24
|
+
such scenarios gracefully by managing them with context variables, similar
|
|
25
|
+
to how spans are managed.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def get_current_span(cls) -> Optional["BaseSpan"]:
|
|
30
|
+
"""
|
|
31
|
+
Retrieves the currently active span from the context.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Optional["BaseSpan"]: The currently active span, or None if no
|
|
35
|
+
span is active in the current context.
|
|
36
|
+
"""
|
|
37
|
+
return _current_span.get()
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def set_current_span(cls, span: Optional["BaseSpan"]) -> contextvars.Token[Optional["BaseSpan"]]:
|
|
41
|
+
"""
|
|
42
|
+
Sets the currently active span in the context.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
span: The span to set as the current active span. Can be None
|
|
46
|
+
to indicate no active span.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
contextvars.Token[Optional["BaseSpan"]]: A token that can be used
|
|
50
|
+
to reset the context variable
|
|
51
|
+
to its previous state.
|
|
52
|
+
"""
|
|
53
|
+
return _current_span.set(span)
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def reset_current_span(cls, token: contextvars.Token[Optional["BaseSpan"]]) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Resets the current span in the context to its previous state.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
token: The token returned by a previous call to `set_current_span`.
|
|
62
|
+
This token is used to restore the context variable to the
|
|
63
|
+
value it had before the `set` call that D_GENERATED the token.
|
|
64
|
+
"""
|
|
65
|
+
_current_span.reset(token)
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def get_current_trace(cls) -> Optional["BaseTrace"]:
|
|
69
|
+
"""
|
|
70
|
+
Retrieves the currently active trace from the context.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Optional["BaseTrace"]: The currently active trace, or None if no
|
|
74
|
+
trace is active in the current context.
|
|
75
|
+
"""
|
|
76
|
+
return _current_trace.get()
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def set_current_trace(cls, trace: Optional["BaseTrace"]) -> contextvars.Token[Optional["BaseTrace"]]:
|
|
80
|
+
"""
|
|
81
|
+
Sets the currently active trace in the context.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
trace: The trace to set as the current active trace. Can be None
|
|
85
|
+
to indicate no active trace.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
contextvars.Token[Optional["BaseTrace"]]: A token that can be used
|
|
89
|
+
to reset the context variable
|
|
90
|
+
to its previous state.
|
|
91
|
+
"""
|
|
92
|
+
return _current_trace.set(trace)
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def reset_current_trace(cls, token: contextvars.Token[Optional["BaseTrace"]]) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Resets the current trace in the context to its previous state.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
token: The token returned by a previous call to `set_current_trace`.
|
|
101
|
+
This token is used to restore the context variable to the
|
|
102
|
+
value it had before the `set` call that D_GENERATED the token.
|
|
103
|
+
"""
|
|
104
|
+
_current_trace.reset(token)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Type, Optional
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
from scale_gp_beta.types.span_upsert_batch_params import Item as SpanCreateRequest
|
|
8
|
+
|
|
9
|
+
from .util import iso_timestamp, generate_span_id
|
|
10
|
+
from .scope import Scope
|
|
11
|
+
from .types import SpanTypeLiterals, SpanStatusLiterals
|
|
12
|
+
from .exceptions import ParamsCreationError
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
import contextvars
|
|
16
|
+
from types import TracebackType
|
|
17
|
+
|
|
18
|
+
from .trace_queue_manager import TraceQueueManager
|
|
19
|
+
|
|
20
|
+
log: logging.Logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BaseSpan:
|
|
24
|
+
"""Base class for all span types, providing common attributes and context management.
|
|
25
|
+
|
|
26
|
+
A span represents a single unit of work or operation within a trace. This base
|
|
27
|
+
class defines the core interface and properties for spans, such as name, IDs,
|
|
28
|
+
timestamps, and methods for starting and ending the span's lifecycle.
|
|
29
|
+
|
|
30
|
+
It is intended to be subclassed by concrete span implementations like `Span`
|
|
31
|
+
(for active tracing) and `NoOpSpan` (for when tracing is disabled).
|
|
32
|
+
|
|
33
|
+
Attributes:
|
|
34
|
+
name (str): The human-readable name of the span.
|
|
35
|
+
trace_id (str): The ID of the trace this span belongs to.
|
|
36
|
+
span_id (str): The unique ID of this span.
|
|
37
|
+
parent_span_id (Optional[str]): The ID of the parent span, if this is a child span.
|
|
38
|
+
start_time (Optional[str]): ISO 8601 timestamp of when the span started.
|
|
39
|
+
Set by the `start()` method.
|
|
40
|
+
end_time (Optional[str]): ISO 8601 timestamp of when the span ended.
|
|
41
|
+
Set by the `end()` method.
|
|
42
|
+
input (Optional[dict[str, Any]]): Input data or parameters for the span's operation.
|
|
43
|
+
output (Optional[dict[str, Any]]): Output data or results from the span's operation.
|
|
44
|
+
metadata (Optional[dict[str, Any]]): Additional arbitrary key-value metadata for the span.
|
|
45
|
+
_contextvar_token (Optional[contextvars.Token]): Token for managing the span's presence
|
|
46
|
+
in the current execution context.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
name: str,
|
|
52
|
+
trace_id: Optional[str] = None,
|
|
53
|
+
queue_manager: Optional[TraceQueueManager] = None,
|
|
54
|
+
span_id: Optional[str] = None,
|
|
55
|
+
parent_span_id: Optional[str] = None,
|
|
56
|
+
input: Optional[dict[str, Any]] = None,
|
|
57
|
+
output: Optional[dict[str, Any]] = None,
|
|
58
|
+
metadata: Optional[dict[str, Any]] = None,
|
|
59
|
+
span_type: SpanTypeLiterals = "STANDALONE"
|
|
60
|
+
):
|
|
61
|
+
self.name = name
|
|
62
|
+
self.trace_id = trace_id or "no_trace_id"
|
|
63
|
+
self.span_id: str = span_id or generate_span_id()
|
|
64
|
+
self.parent_span_id = parent_span_id
|
|
65
|
+
self.start_time: Optional[str] = None
|
|
66
|
+
self.end_time: Optional[str] = None
|
|
67
|
+
self.input = input
|
|
68
|
+
self.output = output
|
|
69
|
+
self.metadata = metadata
|
|
70
|
+
self.span_type: SpanTypeLiterals = span_type
|
|
71
|
+
self.status: SpanStatusLiterals = "SUCCESS"
|
|
72
|
+
self._queue_manager = queue_manager
|
|
73
|
+
|
|
74
|
+
self._contextvar_token: Optional[contextvars.Token[Optional[BaseSpan]]] = None
|
|
75
|
+
|
|
76
|
+
def start(self) -> None:
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def end(self) -> None:
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
def __enter__(self) -> BaseSpan:
|
|
83
|
+
self.start()
|
|
84
|
+
return self
|
|
85
|
+
|
|
86
|
+
def __exit__(
|
|
87
|
+
self,
|
|
88
|
+
exc_type: Optional[Type[BaseException]],
|
|
89
|
+
exc_val: Optional[BaseException],
|
|
90
|
+
exc_tb: Optional[TracebackType]
|
|
91
|
+
) -> None:
|
|
92
|
+
# Naively record details in metadata for now, note that error capture only supported in context manager
|
|
93
|
+
# TODO: support error observations when using direct span.start() and span.end()
|
|
94
|
+
if exc_type is not None:
|
|
95
|
+
if self.metadata is None:
|
|
96
|
+
self.metadata = {}
|
|
97
|
+
self.metadata["error"] = True
|
|
98
|
+
self.metadata["error.type"] = exc_type.__name__
|
|
99
|
+
self.metadata["error.message"] = str(exc_val)
|
|
100
|
+
self.status = "ERROR"
|
|
101
|
+
self.end()
|
|
102
|
+
|
|
103
|
+
def to_request_params(self) -> SpanCreateRequest:
|
|
104
|
+
if self.start_time is None:
|
|
105
|
+
raise ParamsCreationError("No start time specified")
|
|
106
|
+
if self.end_time is None:
|
|
107
|
+
# Can relax this check if we decide to allow span POSTs on creation.
|
|
108
|
+
raise ParamsCreationError("No end time specified")
|
|
109
|
+
|
|
110
|
+
request_data = SpanCreateRequest(
|
|
111
|
+
name=self.name,
|
|
112
|
+
id=self.span_id,
|
|
113
|
+
trace_id=self.trace_id,
|
|
114
|
+
start_timestamp=self.start_time,
|
|
115
|
+
end_timestamp=self.end_time,
|
|
116
|
+
input=self.input or {},
|
|
117
|
+
output=self.output or {},
|
|
118
|
+
metadata=self.metadata or {},
|
|
119
|
+
status=self.status,
|
|
120
|
+
type=self.span_type
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# parent_span_id is optional (root spans)
|
|
124
|
+
if self.parent_span_id is not None:
|
|
125
|
+
request_data["parent_id"] = self.parent_span_id
|
|
126
|
+
|
|
127
|
+
return request_data
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class NoOpSpan(BaseSpan):
|
|
131
|
+
@override
|
|
132
|
+
def start(self) -> None:
|
|
133
|
+
if self.start_time is not None:
|
|
134
|
+
log.warning(f"Span {self.name}: {self.span_id} has already started at {self.start_time}")
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
self.start_time = iso_timestamp()
|
|
138
|
+
self._contextvar_token = Scope.set_current_span(self)
|
|
139
|
+
|
|
140
|
+
@override
|
|
141
|
+
def end(self) -> None:
|
|
142
|
+
if self.end_time is not None:
|
|
143
|
+
log.warning(f"Span {self.name}: {self.span_id} has already ended at {self.end_time}")
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
if self._contextvar_token is None:
|
|
147
|
+
log.warning(f"Span {self.name}: {self.span_id} has not started yet.")
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
self.end_time = iso_timestamp()
|
|
151
|
+
Scope.reset_current_span(self._contextvar_token)
|
|
152
|
+
self._contextvar_token = None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class Span(BaseSpan):
|
|
156
|
+
"""An operational span implementation that records and reports tracing data.
|
|
157
|
+
|
|
158
|
+
`Span` instances represent actual units of work that are part of an active trace.
|
|
159
|
+
They record timestamps, manage their context in `Scope`, and interact with the
|
|
160
|
+
`TraceQueueManager` to report their start and end events for later export.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
def __init__(
|
|
164
|
+
self,
|
|
165
|
+
name: str,
|
|
166
|
+
trace_id: str,
|
|
167
|
+
queue_manager: TraceQueueManager,
|
|
168
|
+
span_id: Optional[str] = None,
|
|
169
|
+
parent_span_id: Optional[str] = None,
|
|
170
|
+
input: Optional[dict[str, Any]] = None,
|
|
171
|
+
output: Optional[dict[str, Any]] = None,
|
|
172
|
+
metadata: Optional[dict[str, Any]] = None,
|
|
173
|
+
span_type: SpanTypeLiterals = "STANDALONE",
|
|
174
|
+
):
|
|
175
|
+
super().__init__(name, trace_id, queue_manager, span_id, parent_span_id, input, output, metadata, span_type)
|
|
176
|
+
self._queue_manager: TraceQueueManager = queue_manager
|
|
177
|
+
self.trace_id: str = trace_id
|
|
178
|
+
|
|
179
|
+
@override
|
|
180
|
+
def start(self) -> None:
|
|
181
|
+
"""Starts the operational Span.
|
|
182
|
+
|
|
183
|
+
Sets the `start_time`, reports the span start to the `TraceQueueManager`
|
|
184
|
+
, and registers this span as the current span.
|
|
185
|
+
"""
|
|
186
|
+
if self.start_time is not None:
|
|
187
|
+
log.warning(f"Span {self.name}: {self.span_id} has already started at {self.start_time}")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
self.start_time = iso_timestamp()
|
|
191
|
+
self._queue_manager.report_span_start(self)
|
|
192
|
+
self._contextvar_token = Scope.set_current_span(self)
|
|
193
|
+
|
|
194
|
+
@override
|
|
195
|
+
def end(self) -> None:
|
|
196
|
+
"""Ends the operational Span.
|
|
197
|
+
|
|
198
|
+
Sets the `end_time`, reports the span end (with its complete data) to the
|
|
199
|
+
`TraceQueueManager` for queuing and export, and resets this span from the
|
|
200
|
+
`Scope`.
|
|
201
|
+
"""
|
|
202
|
+
if self.end_time is not None:
|
|
203
|
+
log.warning(f"Span {self.name}: {self.span_id} has already ended at {self.end_time}")
|
|
204
|
+
return
|
|
205
|
+
if self._contextvar_token is None:
|
|
206
|
+
log.warning(
|
|
207
|
+
(
|
|
208
|
+
f"Span {self.name}: {self.span_id} attempting to end without a valid context token. "
|
|
209
|
+
"Was start() called and completed successfully?"
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
return
|
|
213
|
+
|
|
214
|
+
self.end_time = iso_timestamp()
|
|
215
|
+
self._queue_manager.report_span_end(self)
|
|
216
|
+
Scope.reset_current_span(self._contextvar_token)
|
|
217
|
+
self._contextvar_token = None
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import contextvars
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
from typing import Dict, Type, Optional
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
from .span import Span, NoOpSpan
|
|
8
|
+
from .util import generate_trace_id
|
|
9
|
+
from .scope import Scope
|
|
10
|
+
from .trace_queue_manager import TraceQueueManager
|
|
11
|
+
|
|
12
|
+
log: logging.Logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BaseTrace:
|
|
16
|
+
def __init__(self, queue_manager: Optional[TraceQueueManager], trace_id: Optional[str] = None):
|
|
17
|
+
self.trace_id = trace_id or generate_trace_id()
|
|
18
|
+
self.queue_manager = queue_manager
|
|
19
|
+
|
|
20
|
+
self._in_progress = False
|
|
21
|
+
self._contextvar_token: Optional[contextvars.Token[Optional[BaseTrace]]] = None
|
|
22
|
+
|
|
23
|
+
def start(self) -> None:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
def end(self) -> None:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def __enter__(self) -> "BaseTrace":
|
|
30
|
+
self.start()
|
|
31
|
+
return self
|
|
32
|
+
|
|
33
|
+
def __exit__(
|
|
34
|
+
self,
|
|
35
|
+
exc_type: Optional[Type[BaseException]] = None,
|
|
36
|
+
exc_value: Optional[BaseException] = None,
|
|
37
|
+
traceback: Optional[TracebackType] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
self.end()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class NoOpTrace(BaseTrace):
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
name: str,
|
|
46
|
+
queue_manager: Optional[TraceQueueManager] = None,
|
|
47
|
+
trace_id: Optional[str] = None,
|
|
48
|
+
root_span_id: Optional[str] = None,
|
|
49
|
+
metadata: Optional[Dict[str, Optional[str]]] = None,
|
|
50
|
+
):
|
|
51
|
+
super().__init__(queue_manager, trace_id)
|
|
52
|
+
|
|
53
|
+
self.root_span = NoOpSpan(
|
|
54
|
+
name=name,
|
|
55
|
+
span_id=root_span_id,
|
|
56
|
+
trace_id=self.trace_id,
|
|
57
|
+
queue_manager=queue_manager,
|
|
58
|
+
metadata=metadata,
|
|
59
|
+
span_type="TRACER"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@override
|
|
63
|
+
def start(self) -> None:
|
|
64
|
+
self.root_span.start()
|
|
65
|
+
|
|
66
|
+
@override
|
|
67
|
+
def end(self) -> None:
|
|
68
|
+
self.root_span.end()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Trace(BaseTrace):
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
name: str,
|
|
75
|
+
queue_manager: TraceQueueManager,
|
|
76
|
+
trace_id: Optional[str] = None,
|
|
77
|
+
root_span_id: Optional[str] = None,
|
|
78
|
+
metadata: Optional[Dict[str, Optional[str]]] = None,
|
|
79
|
+
):
|
|
80
|
+
super().__init__(queue_manager, trace_id)
|
|
81
|
+
self.queue_manager: TraceQueueManager = queue_manager
|
|
82
|
+
|
|
83
|
+
self.root_span = Span(
|
|
84
|
+
name=name,
|
|
85
|
+
span_id=root_span_id,
|
|
86
|
+
trace_id=self.trace_id,
|
|
87
|
+
queue_manager=queue_manager,
|
|
88
|
+
metadata=metadata,
|
|
89
|
+
span_type="TRACER"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
@override
|
|
93
|
+
def start(self) -> None:
|
|
94
|
+
if self._in_progress:
|
|
95
|
+
log.warning(f"Trace already started: {self.trace_id}")
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
self._in_progress = True
|
|
99
|
+
self.queue_manager.report_trace_start(self) # no-op
|
|
100
|
+
self._contextvar_token = Scope.set_current_trace(self)
|
|
101
|
+
|
|
102
|
+
self.root_span.start()
|
|
103
|
+
|
|
104
|
+
@override
|
|
105
|
+
def end(self) -> None:
|
|
106
|
+
if not self._in_progress:
|
|
107
|
+
log.warning(f"Ending trace which is not active: {self.trace_id}")
|
|
108
|
+
return
|
|
109
|
+
if self._contextvar_token is None:
|
|
110
|
+
log.warning(f"Ending trace which is not active: {self.trace_id}, contextvar_token not set")
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
self._in_progress = False
|
|
114
|
+
self.queue_manager.report_trace_end(self) # no-op
|
|
115
|
+
Scope.reset_current_trace(self._contextvar_token)
|
|
116
|
+
self._contextvar_token = None
|
|
117
|
+
|
|
118
|
+
self.root_span.end()
|