arize-phoenix 4.30.1__py3-none-any.whl → 4.31.0__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.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.31.0.dist-info}/METADATA +1 -1
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.31.0.dist-info}/RECORD +21 -20
- phoenix/otel/otel.py +115 -6
- phoenix/server/api/context.py +2 -0
- phoenix/server/api/dataloaders/__init__.py +2 -0
- phoenix/server/api/dataloaders/dataset_example_revisions.py +54 -17
- phoenix/server/api/dataloaders/experiment_run_annotations.py +40 -0
- phoenix/server/api/types/ExperimentRun.py +1 -9
- phoenix/server/app.py +36 -2
- phoenix/server/dml_event_handler.py +1 -0
- phoenix/server/main.py +21 -1
- phoenix/server/static/.vite/manifest.json +9 -9
- phoenix/server/static/assets/{components-CkSg5zK4.js → components-CEsu6itL.js} +1 -1
- phoenix/server/static/assets/{index-DTecsU5w.js → index-Cuxn1Qdi.js} +1 -1
- phoenix/server/static/assets/{pages-C6emDFIO.js → pages-eeRVG3GZ.js} +218 -180
- phoenix/trace/fixtures.py +46 -10
- phoenix/trace/utils.py +2 -8
- phoenix/version.py +1 -1
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.31.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.31.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.31.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
7
|
phoenix/services.py,sha256=OyML4t2XGnlqF0JXA9_uccL8HslTABxep9Ci7MViKEU,5216
|
|
8
8
|
phoenix/settings.py,sha256=cO-qgis_S27nHirTobYI9hHPfZH18R--WMmxNdsVUwc,273
|
|
9
|
-
phoenix/version.py,sha256=
|
|
9
|
+
phoenix/version.py,sha256=cwXnCkuybXvG8CJdFQgdInYSNEQ76nXEvTuAMbm7ENc,23
|
|
10
10
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
12
12
|
phoenix/core/model.py,sha256=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
|
|
@@ -64,7 +64,7 @@ phoenix/metrics/retrieval_metrics.py,sha256=XFQPo66h16w7-1AJ92M1VL_BUIXIWxXHGKF_
|
|
|
64
64
|
phoenix/metrics/timeseries.py,sha256=Cib3E0njJzi0vZpmyADvbakFQA98rIkfDaYAOmsmBz8,6277
|
|
65
65
|
phoenix/metrics/wrappers.py,sha256=umZqa_5lf1wZSFe3FgzxF-qp1xbPdKD54W628GlGCUI,8392
|
|
66
66
|
phoenix/otel/__init__.py,sha256=YvEiD-3aGZs9agwLNCXU34ofV3G-Q-dolfsiinOJuT0,407
|
|
67
|
-
phoenix/otel/otel.py,sha256=
|
|
67
|
+
phoenix/otel/otel.py,sha256=NMQ-5KtpfCVGVkRzcz7fBsjCFTTR7R7wHna-87gvxfQ,17065
|
|
68
68
|
phoenix/otel/settings.py,sha256=Qr2-RkgLQRfLhJqtLpEkSpqns7qLjPoOvpEOTqeSohM,3026
|
|
69
69
|
phoenix/pointcloud/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
70
70
|
phoenix/pointcloud/clustering.py,sha256=IzcG67kJ2hPP7pcqVmKPSL_6gKRonKdOT3bCtbTOqnk,820
|
|
@@ -72,32 +72,33 @@ phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYG
|
|
|
72
72
|
phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
|
|
73
73
|
phoenix/pointcloud/umap_parameters.py,sha256=3UQSjrysVOvq2V4KNpTMqNqNiK0BsTZnPBHWZ4fyJtQ,1708
|
|
74
74
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
phoenix/server/app.py,sha256=
|
|
75
|
+
phoenix/server/app.py,sha256=rnd4ps3JYRqD2DdE34TruMiismRTzFqgQrSupXLnVRU,28006
|
|
76
76
|
phoenix/server/dml_event.py,sha256=MpjCFqljxvgb9OB5Cez9vJesb3oHb3XxXictynBfcis,2851
|
|
77
|
-
phoenix/server/dml_event_handler.py,sha256=
|
|
77
|
+
phoenix/server/dml_event_handler.py,sha256=yU23-DDwXcL35p5EPwFW0oZh6mxQxJrJAQPKcYZYJz4,8310
|
|
78
78
|
phoenix/server/grpc_server.py,sha256=jllxDNkpLQxDkvej4RhTokobowbvydF-SU8gSw1MTCc,3378
|
|
79
|
-
phoenix/server/main.py,sha256=
|
|
79
|
+
phoenix/server/main.py,sha256=OXqRIppf_AiFWBMMLIozvqRAMrJqwK7t5uFL6yQC2j8,14485
|
|
80
80
|
phoenix/server/prometheus.py,sha256=j9DHB2fERuq_ZKmwVaqR-9wx5WcPPuU1Cm5Bhg5241Y,2996
|
|
81
81
|
phoenix/server/telemetry.py,sha256=T_2OKrxNViAeaANlNspEekg_Y5uZIFWvKAnpz8Aoqvk,2762
|
|
82
82
|
phoenix/server/thread_server.py,sha256=RwXQGP_QhGD7le6WB7xEygEEuwBl5Ck_Zo8xGIYGi9M,2135
|
|
83
83
|
phoenix/server/types.py,sha256=S2dReLNboR2nzjRK5j3MUyUDqu6AQFD7KRwJkeKj1q4,3609
|
|
84
84
|
phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
85
|
-
phoenix/server/api/context.py,sha256=
|
|
85
|
+
phoenix/server/api/context.py,sha256=XLlRtIhBl3iEq7exrN_DaO0n-XyvuvdO5bLB4uDrQhI,3724
|
|
86
86
|
phoenix/server/api/exceptions.py,sha256=KdAzgwNan-wQ7THDrSoeJU2k9zWQVcH6lRiB462VsRA,990
|
|
87
87
|
phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
|
|
88
88
|
phoenix/server/api/queries.py,sha256=hUzeHOUWuBQ-kjXh13-d5LgJfkbB8XSpFaHJX4YXpC8,23875
|
|
89
89
|
phoenix/server/api/schema.py,sha256=4L2m6QXhaV13YPTZCEZ3hqCPQFHZOy3QnJVLRYQFzpg,548
|
|
90
90
|
phoenix/server/api/utils.py,sha256=Kl47G-1A7QKTDrc75BU2QK6HupsG6MWuXxy351FOfKQ,858
|
|
91
|
-
phoenix/server/api/dataloaders/__init__.py,sha256=
|
|
91
|
+
phoenix/server/api/dataloaders/__init__.py,sha256=D1xEKunv8ZUBEPk2eStX-JhoPR3_NaQcNOp47H-oChM,3161
|
|
92
92
|
phoenix/server/api/dataloaders/annotation_summaries.py,sha256=Wv8AORZoGd5TJ4Y-em8iqJu87AMpZP7lWOTr-SML-x8,5560
|
|
93
93
|
phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=q091UmkXx37OBKh7L-GJ5LXHyRXfX2w4XTk1NMHtPpw,1827
|
|
94
|
-
phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=
|
|
94
|
+
phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=_X2CwCc6lAkD4VuwAiyo4DfSVS8uuzub05sKyKiEXm8,5149
|
|
95
95
|
phoenix/server/api/dataloaders/dataset_example_spans.py,sha256=-TjdyyJv2c2JiN1OXu6MMmQ-BEKlHXucEDcuObeRVsU,1416
|
|
96
96
|
phoenix/server/api/dataloaders/document_evaluation_summaries.py,sha256=5XOom2KRAmCwPmtlraiZOSl3vhfaW-eiiYkmetAEalw,5616
|
|
97
97
|
phoenix/server/api/dataloaders/document_evaluations.py,sha256=V6sE34jON_qFxt7eArJbktykAsty-gnBZHlEkORcj0E,1296
|
|
98
98
|
phoenix/server/api/dataloaders/document_retrieval_metrics.py,sha256=JqDqkUuoeG6WfcmWSrmQptfF6IPX8XgzYzyECXTAjgg,4202
|
|
99
99
|
phoenix/server/api/dataloaders/experiment_annotation_summaries.py,sha256=qDEBRo0XKJMYBYlXBgJ-69jwPK-0r4pi9ZhbjC_vx6M,2813
|
|
100
100
|
phoenix/server/api/dataloaders/experiment_error_rates.py,sha256=wWTFOO2UxGIYUu53nnzzLk04-mJxw-BQgJELA9gT5bY,1949
|
|
101
|
+
phoenix/server/api/dataloaders/experiment_run_annotations.py,sha256=Ey42FYy6WIASWlO-KKwHewfvH_RBL0Ci3W3xrv4oyaE,1361
|
|
101
102
|
phoenix/server/api/dataloaders/experiment_run_counts.py,sha256=8VlKRaXwD56-7q_uonRr7L6QlEkyEQubkFKmKx6vuz0,1661
|
|
102
103
|
phoenix/server/api/dataloaders/experiment_sequence_number.py,sha256=hSpKyOz3ES4UTfOzOfHeQ1ZXat-bzcdKybVSbYmhrBw,1563
|
|
103
104
|
phoenix/server/api/dataloaders/latency_ms_quantile.py,sha256=5Y2OQ_GeH1My2573eOm7zPbqpwDZ_WeMLoZMq3KDoNQ,7403
|
|
@@ -198,7 +199,7 @@ phoenix/server/api/types/ExampleRevisionInterface.py,sha256=gV3Gt9-3Oi5wjaVtepC6
|
|
|
198
199
|
phoenix/server/api/types/Experiment.py,sha256=YNs8SzOMSYUKiAMANuWSv8NxSNFzSIFOBOWb_yztE0s,5482
|
|
199
200
|
phoenix/server/api/types/ExperimentAnnotationSummary.py,sha256=Uk3JtxIrsMoZT5tqc4nJdUOM3XegVzjUyoV3pkjNotE,256
|
|
200
201
|
phoenix/server/api/types/ExperimentComparison.py,sha256=0sFz6MoBDw39dds0qVyaqhVs9qqO5rkG1FMSjmfBeCc,441
|
|
201
|
-
phoenix/server/api/types/ExperimentRun.py,sha256=
|
|
202
|
+
phoenix/server/api/types/ExperimentRun.py,sha256=LkR7fBRZ3nH57ZoHJwePTGtJYcTMM-EH5r1TVPiMyxg,2687
|
|
202
203
|
phoenix/server/api/types/ExperimentRunAnnotation.py,sha256=iBxDaD9DgiF-Qymp5QyxWfJRGYXM1_CeWA_qzsZBqkI,1812
|
|
203
204
|
phoenix/server/api/types/ExportedFile.py,sha256=e3GTn7B5LgsTbqiwjhMCQH7VsiqXitrBO4aCMS1lHsg,163
|
|
204
205
|
phoenix/server/api/types/Functionality.py,sha256=tzV9xdhB8zqfsjWxP66NDC7EZsplYkYO7jRbLWJIeeg,382
|
|
@@ -241,10 +242,10 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
241
242
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
242
243
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
243
244
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
244
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
245
|
-
phoenix/server/static/assets/components-
|
|
246
|
-
phoenix/server/static/assets/index-
|
|
247
|
-
phoenix/server/static/assets/pages-
|
|
245
|
+
phoenix/server/static/.vite/manifest.json,sha256=l5PYEBo0V10WvPZcDPW9uwNedEA5nmLoOrC_-ZMrU-k,1929
|
|
246
|
+
phoenix/server/static/assets/components-CEsu6itL.js,sha256=s16CoqiDIY0P1koerMJLXKRGckrry2j7TdFmT_tusLk,244317
|
|
247
|
+
phoenix/server/static/assets/index-Cuxn1Qdi.js,sha256=1j6OndkjUTZy8MlmlLOeOdoYadDgn60nBYhEN3lh-20,7515
|
|
248
|
+
phoenix/server/static/assets/pages-eeRVG3GZ.js,sha256=uyG6j1wduaoEtcO4HwdPrtQCQAoECeC0TiA6edyT6bk,504931
|
|
248
249
|
phoenix/server/static/assets/vendor-DsnEJuEV.js,sha256=YyePucCaVO5Wke5vLm6NF6V3_rAomN7TqcBzv8QY6q0,1435199
|
|
249
250
|
phoenix/server/static/assets/vendor-DxkFTwjz.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
|
|
250
251
|
phoenix/server/static/assets/vendor-arizeai-DtynTLNi.js,sha256=7D2zoxiUlFzqSpK-BDO4HlhbruUMmw3_CCDYQq6Mw-4,304008
|
|
@@ -263,7 +264,7 @@ phoenix/trace/attributes.py,sha256=B_OrzVaxZwFkrAFXZyicYoIti1UdUysURsvUS2GyW1U,1
|
|
|
263
264
|
phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
|
|
264
265
|
phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
|
|
265
266
|
phoenix/trace/exporter.py,sha256=eAYemdvDCHMugDJiaR29BFFMTQBdf3oerdkz34Cl3hE,4736
|
|
266
|
-
phoenix/trace/fixtures.py,sha256=
|
|
267
|
+
phoenix/trace/fixtures.py,sha256=YsKJJEnqo1f_yJzVrfQnnrmS0LlQl7k37lbLY2pZ7ds,17856
|
|
267
268
|
phoenix/trace/otel.py,sha256=WA720jvRadiZBAKjsYoPyXzypHwbyEK2OZRVUwtbjB8,9976
|
|
268
269
|
phoenix/trace/projects.py,sha256=2BwlNjFE-uwpqYtCu5YyBiYZk9wRPpM13vh3-Cv7GkA,2157
|
|
269
270
|
phoenix/trace/schemas.py,sha256=HpWSyzec0yDHEQXEDuwyLbhpvKrqkGps8BJqGiIFj8Y,5978
|
|
@@ -271,7 +272,7 @@ phoenix/trace/span_evaluations.py,sha256=GaADtJLi2njra4aYaie0BIwkSgdxPB_SNseglI4
|
|
|
271
272
|
phoenix/trace/span_json_decoder.py,sha256=jkpYSmOUsSptvahOvetrPjVkPIuI4h6b87eizL8wHp8,3230
|
|
272
273
|
phoenix/trace/span_json_encoder.py,sha256=tzSCIQJbeFBm33K68G8A5M12n_86tCDyuU0WAobxEz4,2010
|
|
273
274
|
phoenix/trace/trace_dataset.py,sha256=Wq89jJ4hYQ1Qt-Uj11ZNzKQYQeKmGY6NqWStQiiTlMw,14351
|
|
274
|
-
phoenix/trace/utils.py,sha256=
|
|
275
|
+
phoenix/trace/utils.py,sha256=lWinMM7Tsq_DCsBD5Ck97lxouBHrY4muGNsh8JD3qg4,1694
|
|
275
276
|
phoenix/trace/dsl/README.md,sha256=ihmP9zGUC5V-TDbzKla76LuyDqPDQIBUH2BORwxNI68,2902
|
|
276
277
|
phoenix/trace/dsl/__init__.py,sha256=WIQIjJg362XD3s50OsPJJ0xbDsGp41bSv7vDllLrPuA,144
|
|
277
278
|
phoenix/trace/dsl/filter.py,sha256=9NwATCUOgJ4Pms8XsEcinROUuxZ9UW-ISV09o65Ms70,32600
|
|
@@ -295,8 +296,8 @@ phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,
|
|
|
295
296
|
phoenix/utilities/project.py,sha256=8IJuMM4yUMoooPi37sictGj8Etu9rGmq6RFtc9848cQ,436
|
|
296
297
|
phoenix/utilities/re.py,sha256=PDve_OLjRTM8yQQJHC8-n3HdIONi7aNils3ZKRZ5uBM,2045
|
|
297
298
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
298
|
-
arize_phoenix-4.
|
|
299
|
-
arize_phoenix-4.
|
|
300
|
-
arize_phoenix-4.
|
|
301
|
-
arize_phoenix-4.
|
|
302
|
-
arize_phoenix-4.
|
|
299
|
+
arize_phoenix-4.31.0.dist-info/METADATA,sha256=yKHi2ksTlU_0xsldV4ozw7XATWGBRaS8w18wnaLElJE,11977
|
|
300
|
+
arize_phoenix-4.31.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
301
|
+
arize_phoenix-4.31.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
302
|
+
arize_phoenix-4.31.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
303
|
+
arize_phoenix-4.31.0.dist-info/RECORD,,
|
phoenix/otel/otel.py
CHANGED
|
@@ -51,9 +51,10 @@ def register(
|
|
|
51
51
|
not provided, the `PHOENIX_PROJECT_NAME` environment variable will be used.
|
|
52
52
|
batch (bool): If True, spans will be processed using a BatchSpanprocessor. If False, spans
|
|
53
53
|
will be processed one at a time using a SimpleSpanProcessor.
|
|
54
|
-
set_global_tracer_provider (bool): If False, the TracerProvider will not be set as the
|
|
55
|
-
tracer provider. Defaults to True.
|
|
56
|
-
headers (dict, optional): Optional headers to include in the
|
|
54
|
+
set_global_tracer_provider (bool): If False, the TracerProvider will not be set as the
|
|
55
|
+
global tracer provider. Defaults to True.
|
|
56
|
+
headers (dict, optional): Optional headers to include in the request to the collector.
|
|
57
|
+
If not provided, the `PHOENIX_CLIENT_HEADERS` environment variable will be used.
|
|
57
58
|
verbose (bool): If True, configuration details will be printed to stdout.
|
|
58
59
|
"""
|
|
59
60
|
|
|
@@ -73,7 +74,8 @@ def register(
|
|
|
73
74
|
global_provider_msg = (
|
|
74
75
|
"| \n"
|
|
75
76
|
"| `register` has set this TracerProvider as the global OpenTelemetry default.\n"
|
|
76
|
-
"| To disable this behavior, call `register` with
|
|
77
|
+
"| To disable this behavior, call `register` with "
|
|
78
|
+
"`set_global_tracer_provider=False`.\n"
|
|
77
79
|
)
|
|
78
80
|
else:
|
|
79
81
|
global_provider_msg = ""
|
|
@@ -85,6 +87,22 @@ def register(
|
|
|
85
87
|
|
|
86
88
|
|
|
87
89
|
class TracerProvider(_TracerProvider):
|
|
90
|
+
"""
|
|
91
|
+
An extension of `opentelemetry.sdk.trace.TracerProvider` with Phoenix-aware defaults.
|
|
92
|
+
|
|
93
|
+
Extended keyword arguments are documented in the `Args` section. For further documentation, see
|
|
94
|
+
the OpenTelemetry documentation at https://opentelemetry.io/docs/specs/otel/trace/sdk/.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
endpoint (str, optional): The collector endpoint to which spans will be exported. If
|
|
98
|
+
specified, a default SpanProcessor will be created and added to this TracerProvider.
|
|
99
|
+
If not provided, the `PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be
|
|
100
|
+
used to infer which collector endpoint to use, defaults to the gRPC endpoint. When
|
|
101
|
+
specifying the endpoint, the transport method (HTTP or gRPC) will be inferred from the
|
|
102
|
+
URL.
|
|
103
|
+
verbose (bool): If True, configuration details will be printed to stdout.
|
|
104
|
+
"""
|
|
105
|
+
|
|
88
106
|
def __init__(
|
|
89
107
|
self, *args: Any, endpoint: Optional[str] = None, verbose: bool = True, **kwargs: Any
|
|
90
108
|
):
|
|
@@ -112,6 +130,12 @@ class TracerProvider(_TracerProvider):
|
|
|
112
130
|
print(self._tracing_details())
|
|
113
131
|
|
|
114
132
|
def add_span_processor(self, *args: Any, **kwargs: Any) -> None:
|
|
133
|
+
"""
|
|
134
|
+
Registers a new `SpanProcessor` for this `TracerProvider`.
|
|
135
|
+
|
|
136
|
+
If this `TracerProvider` has a default processor, it will be removed.
|
|
137
|
+
"""
|
|
138
|
+
|
|
115
139
|
if self._default_processor:
|
|
116
140
|
self._active_span_processor.shutdown()
|
|
117
141
|
self._active_span_processor._span_processors = tuple() # remove default processors
|
|
@@ -163,6 +187,24 @@ class TracerProvider(_TracerProvider):
|
|
|
163
187
|
|
|
164
188
|
|
|
165
189
|
class SimpleSpanProcessor(_SimpleSpanProcessor):
|
|
190
|
+
"""
|
|
191
|
+
Simple SpanProcessor implementation.
|
|
192
|
+
|
|
193
|
+
SimpleSpanProcessor is an implementation of `SpanProcessor` that passes ended spans directly to
|
|
194
|
+
the configured `SpanExporter`.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
span_exporter (SpanExporter, optional): The `SpanExporter` to which ended spans will be
|
|
198
|
+
passed.
|
|
199
|
+
endpoint (str, optional): The collector endpoint to which spans will be exported. If not
|
|
200
|
+
provided, the `PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to
|
|
201
|
+
infer which collector endpoint to use, defaults to the gRPC endpoint. When specifying
|
|
202
|
+
the endpoint, the transport method (HTTP or gRPC) will be inferred from the URL.
|
|
203
|
+
headers (dict, optional): Optional headers to include in the request to the collector.
|
|
204
|
+
If not provided, the `PHOENIX_CLIENT_HEADERS` or `OTEL_EXPORTER_OTLP_HEADERS`
|
|
205
|
+
environment variable will be used.
|
|
206
|
+
"""
|
|
207
|
+
|
|
166
208
|
def __init__(
|
|
167
209
|
self,
|
|
168
210
|
span_exporter: Optional[SpanExporter] = None,
|
|
@@ -182,6 +224,37 @@ class SimpleSpanProcessor(_SimpleSpanProcessor):
|
|
|
182
224
|
|
|
183
225
|
|
|
184
226
|
class BatchSpanProcessor(_BatchSpanProcessor):
|
|
227
|
+
"""
|
|
228
|
+
Batch SpanProcessor implementation.
|
|
229
|
+
|
|
230
|
+
`BatchSpanProcessor` is an implementation of `SpanProcessor` that batches ended spans and
|
|
231
|
+
pushes them to the configured `SpanExporter`.
|
|
232
|
+
|
|
233
|
+
`BatchSpanProcessor` is configurable with the following environment variables which correspond
|
|
234
|
+
to constructor parameters:
|
|
235
|
+
|
|
236
|
+
- :envvar:`OTEL_BSP_SCHEDULE_DELAY`
|
|
237
|
+
- :envvar:`OTEL_BSP_MAX_QUEUE_SIZE`
|
|
238
|
+
- :envvar:`OTEL_BSP_MAX_EXPORT_BATCH_SIZE`
|
|
239
|
+
- :envvar:`OTEL_BSP_EXPORT_TIMEOUT`
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
span_exporter (SpanExporter, optional): The `SpanExporter` to which ended spans will be
|
|
243
|
+
passed.
|
|
244
|
+
endpoint (str, optional): The collector endpoint to which spans will be exported. If not
|
|
245
|
+
provided, the `PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to
|
|
246
|
+
infer which collector endpoint to use, defaults to the gRPC endpoint. When specifying
|
|
247
|
+
the endpoint, the transport method (HTTP or gRPC) will be inferred from the URL.
|
|
248
|
+
headers (dict, optional): Optional headers to include in the request to the collector.
|
|
249
|
+
If not provided, the `PHOENIX_CLIENT_HEADERS` or `OTEL_EXPORTER_OTLP_HEADERS`
|
|
250
|
+
environment variable will be used.
|
|
251
|
+
max_queue_size (int, optional): The maximum queue size.
|
|
252
|
+
schedule_delay_millis (float, optional): The delay between two consecutive exports in
|
|
253
|
+
milliseconds.
|
|
254
|
+
max_export_batch_size (int, optional): The maximum batch size.
|
|
255
|
+
export_timeout_millis (float, optional): The batch timeout in milliseconds.
|
|
256
|
+
"""
|
|
257
|
+
|
|
185
258
|
def __init__(
|
|
186
259
|
self,
|
|
187
260
|
span_exporter: Optional[SpanExporter] = None,
|
|
@@ -201,6 +274,20 @@ class BatchSpanProcessor(_BatchSpanProcessor):
|
|
|
201
274
|
|
|
202
275
|
|
|
203
276
|
class HTTPSpanExporter(_HTTPSpanExporter):
|
|
277
|
+
"""
|
|
278
|
+
OTLP span exporter using HTTP.
|
|
279
|
+
|
|
280
|
+
For more information, see:
|
|
281
|
+
- `opentelemetry.exporter.otlp.proto.http.trace_exporter.OTLPSpanExporter`
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
endpoint (str, optional): OpenTelemetry Collector receiver endpoint. If not provided, the
|
|
285
|
+
`PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to infer which
|
|
286
|
+
collector endpoint to use, defaults to the HTTP endpoint.
|
|
287
|
+
headers: Headers to send when exporting. If not provided, the `PHOENIX_CLIENT_HEADERS`
|
|
288
|
+
or `OTEL_EXPORTER_OTLP_HEADERS` environment variables will be used.
|
|
289
|
+
"""
|
|
290
|
+
|
|
204
291
|
def __init__(self, *args: Any, **kwargs: Any):
|
|
205
292
|
sig = inspect.signature(_HTTPSpanExporter)
|
|
206
293
|
bound_args = sig.bind_partial(*args, **kwargs)
|
|
@@ -210,12 +297,30 @@ class HTTPSpanExporter(_HTTPSpanExporter):
|
|
|
210
297
|
bound_args.arguments["headers"] = get_env_client_headers()
|
|
211
298
|
|
|
212
299
|
if bound_args.arguments.get("endpoint") is None:
|
|
213
|
-
_, endpoint = _normalized_endpoint(None)
|
|
300
|
+
_, endpoint = _normalized_endpoint(None, use_http=True)
|
|
214
301
|
bound_args.arguments["endpoint"] = endpoint
|
|
215
302
|
super().__init__(**bound_args.arguments)
|
|
216
303
|
|
|
217
304
|
|
|
218
305
|
class GRPCSpanExporter(_GRPCSpanExporter):
|
|
306
|
+
"""
|
|
307
|
+
OTLP span exporter using gRPC.
|
|
308
|
+
|
|
309
|
+
For more information, see:
|
|
310
|
+
- `opentelemetry.exporter.otlp.proto.grpc.trace_exporter.OTLPSpanExporter`
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
endpoint (str, optional): OpenTelemetry Collector receiver endpoint. If not provided, the
|
|
314
|
+
`PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to infer which
|
|
315
|
+
collector endpoint to use, defaults to the gRPC endpoint.
|
|
316
|
+
insecure: Connection type
|
|
317
|
+
credentials: Credentials object for server authentication
|
|
318
|
+
headers: Headers to send when exporting. If not provided, the `PHOENIX_CLIENT_HEADERS`
|
|
319
|
+
or `OTEL_EXPORTER_OTLP_HEADERS` environment variables will be used.
|
|
320
|
+
timeout: Backend request timeout in seconds
|
|
321
|
+
compression: gRPC compression method to use
|
|
322
|
+
"""
|
|
323
|
+
|
|
219
324
|
def __init__(self, *args: Any, **kwargs: Any):
|
|
220
325
|
sig = inspect.signature(_GRPCSpanExporter)
|
|
221
326
|
bound_args = sig.bind_partial(*args, **kwargs)
|
|
@@ -270,12 +375,16 @@ _KNOWN_PROVIDERS = {
|
|
|
270
375
|
}
|
|
271
376
|
|
|
272
377
|
|
|
273
|
-
def _normalized_endpoint(
|
|
378
|
+
def _normalized_endpoint(
|
|
379
|
+
endpoint: Optional[str], use_http: bool = False
|
|
380
|
+
) -> Tuple[ParseResult, str]:
|
|
274
381
|
if endpoint is None:
|
|
275
382
|
base_endpoint = get_env_collector_endpoint() or "http://localhost:6006"
|
|
276
383
|
parsed = urlparse(base_endpoint)
|
|
277
384
|
if parsed.hostname in _KNOWN_PROVIDERS:
|
|
278
385
|
parsed = _KNOWN_PROVIDERS[parsed.hostname](parsed)
|
|
386
|
+
elif use_http:
|
|
387
|
+
parsed = _construct_http_endpoint(parsed)
|
|
279
388
|
else:
|
|
280
389
|
parsed = _construct_grpc_endpoint(parsed)
|
|
281
390
|
else:
|
phoenix/server/api/context.py
CHANGED
|
@@ -17,6 +17,7 @@ from phoenix.server.api.dataloaders import (
|
|
|
17
17
|
DocumentRetrievalMetricsDataLoader,
|
|
18
18
|
ExperimentAnnotationSummaryDataLoader,
|
|
19
19
|
ExperimentErrorRatesDataLoader,
|
|
20
|
+
ExperimentRunAnnotations,
|
|
20
21
|
ExperimentRunCountsDataLoader,
|
|
21
22
|
ExperimentSequenceNumberDataLoader,
|
|
22
23
|
LatencyMsQuantileDataLoader,
|
|
@@ -45,6 +46,7 @@ class DataLoaders:
|
|
|
45
46
|
annotation_summaries: AnnotationSummaryDataLoader
|
|
46
47
|
experiment_annotation_summaries: ExperimentAnnotationSummaryDataLoader
|
|
47
48
|
experiment_error_rates: ExperimentErrorRatesDataLoader
|
|
49
|
+
experiment_run_annotations: ExperimentRunAnnotations
|
|
48
50
|
experiment_run_counts: ExperimentRunCountsDataLoader
|
|
49
51
|
experiment_sequence_number: ExperimentSequenceNumberDataLoader
|
|
50
52
|
latency_ms_quantile: LatencyMsQuantileDataLoader
|
|
@@ -12,6 +12,7 @@ from .document_evaluations import DocumentEvaluationsDataLoader
|
|
|
12
12
|
from .document_retrieval_metrics import DocumentRetrievalMetricsDataLoader
|
|
13
13
|
from .experiment_annotation_summaries import ExperimentAnnotationSummaryDataLoader
|
|
14
14
|
from .experiment_error_rates import ExperimentErrorRatesDataLoader
|
|
15
|
+
from .experiment_run_annotations import ExperimentRunAnnotations
|
|
15
16
|
from .experiment_run_counts import ExperimentRunCountsDataLoader
|
|
16
17
|
from .experiment_sequence_number import ExperimentSequenceNumberDataLoader
|
|
17
18
|
from .latency_ms_quantile import LatencyMsQuantileCache, LatencyMsQuantileDataLoader
|
|
@@ -36,6 +37,7 @@ __all__ = [
|
|
|
36
37
|
"AnnotationSummaryDataLoader",
|
|
37
38
|
"ExperimentAnnotationSummaryDataLoader",
|
|
38
39
|
"ExperimentErrorRatesDataLoader",
|
|
40
|
+
"ExperimentRunAnnotations",
|
|
39
41
|
"ExperimentRunCountsDataLoader",
|
|
40
42
|
"ExperimentSequenceNumberDataLoader",
|
|
41
43
|
"LatencyMsQuantileDataLoader",
|
|
@@ -5,7 +5,8 @@ from typing import (
|
|
|
5
5
|
Union,
|
|
6
6
|
)
|
|
7
7
|
|
|
8
|
-
from sqlalchemy import
|
|
8
|
+
from sqlalchemy import and_, case, func, null, or_, select
|
|
9
|
+
from sqlalchemy.sql.expression import literal
|
|
9
10
|
from strawberry.dataloader import DataLoader
|
|
10
11
|
from typing_extensions import TypeAlias
|
|
11
12
|
|
|
@@ -22,40 +23,76 @@ Result: TypeAlias = DatasetExampleRevision
|
|
|
22
23
|
|
|
23
24
|
class DatasetExampleRevisionsDataLoader(DataLoader[Key, Result]):
|
|
24
25
|
def __init__(self, db: DbSessionFactory) -> None:
|
|
25
|
-
super().__init__(
|
|
26
|
+
super().__init__(
|
|
27
|
+
load_fn=self._load_fn,
|
|
28
|
+
max_batch_size=200, # needed to prevent the size of the query from getting too large
|
|
29
|
+
)
|
|
26
30
|
self._db = db
|
|
27
31
|
|
|
28
32
|
async def _load_fn(self, keys: List[Key]) -> List[Union[Result, NotFound]]:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
example_and_version_ids = tuple(
|
|
34
|
+
set(
|
|
35
|
+
(example_id, version_id)
|
|
36
|
+
for example_id, version_id in keys
|
|
37
|
+
if version_id is not None
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
versionless_example_ids = tuple(
|
|
41
|
+
set(example_id for example_id, version_id in keys if version_id is None)
|
|
42
|
+
)
|
|
43
|
+
resolved_example_and_version_ids = (
|
|
44
|
+
(
|
|
33
45
|
select(
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
models.DatasetExample.id.label("example_id"),
|
|
47
|
+
models.DatasetVersion.id.label("version_id"),
|
|
48
|
+
)
|
|
49
|
+
.select_from(models.DatasetExample)
|
|
50
|
+
.join(
|
|
51
|
+
models.DatasetVersion,
|
|
52
|
+
onclause=literal(True), # cross join
|
|
53
|
+
)
|
|
54
|
+
.where(
|
|
55
|
+
or_(
|
|
56
|
+
*(
|
|
57
|
+
and_(
|
|
58
|
+
models.DatasetExample.id == example_id,
|
|
59
|
+
models.DatasetVersion.id == version_id,
|
|
60
|
+
)
|
|
61
|
+
for example_id, version_id in example_and_version_ids
|
|
62
|
+
)
|
|
63
|
+
)
|
|
36
64
|
)
|
|
37
|
-
for example_id, version_id in keys
|
|
38
65
|
)
|
|
39
|
-
|
|
66
|
+
.union(
|
|
67
|
+
select(
|
|
68
|
+
models.DatasetExample.id.label("example_id"), null().label("version_id")
|
|
69
|
+
).where(models.DatasetExample.id.in_(versionless_example_ids))
|
|
70
|
+
)
|
|
71
|
+
.subquery()
|
|
72
|
+
)
|
|
40
73
|
revision_ids = (
|
|
41
74
|
select(
|
|
42
|
-
|
|
43
|
-
|
|
75
|
+
resolved_example_and_version_ids.c.example_id,
|
|
76
|
+
resolved_example_and_version_ids.c.version_id,
|
|
44
77
|
func.max(models.DatasetExampleRevision.id).label("revision_id"),
|
|
45
78
|
)
|
|
46
|
-
.select_from(
|
|
79
|
+
.select_from(resolved_example_and_version_ids)
|
|
47
80
|
.join(
|
|
48
81
|
models.DatasetExampleRevision,
|
|
49
|
-
onclause=
|
|
82
|
+
onclause=resolved_example_and_version_ids.c.example_id
|
|
50
83
|
== models.DatasetExampleRevision.dataset_example_id,
|
|
51
84
|
)
|
|
52
85
|
.where(
|
|
53
86
|
or_(
|
|
54
|
-
|
|
55
|
-
models.DatasetExampleRevision.dataset_version_id
|
|
87
|
+
resolved_example_and_version_ids.c.version_id.is_(None),
|
|
88
|
+
models.DatasetExampleRevision.dataset_version_id
|
|
89
|
+
<= resolved_example_and_version_ids.c.version_id,
|
|
56
90
|
)
|
|
57
91
|
)
|
|
58
|
-
.group_by(
|
|
92
|
+
.group_by(
|
|
93
|
+
resolved_example_and_version_ids.c.example_id,
|
|
94
|
+
resolved_example_and_version_ids.c.version_id,
|
|
95
|
+
)
|
|
59
96
|
).subquery()
|
|
60
97
|
query = (
|
|
61
98
|
select(
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from typing import (
|
|
3
|
+
DefaultDict,
|
|
4
|
+
List,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from sqlalchemy import select
|
|
8
|
+
from strawberry.dataloader import DataLoader
|
|
9
|
+
from typing_extensions import TypeAlias
|
|
10
|
+
|
|
11
|
+
from phoenix.db.models import ExperimentRunAnnotation as OrmExperimentRunAnnotation
|
|
12
|
+
from phoenix.server.types import DbSessionFactory
|
|
13
|
+
|
|
14
|
+
ExperimentRunID: TypeAlias = int
|
|
15
|
+
Key: TypeAlias = ExperimentRunID
|
|
16
|
+
Result: TypeAlias = List[OrmExperimentRunAnnotation]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ExperimentRunAnnotations(DataLoader[Key, Result]):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
db: DbSessionFactory,
|
|
23
|
+
) -> None:
|
|
24
|
+
super().__init__(load_fn=self._load_fn)
|
|
25
|
+
self._db = db
|
|
26
|
+
|
|
27
|
+
async def _load_fn(self, keys: List[Key]) -> List[Result]:
|
|
28
|
+
run_ids = tuple(set(keys))
|
|
29
|
+
annotations: DefaultDict[Key, Result] = defaultdict(list)
|
|
30
|
+
async with self._db() as session:
|
|
31
|
+
async for run_id, annotation in await session.stream(
|
|
32
|
+
select(
|
|
33
|
+
OrmExperimentRunAnnotation.experiment_run_id, OrmExperimentRunAnnotation
|
|
34
|
+
).where(OrmExperimentRunAnnotation.experiment_run_id.in_(run_ids))
|
|
35
|
+
):
|
|
36
|
+
annotations[run_id].append(annotation)
|
|
37
|
+
return [
|
|
38
|
+
sorted(annotations[run_id], key=lambda annotation: annotation.name, reverse=True)
|
|
39
|
+
for run_id in run_ids
|
|
40
|
+
]
|
|
@@ -2,7 +2,6 @@ from datetime import datetime
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
import strawberry
|
|
5
|
-
from sqlalchemy import select
|
|
6
5
|
from strawberry import UNSET
|
|
7
6
|
from strawberry.relay import Connection, GlobalID, Node, NodeID
|
|
8
7
|
from strawberry.scalars import JSON
|
|
@@ -48,14 +47,7 @@ class ExperimentRun(Node):
|
|
|
48
47
|
before=before if isinstance(before, CursorString) else None,
|
|
49
48
|
)
|
|
50
49
|
run_id = self.id_attr
|
|
51
|
-
|
|
52
|
-
annotations = (
|
|
53
|
-
await session.scalars(
|
|
54
|
-
select(models.ExperimentRunAnnotation)
|
|
55
|
-
.where(models.ExperimentRunAnnotation.experiment_run_id == run_id)
|
|
56
|
-
.order_by(models.ExperimentRunAnnotation.name.desc())
|
|
57
|
-
)
|
|
58
|
-
).all()
|
|
50
|
+
annotations = await info.context.data_loaders.experiment_run_annotations.load(run_id)
|
|
59
51
|
return connection_from_list(
|
|
60
52
|
[to_gql_experiment_run_annotation(annotation) for annotation in annotations], args
|
|
61
53
|
)
|
phoenix/server/app.py
CHANGED
|
@@ -46,7 +46,13 @@ from typing_extensions import TypeAlias
|
|
|
46
46
|
|
|
47
47
|
import phoenix
|
|
48
48
|
import phoenix.trace.v1 as pb
|
|
49
|
-
from phoenix.config import
|
|
49
|
+
from phoenix.config import (
|
|
50
|
+
DEFAULT_PROJECT_NAME,
|
|
51
|
+
SERVER_DIR,
|
|
52
|
+
get_env_host,
|
|
53
|
+
get_env_port,
|
|
54
|
+
server_instrumentation_is_enabled,
|
|
55
|
+
)
|
|
50
56
|
from phoenix.core.model_schema import Model
|
|
51
57
|
from phoenix.db import models
|
|
52
58
|
from phoenix.db.bulk_inserter import BulkInserter
|
|
@@ -66,6 +72,7 @@ from phoenix.server.api.dataloaders import (
|
|
|
66
72
|
DocumentRetrievalMetricsDataLoader,
|
|
67
73
|
ExperimentAnnotationSummaryDataLoader,
|
|
68
74
|
ExperimentErrorRatesDataLoader,
|
|
75
|
+
ExperimentRunAnnotations,
|
|
69
76
|
ExperimentRunCountsDataLoader,
|
|
70
77
|
ExperimentSequenceNumberDataLoader,
|
|
71
78
|
LatencyMsQuantileDataLoader,
|
|
@@ -94,10 +101,13 @@ from phoenix.server.types import (
|
|
|
94
101
|
LastUpdatedAt,
|
|
95
102
|
)
|
|
96
103
|
from phoenix.trace.fixtures import (
|
|
104
|
+
TracesFixture,
|
|
105
|
+
get_dataset_fixtures,
|
|
97
106
|
get_evals_from_fixture,
|
|
98
107
|
get_trace_fixture_by_name,
|
|
99
108
|
load_example_traces,
|
|
100
109
|
reset_fixture_span_ids_and_timestamps,
|
|
110
|
+
send_dataset_fixtures,
|
|
101
111
|
)
|
|
102
112
|
from phoenix.trace.otel import decode_otlp_span, encode_span_to_otlp
|
|
103
113
|
from phoenix.trace.schemas import Span
|
|
@@ -249,6 +259,7 @@ class Scaffolder(DaemonTask):
|
|
|
249
259
|
queue_evaluation: Callable[[pb.Evaluation], Awaitable[None]],
|
|
250
260
|
tracing_fixture_names: Set[str] = set(),
|
|
251
261
|
force_fixture_ingestion: bool = False,
|
|
262
|
+
scaffold_datasets: bool = False,
|
|
252
263
|
) -> None:
|
|
253
264
|
super().__init__()
|
|
254
265
|
self._db = db
|
|
@@ -258,6 +269,7 @@ class Scaffolder(DaemonTask):
|
|
|
258
269
|
get_trace_fixture_by_name(name) for name in tracing_fixture_names
|
|
259
270
|
)
|
|
260
271
|
self._force_fixture_ingestion = force_fixture_ingestion
|
|
272
|
+
self._scaffold_datasets = scaffold_datasets
|
|
261
273
|
|
|
262
274
|
async def __aenter__(self) -> None:
|
|
263
275
|
await self.start()
|
|
@@ -271,7 +283,7 @@ class Scaffolder(DaemonTask):
|
|
|
271
283
|
Determines whether to load fixtures and handles them.
|
|
272
284
|
"""
|
|
273
285
|
if await self._should_load_fixtures():
|
|
274
|
-
logger.info("Loading trace fixtures
|
|
286
|
+
logger.info("Loading trace fixtures...")
|
|
275
287
|
await self._handle_tracing_fixtures()
|
|
276
288
|
logger.info("Finished loading fixtures.")
|
|
277
289
|
else:
|
|
@@ -316,6 +328,10 @@ class Scaffolder(DaemonTask):
|
|
|
316
328
|
get_evals_from_fixture(fixture.name),
|
|
317
329
|
)
|
|
318
330
|
|
|
331
|
+
# Ingest dataset fixtures
|
|
332
|
+
if self._scaffold_datasets:
|
|
333
|
+
await self._handle_dataset_fixtures(fixture)
|
|
334
|
+
|
|
319
335
|
project_name = fixture.project_name or fixture.name
|
|
320
336
|
logger.info(f"Loading '{project_name}' fixtures...")
|
|
321
337
|
for span in fixture_spans:
|
|
@@ -330,6 +346,19 @@ class Scaffolder(DaemonTask):
|
|
|
330
346
|
except Exception as e:
|
|
331
347
|
logger.error(f"Unexpected error processing fixture '{fixture.name}': {e}")
|
|
332
348
|
|
|
349
|
+
async def _handle_dataset_fixtures(self, fixture: TracesFixture) -> None:
|
|
350
|
+
loop = asyncio.get_running_loop()
|
|
351
|
+
try:
|
|
352
|
+
dataset_fixtures = await loop.run_in_executor(None, get_dataset_fixtures, fixture.name)
|
|
353
|
+
await loop.run_in_executor(
|
|
354
|
+
None,
|
|
355
|
+
send_dataset_fixtures,
|
|
356
|
+
f"http://{get_env_host()}:{get_env_port()}",
|
|
357
|
+
dataset_fixtures,
|
|
358
|
+
)
|
|
359
|
+
except Exception as e:
|
|
360
|
+
logger.error(f"Error processing dataset fixture: {e}")
|
|
361
|
+
|
|
333
362
|
|
|
334
363
|
def _lifespan(
|
|
335
364
|
*,
|
|
@@ -343,6 +372,7 @@ def _lifespan(
|
|
|
343
372
|
read_only: bool = False,
|
|
344
373
|
tracing_fixture_names: Set[str] = set(),
|
|
345
374
|
force_fixture_ingestion: bool = False,
|
|
375
|
+
scaffold_datasets: bool = False,
|
|
346
376
|
) -> StatefulLifespan[FastAPI]:
|
|
347
377
|
@contextlib.asynccontextmanager
|
|
348
378
|
async def lifespan(_: FastAPI) -> AsyncIterator[Dict[str, Any]]:
|
|
@@ -364,6 +394,7 @@ def _lifespan(
|
|
|
364
394
|
queue_evaluation=queue_evaluation,
|
|
365
395
|
tracing_fixture_names=tracing_fixture_names,
|
|
366
396
|
force_fixture_ingestion=force_fixture_ingestion,
|
|
397
|
+
scaffold_datasets=scaffold_datasets,
|
|
367
398
|
):
|
|
368
399
|
for callback in startup_callbacks:
|
|
369
400
|
callback()
|
|
@@ -446,6 +477,7 @@ def create_graphql_router(
|
|
|
446
477
|
),
|
|
447
478
|
experiment_annotation_summaries=ExperimentAnnotationSummaryDataLoader(db),
|
|
448
479
|
experiment_error_rates=ExperimentErrorRatesDataLoader(db),
|
|
480
|
+
experiment_run_annotations=ExperimentRunAnnotations(db),
|
|
449
481
|
experiment_run_counts=ExperimentRunCountsDataLoader(db),
|
|
450
482
|
experiment_sequence_number=ExperimentSequenceNumberDataLoader(db),
|
|
451
483
|
latency_ms_quantile=LatencyMsQuantileDataLoader(
|
|
@@ -557,6 +589,7 @@ def create_app(
|
|
|
557
589
|
secret: Optional[str] = None,
|
|
558
590
|
tracing_fixture_names: Set[str] = set(),
|
|
559
591
|
force_fixture_ingestion: bool = False,
|
|
592
|
+
scaffold_datasets: bool = False,
|
|
560
593
|
) -> FastAPI:
|
|
561
594
|
startup_callbacks_list: List[Callable[[], None]] = list(startup_callbacks)
|
|
562
595
|
shutdown_callbacks_list: List[Callable[[], None]] = list(shutdown_callbacks)
|
|
@@ -644,6 +677,7 @@ def create_app(
|
|
|
644
677
|
startup_callbacks=startup_callbacks_list,
|
|
645
678
|
tracing_fixture_names=tracing_fixture_names,
|
|
646
679
|
force_fixture_ingestion=force_fixture_ingestion,
|
|
680
|
+
scaffold_datasets=scaffold_datasets,
|
|
647
681
|
),
|
|
648
682
|
middleware=[
|
|
649
683
|
Middleware(HeadersMiddleware),
|
|
@@ -186,6 +186,7 @@ class _AnnotationDmlEventHandler(
|
|
|
186
186
|
async def __call__(self) -> None:
|
|
187
187
|
async with self._db() as session:
|
|
188
188
|
async for row in await session.stream(self._get_stmt()):
|
|
189
|
+
self._last_updated_at.set(Project, row.id)
|
|
189
190
|
if cache := self._cache_for_dataloaders:
|
|
190
191
|
self._clear(cache, row.id, row.name)
|
|
191
192
|
|