arize-phoenix 10.11.0__py3-none-any.whl → 10.13.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-10.11.0.dist-info → arize_phoenix-10.13.0.dist-info}/METADATA +1 -1
- {arize_phoenix-10.11.0.dist-info → arize_phoenix-10.13.0.dist-info}/RECORD +25 -25
- phoenix/config.py +15 -0
- phoenix/server/api/helpers/playground_clients.py +0 -1
- phoenix/server/api/queries.py +10 -0
- phoenix/server/api/routers/v1/spans.py +164 -3
- phoenix/server/api/types/Project.py +19 -0
- phoenix/server/app.py +4 -0
- phoenix/server/main.py +3 -0
- phoenix/server/static/.vite/manifest.json +36 -36
- phoenix/server/static/assets/{components-DGavuwFF.js → components-37rV35eH.js} +256 -256
- phoenix/server/static/assets/{index-DNmPxkEL.js → index-CdNW7TcY.js} +2 -2
- phoenix/server/static/assets/{pages-Bns7xROJ.js → pages-BWWAYqfd.js} +545 -478
- phoenix/server/static/assets/{vendor-ARQZvmz5.js → vendor-BKYy4SMr.js} +1 -1
- phoenix/server/static/assets/{vendor-arizeai-Ct6kvW4e.js → vendor-arizeai-hGVPFFRq.js} +22 -22
- phoenix/server/static/assets/{vendor-codemirror-BxoXtD6f.js → vendor-codemirror-BlmFw5CA.js} +1 -1
- phoenix/server/static/assets/{vendor-recharts-Cl8AO7Np.js → vendor-recharts-Bz7zqjbW.js} +1 -1
- phoenix/server/static/assets/{vendor-shiki-BpqODMgR.js → vendor-shiki-BitvudxD.js} +1 -1
- phoenix/server/templates/index.html +24 -0
- phoenix/settings.py +3 -0
- phoenix/version.py +1 -1
- {arize_phoenix-10.11.0.dist-info → arize_phoenix-10.13.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-10.11.0.dist-info → arize_phoenix-10.13.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-10.11.0.dist-info → arize_phoenix-10.13.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-10.11.0.dist-info → arize_phoenix-10.13.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
phoenix/__init__.py,sha256=xkpXH76HFbEDCq8IhiFp-2GnEHx39xPMdOpV5Skew1w,5481
|
|
2
2
|
phoenix/auth.py,sha256=yW78f1xWNjTE30ACGUM14nOd5BzkukhlzA9B45kSUkM,11053
|
|
3
|
-
phoenix/config.py,sha256=
|
|
3
|
+
phoenix/config.py,sha256=1K086wVZDsu8GC1qwk3EBe2Uuw0ZSAhiZhI62PlspaU,57463
|
|
4
4
|
phoenix/datetime_utils.py,sha256=iJzNG6YJ6V7_u8B2iA7P2Z26FyxYbOPtx0dhJ7kNDHA,3398
|
|
5
5
|
phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
7
|
phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
|
|
8
|
-
phoenix/settings.py,sha256=
|
|
9
|
-
phoenix/version.py,sha256=
|
|
8
|
+
phoenix/settings.py,sha256=2kHfT3BNOVd4dAO1bq-syEQbHSG8oX2-7NhOwK2QREk,896
|
|
9
|
+
phoenix/version.py,sha256=ZCckrFpi-O_8Vaq7PPbDoo6WhScFhLb8iXD_3Rb_SpY,24
|
|
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=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
|
|
@@ -89,14 +89,14 @@ phoenix/pointcloud/pointcloud.py,sha256=SN_1wXZcwKrtSnHGZLDZGx71orqE1WyVF7E-D58d
|
|
|
89
89
|
phoenix/pointcloud/projectors.py,sha256=TQgwc9cJDjJkin1WZyZzgl3HsYrLLiyWD7Czy4jNW3U,1088
|
|
90
90
|
phoenix/pointcloud/umap_parameters.py,sha256=db_WEPoamuWtopZx7tQfAXPnoE0MS8FkAV0_ThjEx_Q,1735
|
|
91
91
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
92
|
-
phoenix/server/app.py,sha256=
|
|
92
|
+
phoenix/server/app.py,sha256=PFXCs_lGUr_LxLktje4dYI3TZmw8VC3KgXzZexfVQ8Q,41497
|
|
93
93
|
phoenix/server/authorization.py,sha256=fofeRwuoodCUB3DQYPCuAgIyeiwopXW0tkH_KZvU0Rg,1848
|
|
94
94
|
phoenix/server/bearer_auth.py,sha256=b2iHV2nwvWlZJ2O_nWOzHctJ0aUrEIOygIDrO7VOCSw,6700
|
|
95
95
|
phoenix/server/dml_event.py,sha256=MjJmVEKytq75chBOSyvYDusUnEbg1pHpIjR3pZkUaJA,2838
|
|
96
96
|
phoenix/server/dml_event_handler.py,sha256=EZLXmCvx4pJrCkz29gxwKwmvmUkTtPCHw6klR-XM8qE,8258
|
|
97
97
|
phoenix/server/grpc_server.py,sha256=dod29zE_Zlir7NyLcdVM8GH3P8sy-9ykzfaBfVifyE4,4656
|
|
98
98
|
phoenix/server/jwt_store.py,sha256=B6uVildN_dQDTG_-aHHvuVSI7wIVK1yvED-_y6se2GU,16905
|
|
99
|
-
phoenix/server/main.py,sha256=
|
|
99
|
+
phoenix/server/main.py,sha256=j00TIU7QYOIXaJW9EpqsjEACKtwtSy70s0zWdwfuPw0,18436
|
|
100
100
|
phoenix/server/oauth2.py,sha256=GvUqZBoZ5dG-l2G1RMl1SUcN10jNAjaMXFznMSWz2Zs,3336
|
|
101
101
|
phoenix/server/prometheus.py,sha256=1KjvSfjSa2-BPjDybVMM_Kag316CsN-Zwt64YNr_snc,7825
|
|
102
102
|
phoenix/server/rate_limiters.py,sha256=cFc73D2NaxqNZZDbwfIDw4So-fRVOJPBtqxOZ8Qky_s,7155
|
|
@@ -110,7 +110,7 @@ phoenix/server/api/auth.py,sha256=cvKH2FQLL7PasiqZMHgu9P4qchhEG7a7P9Nxy35FoIQ,15
|
|
|
110
110
|
phoenix/server/api/context.py,sha256=oxNmVIIyycl22iQZjv59lU1inwlo-Povxe2Ok7t54mw,6954
|
|
111
111
|
phoenix/server/api/exceptions.py,sha256=TA0JuY2YRnj35qGuMSQ8d0ToHum9gWm9W--3fSKHrX0,1171
|
|
112
112
|
phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
|
|
113
|
-
phoenix/server/api/queries.py,sha256=
|
|
113
|
+
phoenix/server/api/queries.py,sha256=J2OU59r6Jq5zs4fFl_nawj56dcBXH8iz5Ze_02YjVog,41606
|
|
114
114
|
phoenix/server/api/schema.py,sha256=fcs36xQwFF_Qe41_5cWR8wYpDvOrnbcyTeo5WNMbDsA,1702
|
|
115
115
|
phoenix/server/api/subscriptions.py,sha256=73s6TzwI2M_bjIZDYwgohdI_13iv7pgpLCvZYNuExnw,23777
|
|
116
116
|
phoenix/server/api/utils.py,sha256=quCBRcusc6PUq9tJq7M8PgwFZp7nXgVAxtbw8feribY,833
|
|
@@ -158,7 +158,7 @@ phoenix/server/api/helpers/__init__.py,sha256=m2-xaSPqUiSs91k62JaRDjFNfl-1byxBfY
|
|
|
158
158
|
phoenix/server/api/helpers/annotations.py,sha256=9gMXKpMTfWEChoSCnvdWYuyB0hlSnNOp-qUdar9Vono,262
|
|
159
159
|
phoenix/server/api/helpers/dataset_helpers.py,sha256=DoMBTg-qXTnC_K4Evx1WKpCCYgRbITpVqyY-8efJRf0,8984
|
|
160
160
|
phoenix/server/api/helpers/experiment_run_filters.py,sha256=DOnVwrmn39eAkk2mwuZP8kIcAnR5jrOgllEwWSjsw94,29893
|
|
161
|
-
phoenix/server/api/helpers/playground_clients.py,sha256=
|
|
161
|
+
phoenix/server/api/helpers/playground_clients.py,sha256=laFDXVnj-n5-nze5OeJSLT5nwdz2IWFTVccKNcLqK7U,47932
|
|
162
162
|
phoenix/server/api/helpers/playground_registry.py,sha256=CPLMziFB2wmr-dfbx7VbzO2f8YIG_k5RftzvGXYGQ1w,2570
|
|
163
163
|
phoenix/server/api/helpers/playground_spans.py,sha256=QpXwPl_fFNwm_iA1A77XApUyXMl1aDmonw8aXuNZ_4k,17132
|
|
164
164
|
phoenix/server/api/helpers/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -242,7 +242,7 @@ phoenix/server/api/routers/v1/experiments.py,sha256=V9_sxqLTE1MKGFu9H3FEdGKr70lY
|
|
|
242
242
|
phoenix/server/api/routers/v1/models.py,sha256=p3gJN-9SWiUYTUTft4bZMsZVCBNTb4nN1Foy68eRZzQ,1997
|
|
243
243
|
phoenix/server/api/routers/v1/projects.py,sha256=LFWxHYPRZy-1EvroNylL635vU1UuDbcuRo1oD26yBnw,12551
|
|
244
244
|
phoenix/server/api/routers/v1/prompts.py,sha256=aBOUBwLDzZDIzJQkxJcR8ZKnakNJOLMwzsLKINSs1mA,26545
|
|
245
|
-
phoenix/server/api/routers/v1/spans.py,sha256=
|
|
245
|
+
phoenix/server/api/routers/v1/spans.py,sha256=HhZtXsNTdOmMXWtMkz3VUb3aqpGsVAU5XOYi2KfvGMc,44106
|
|
246
246
|
phoenix/server/api/routers/v1/traces.py,sha256=DfzeszQvtlrVxvurJLaWJJAhkCZ4BodLwpFuBYPwN5Q,8206
|
|
247
247
|
phoenix/server/api/routers/v1/users.py,sha256=ZcW3if0L8-lUusTzET7fhlhvnmiCICDrGimzB7i3irc,11947
|
|
248
248
|
phoenix/server/api/routers/v1/utils.py,sha256=oXIOGPzPTkE0ZWUTRCoRIQQ7wTzoSwtWFaUSjlGBqts,4960
|
|
@@ -295,7 +295,7 @@ phoenix/server/api/types/MimeType.py,sha256=Zpi6zCalkSFgsvhzvOs-O1gYA04usAi9H__Q
|
|
|
295
295
|
phoenix/server/api/types/Model.py,sha256=8UIFqMe1q-2ufBNg-gxHusV8wM1h-KbfLUeJjyVcMvQ,8081
|
|
296
296
|
phoenix/server/api/types/NumericRange.py,sha256=afEjgF97Go_OvmjMggbPBt-zGM8IONewAyEiKEHRds0,192
|
|
297
297
|
phoenix/server/api/types/PerformanceMetric.py,sha256=KFkmJDqP43eDUtARQOUqR7NYcxvL6Vh2uisHWU6H3ko,387
|
|
298
|
-
phoenix/server/api/types/Project.py,sha256=
|
|
298
|
+
phoenix/server/api/types/Project.py,sha256=FulRsgTWcvZEyiV3lzJ505HMa9Eq7aoQr3OkbPWH2Ws,29864
|
|
299
299
|
phoenix/server/api/types/ProjectSession.py,sha256=fyfVtpUpFOTnBx8DFnH3dr7WXAssN0ooAgrQSSi7kEI,4677
|
|
300
300
|
phoenix/server/api/types/ProjectTraceRetentionPolicy.py,sha256=tYy2kgalPDyuaYZr0VUHjH0YpXaiF_QOzg5yfaV_c7c,3782
|
|
301
301
|
phoenix/server/api/types/Prompt.py,sha256=ccP4eq1e38xbF0afclGWLOuDpBVpNbJ3AOSRClF8yFQ,4955
|
|
@@ -350,19 +350,19 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
350
350
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
351
351
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
352
352
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
353
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
354
|
-
phoenix/server/static/assets/components-
|
|
355
|
-
phoenix/server/static/assets/index-
|
|
356
|
-
phoenix/server/static/assets/pages-
|
|
357
|
-
phoenix/server/static/assets/vendor-
|
|
353
|
+
phoenix/server/static/.vite/manifest.json,sha256=FX0jH9ulkLFAOYFQ_fY2V_eLblREsX4bRMst-NAYskU,2165
|
|
354
|
+
phoenix/server/static/assets/components-37rV35eH.js,sha256=bkm_c7mVyxDrVczT2PTykcER8YdFKEhJOWilzyoZj7c,566746
|
|
355
|
+
phoenix/server/static/assets/index-CdNW7TcY.js,sha256=VUdSy0fh-bRVlI9kH5irs9iJknpeEJvE4V7C8xgq-IM,61125
|
|
356
|
+
phoenix/server/static/assets/pages-BWWAYqfd.js,sha256=dVpjKI0o-nl6MgAi4HZvQwixBPWSQimxYNrKjSkkTDI,1061332
|
|
357
|
+
phoenix/server/static/assets/vendor-BKYy4SMr.js,sha256=lUYFHNxWckrqWult9uTiNwc6-Qv5Bfr1IcjrHoos1oU,2735976
|
|
358
358
|
phoenix/server/static/assets/vendor-WIZid84E.css,sha256=spZD2r7XL5GfLO13ln-IuXfnjAref8l6g_n_AvxxOlI,5517
|
|
359
|
-
phoenix/server/static/assets/vendor-arizeai-
|
|
360
|
-
phoenix/server/static/assets/vendor-codemirror-
|
|
361
|
-
phoenix/server/static/assets/vendor-recharts-
|
|
362
|
-
phoenix/server/static/assets/vendor-shiki-
|
|
359
|
+
phoenix/server/static/assets/vendor-arizeai-hGVPFFRq.js,sha256=pcKvIP_UPEeg-UJpM4DKz0bQQ1X1eIfmwz16Uu7pTY4,178469
|
|
360
|
+
phoenix/server/static/assets/vendor-codemirror-BlmFw5CA.js,sha256=QODyQdDaw_c_n-qaHcjfGxzU2ECerJcAVtnaF-8L6O4,781264
|
|
361
|
+
phoenix/server/static/assets/vendor-recharts-Bz7zqjbW.js,sha256=c7rl5xi-366k-e16Udyr6M_ZADAZGELnUOJrBR-1PBc,282150
|
|
362
|
+
phoenix/server/static/assets/vendor-shiki-BitvudxD.js,sha256=cVscU0RuS8MzpAVyJc4N28iswI9hNRUM_9rUO0RR0ug,8980312
|
|
363
363
|
phoenix/server/static/assets/vendor-three-C5WAXd5r.js,sha256=ELkg06u70N7h8oFmvqdoHyPuUf9VgGEWeT4LKFx4VWo,620975
|
|
364
364
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
365
|
-
phoenix/server/templates/index.html,sha256=
|
|
365
|
+
phoenix/server/templates/index.html,sha256=TxaZTZKUz7-xQ3XlPO3DAPMj6S1rMEr5v6g1UmgaW70,6761
|
|
366
366
|
phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
367
367
|
phoenix/session/client.py,sha256=uw5WlCuFcN_eEj7Ko2bhJVcaihEIp7Evy50KnL6Sq-k,35602
|
|
368
368
|
phoenix/session/data_extractor.py,sha256=Y0RzYFaNy9fQj8PEIeQ76TBZ90_E1FW7bXu3K5x0EZY,2782
|
|
@@ -400,9 +400,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
|
|
|
400
400
|
phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
|
|
401
401
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
402
402
|
phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
|
|
403
|
-
arize_phoenix-10.
|
|
404
|
-
arize_phoenix-10.
|
|
405
|
-
arize_phoenix-10.
|
|
406
|
-
arize_phoenix-10.
|
|
407
|
-
arize_phoenix-10.
|
|
408
|
-
arize_phoenix-10.
|
|
403
|
+
arize_phoenix-10.13.0.dist-info/METADATA,sha256=-62CQ8KNaGaN5BH9v0396cVRQ0hiBNE1ZYq6YUJ5jFM,27006
|
|
404
|
+
arize_phoenix-10.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
405
|
+
arize_phoenix-10.13.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
|
|
406
|
+
arize_phoenix-10.13.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
407
|
+
arize_phoenix-10.13.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
408
|
+
arize_phoenix-10.13.0.dist-info/RECORD,,
|
phoenix/config.py
CHANGED
|
@@ -50,6 +50,11 @@ ENV_PHOENIX_PROJECT_NAME = "PHOENIX_PROJECT_NAME"
|
|
|
50
50
|
"""
|
|
51
51
|
The project name to use when logging traces and evals. defaults to 'default'.
|
|
52
52
|
"""
|
|
53
|
+
ENV_PHOENIX_FULLSTORY_ORG = "PHOENIX_FULLSTORY_ORG"
|
|
54
|
+
"""
|
|
55
|
+
The FullStory organization ID for web analytics tracking. When set, FullStory tracking
|
|
56
|
+
will be enabled in the Phoenix web interface.
|
|
57
|
+
"""
|
|
53
58
|
ENV_PHOENIX_SQL_DATABASE_URL = "PHOENIX_SQL_DATABASE_URL"
|
|
54
59
|
"""
|
|
55
60
|
The SQL database URL to use when logging traces and evals.
|
|
@@ -1520,6 +1525,16 @@ def get_env_allowed_origins() -> Optional[list[str]]:
|
|
|
1520
1525
|
return allowed_origins.split(",")
|
|
1521
1526
|
|
|
1522
1527
|
|
|
1528
|
+
def get_env_fullstory_org() -> Optional[str]:
|
|
1529
|
+
"""
|
|
1530
|
+
Get the FullStory organization ID from environment variables.
|
|
1531
|
+
|
|
1532
|
+
Returns:
|
|
1533
|
+
Optional[str]: The FullStory organization ID if set, None otherwise.
|
|
1534
|
+
"""
|
|
1535
|
+
return getenv(ENV_PHOENIX_FULLSTORY_ORG)
|
|
1536
|
+
|
|
1537
|
+
|
|
1523
1538
|
def verify_server_environment_variables() -> None:
|
|
1524
1539
|
"""Verify that the environment variables are set correctly. Raises an error otherwise."""
|
|
1525
1540
|
get_env_root_url()
|
phoenix/server/api/queries.py
CHANGED
|
@@ -319,6 +319,16 @@ class Query:
|
|
|
319
319
|
after: Optional[CursorString] = UNSET,
|
|
320
320
|
filter_condition: Optional[str] = UNSET,
|
|
321
321
|
) -> Connection[ExperimentComparison]:
|
|
322
|
+
# Handle empty experiment_ids gracefully
|
|
323
|
+
if not experiment_ids:
|
|
324
|
+
return connection_from_list(
|
|
325
|
+
data=[],
|
|
326
|
+
args=ConnectionArgs(
|
|
327
|
+
first=first,
|
|
328
|
+
after=after if isinstance(after, CursorString) else None,
|
|
329
|
+
),
|
|
330
|
+
)
|
|
331
|
+
|
|
322
332
|
experiment_ids_ = [
|
|
323
333
|
from_global_id_with_expected_type(experiment_id, OrmExperiment.__name__)
|
|
324
334
|
for experiment_id in experiment_ids
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import warnings
|
|
2
3
|
from asyncio import get_running_loop
|
|
3
4
|
from collections.abc import AsyncIterator
|
|
@@ -12,7 +13,12 @@ from pydantic import BaseModel, Field
|
|
|
12
13
|
from sqlalchemy import select
|
|
13
14
|
from starlette.requests import Request
|
|
14
15
|
from starlette.responses import Response, StreamingResponse
|
|
15
|
-
from starlette.status import
|
|
16
|
+
from starlette.status import (
|
|
17
|
+
HTTP_202_ACCEPTED,
|
|
18
|
+
HTTP_400_BAD_REQUEST,
|
|
19
|
+
HTTP_404_NOT_FOUND,
|
|
20
|
+
HTTP_422_UNPROCESSABLE_ENTITY,
|
|
21
|
+
)
|
|
16
22
|
from strawberry.relay import GlobalID
|
|
17
23
|
|
|
18
24
|
from phoenix.config import DEFAULT_PROJECT_NAME
|
|
@@ -26,6 +32,19 @@ from phoenix.server.bearer_auth import PhoenixUser
|
|
|
26
32
|
from phoenix.server.dml_event import SpanAnnotationInsertEvent
|
|
27
33
|
from phoenix.trace.attributes import flatten
|
|
28
34
|
from phoenix.trace.dsl import SpanQuery as SpanQuery_
|
|
35
|
+
from phoenix.trace.schemas import (
|
|
36
|
+
Span as SpanForInsertion,
|
|
37
|
+
)
|
|
38
|
+
from phoenix.trace.schemas import (
|
|
39
|
+
SpanContext as InsertionSpanContext,
|
|
40
|
+
)
|
|
41
|
+
from phoenix.trace.schemas import (
|
|
42
|
+
SpanEvent as InternalSpanEvent,
|
|
43
|
+
)
|
|
44
|
+
from phoenix.trace.schemas import (
|
|
45
|
+
SpanKind,
|
|
46
|
+
SpanStatusCode,
|
|
47
|
+
)
|
|
29
48
|
from phoenix.utilities.json import encode_df_as_json_string
|
|
30
49
|
|
|
31
50
|
from .models import V1RoutesBaseModel
|
|
@@ -393,7 +412,9 @@ class SpanEvent(V1RoutesBaseModel):
|
|
|
393
412
|
|
|
394
413
|
|
|
395
414
|
class Span(V1RoutesBaseModel):
|
|
396
|
-
id: str = Field(
|
|
415
|
+
id: str = Field(
|
|
416
|
+
default="", description="Span Global ID, distinct from the OpenTelemetry span ID"
|
|
417
|
+
)
|
|
397
418
|
name: str = Field(description="Name of the span operation")
|
|
398
419
|
context: SpanContext = Field(description="Span context containing trace_id and span_id")
|
|
399
420
|
span_kind: str = Field(description="Type of work that the span encapsulates")
|
|
@@ -440,7 +461,7 @@ async def query_spans_handler(
|
|
|
440
461
|
)
|
|
441
462
|
end_time = request_body.end_time or request_body.stop_time
|
|
442
463
|
try:
|
|
443
|
-
span_queries = [SpanQuery_.from_dict(query.
|
|
464
|
+
span_queries = [SpanQuery_.from_dict(query.model_dump()) for query in queries]
|
|
444
465
|
except Exception as e:
|
|
445
466
|
raise HTTPException(
|
|
446
467
|
detail=f"Invalid query: {e}",
|
|
@@ -956,3 +977,143 @@ async def annotate_spans(
|
|
|
956
977
|
for id_ in inserted_ids
|
|
957
978
|
]
|
|
958
979
|
)
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
class CreateSpansRequestBody(RequestBody[list[Span]]):
|
|
983
|
+
data: list[Span]
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
class CreateSpansResponseBody(V1RoutesBaseModel):
|
|
987
|
+
total_received: int = Field(description="Total number of spans received")
|
|
988
|
+
total_queued: int = Field(description="Number of spans successfully queued for insertion")
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
@router.post(
|
|
992
|
+
"/projects/{project_identifier}/spans",
|
|
993
|
+
operation_id="createSpans",
|
|
994
|
+
summary="Create spans",
|
|
995
|
+
description=(
|
|
996
|
+
"Submit spans to be inserted into a project. If any spans are invalid or "
|
|
997
|
+
"duplicates, no spans will be inserted."
|
|
998
|
+
),
|
|
999
|
+
responses=add_errors_to_responses([HTTP_404_NOT_FOUND, HTTP_400_BAD_REQUEST]),
|
|
1000
|
+
status_code=HTTP_202_ACCEPTED,
|
|
1001
|
+
)
|
|
1002
|
+
async def create_spans(
|
|
1003
|
+
request: Request,
|
|
1004
|
+
request_body: CreateSpansRequestBody,
|
|
1005
|
+
project_identifier: str = Path(
|
|
1006
|
+
description=(
|
|
1007
|
+
"The project identifier: either project ID or project name. If using a project name, "
|
|
1008
|
+
"it cannot contain slash (/), question mark (?), or pound sign (#) characters."
|
|
1009
|
+
)
|
|
1010
|
+
),
|
|
1011
|
+
) -> CreateSpansResponseBody:
|
|
1012
|
+
def convert_api_span_for_insertion(api_span: Span) -> SpanForInsertion:
|
|
1013
|
+
"""
|
|
1014
|
+
Convert from API Span to phoenix.trace.schemas.Span
|
|
1015
|
+
Note: The 'id' field has a default empty string and is ignored during insertion.
|
|
1016
|
+
"""
|
|
1017
|
+
try:
|
|
1018
|
+
span_kind = SpanKind(api_span.span_kind.upper())
|
|
1019
|
+
except ValueError:
|
|
1020
|
+
span_kind = SpanKind.UNKNOWN
|
|
1021
|
+
|
|
1022
|
+
try:
|
|
1023
|
+
status_code = SpanStatusCode(api_span.status_code.upper())
|
|
1024
|
+
except ValueError:
|
|
1025
|
+
status_code = SpanStatusCode.UNSET
|
|
1026
|
+
|
|
1027
|
+
internal_events: list[InternalSpanEvent] = []
|
|
1028
|
+
for event in api_span.events:
|
|
1029
|
+
if event.timestamp:
|
|
1030
|
+
internal_events.append(
|
|
1031
|
+
InternalSpanEvent(
|
|
1032
|
+
name=event.name, timestamp=event.timestamp, attributes=event.attributes
|
|
1033
|
+
)
|
|
1034
|
+
)
|
|
1035
|
+
|
|
1036
|
+
# Add back the openinference.span.kind attribute since it's stored separately in the API
|
|
1037
|
+
attributes = dict(api_span.attributes)
|
|
1038
|
+
attributes["openinference.span.kind"] = api_span.span_kind
|
|
1039
|
+
|
|
1040
|
+
# Create span for insertion - note we ignore the 'id' field as it's server-generated
|
|
1041
|
+
return SpanForInsertion(
|
|
1042
|
+
name=api_span.name,
|
|
1043
|
+
context=InsertionSpanContext(
|
|
1044
|
+
trace_id=api_span.context.trace_id, span_id=api_span.context.span_id
|
|
1045
|
+
),
|
|
1046
|
+
span_kind=span_kind,
|
|
1047
|
+
parent_id=api_span.parent_id,
|
|
1048
|
+
start_time=api_span.start_time,
|
|
1049
|
+
end_time=api_span.end_time,
|
|
1050
|
+
status_code=status_code,
|
|
1051
|
+
status_message=api_span.status_message,
|
|
1052
|
+
attributes=attributes,
|
|
1053
|
+
events=internal_events,
|
|
1054
|
+
conversation=None, # Unused
|
|
1055
|
+
)
|
|
1056
|
+
|
|
1057
|
+
async with request.app.state.db() as session:
|
|
1058
|
+
project = await _get_project_by_identifier(session, project_identifier)
|
|
1059
|
+
|
|
1060
|
+
total_received = len(request_body.data)
|
|
1061
|
+
duplicate_spans: list[dict[str, str]] = []
|
|
1062
|
+
invalid_spans: list[dict[str, str]] = []
|
|
1063
|
+
spans_to_queue: list[tuple[SpanForInsertion, str]] = []
|
|
1064
|
+
|
|
1065
|
+
existing_span_ids: set[str] = set()
|
|
1066
|
+
span_ids = [span.context.span_id for span in request_body.data]
|
|
1067
|
+
async with request.app.state.db() as session:
|
|
1068
|
+
existing_result = await session.execute(
|
|
1069
|
+
select(models.Span.span_id).where(models.Span.span_id.in_(span_ids))
|
|
1070
|
+
)
|
|
1071
|
+
existing_span_ids = {row[0] for row in existing_result}
|
|
1072
|
+
|
|
1073
|
+
for api_span in request_body.data:
|
|
1074
|
+
# Check if it's a duplicate
|
|
1075
|
+
if api_span.context.span_id in existing_span_ids:
|
|
1076
|
+
duplicate_spans.append(
|
|
1077
|
+
{
|
|
1078
|
+
"span_id": api_span.context.span_id,
|
|
1079
|
+
"trace_id": api_span.context.trace_id,
|
|
1080
|
+
}
|
|
1081
|
+
)
|
|
1082
|
+
continue
|
|
1083
|
+
|
|
1084
|
+
try:
|
|
1085
|
+
span_for_insertion = convert_api_span_for_insertion(api_span)
|
|
1086
|
+
spans_to_queue.append((span_for_insertion, project.name))
|
|
1087
|
+
except Exception as e:
|
|
1088
|
+
invalid_spans.append(
|
|
1089
|
+
{
|
|
1090
|
+
"span_id": api_span.context.span_id,
|
|
1091
|
+
"trace_id": api_span.context.trace_id,
|
|
1092
|
+
"error": str(e),
|
|
1093
|
+
}
|
|
1094
|
+
)
|
|
1095
|
+
|
|
1096
|
+
# If there are any duplicates or invalid spans, reject the entire request
|
|
1097
|
+
if duplicate_spans or invalid_spans:
|
|
1098
|
+
error_detail = {
|
|
1099
|
+
"error": "Request contains invalid or duplicate spans",
|
|
1100
|
+
"total_received": total_received,
|
|
1101
|
+
"total_queued": 0, # No spans are queued when there are validation errors
|
|
1102
|
+
"total_duplicates": len(duplicate_spans),
|
|
1103
|
+
"total_invalid": len(invalid_spans),
|
|
1104
|
+
"duplicate_spans": duplicate_spans,
|
|
1105
|
+
"invalid_spans": invalid_spans,
|
|
1106
|
+
}
|
|
1107
|
+
raise HTTPException(
|
|
1108
|
+
status_code=HTTP_400_BAD_REQUEST,
|
|
1109
|
+
detail=json.dumps(error_detail),
|
|
1110
|
+
)
|
|
1111
|
+
|
|
1112
|
+
# All spans are valid, queue them all
|
|
1113
|
+
for span_for_insertion, project_name in spans_to_queue:
|
|
1114
|
+
await request.state.queue_span_for_bulk_insert(span_for_insertion, project_name)
|
|
1115
|
+
|
|
1116
|
+
return CreateSpansResponseBody(
|
|
1117
|
+
total_received=total_received,
|
|
1118
|
+
total_queued=len(spans_to_queue),
|
|
1119
|
+
)
|
|
@@ -326,8 +326,27 @@ class Project(Node):
|
|
|
326
326
|
after: Optional[CursorString] = UNSET,
|
|
327
327
|
sort: Optional[ProjectSessionSort] = UNSET,
|
|
328
328
|
filter_io_substring: Optional[str] = UNSET,
|
|
329
|
+
session_id: Optional[str] = UNSET,
|
|
329
330
|
) -> Connection[ProjectSession]:
|
|
330
331
|
table = models.ProjectSession
|
|
332
|
+
if session_id:
|
|
333
|
+
async with info.context.db() as session:
|
|
334
|
+
ans = await session.scalar(
|
|
335
|
+
select(table).filter_by(
|
|
336
|
+
session_id=session_id,
|
|
337
|
+
project_id=self.project_rowid,
|
|
338
|
+
)
|
|
339
|
+
)
|
|
340
|
+
if ans:
|
|
341
|
+
return connection_from_list(
|
|
342
|
+
data=[to_gql_project_session(ans)],
|
|
343
|
+
args=ConnectionArgs(),
|
|
344
|
+
)
|
|
345
|
+
elif not filter_io_substring:
|
|
346
|
+
return connection_from_list(
|
|
347
|
+
data=[],
|
|
348
|
+
args=ConnectionArgs(),
|
|
349
|
+
)
|
|
331
350
|
stmt = select(table).filter_by(project_id=self.project_rowid)
|
|
332
351
|
if time_range:
|
|
333
352
|
if time_range.start:
|
phoenix/server/app.py
CHANGED
|
@@ -214,6 +214,8 @@ class AppConfig(NamedTuple):
|
|
|
214
214
|
oauth2_idps: Sequence[OAuth2Idp]
|
|
215
215
|
basic_auth_disabled: bool = False
|
|
216
216
|
auto_login_idp_name: Optional[str] = None
|
|
217
|
+
fullstory_org: Optional[str] = None
|
|
218
|
+
""" FullStory organization ID for web analytics tracking """
|
|
217
219
|
|
|
218
220
|
|
|
219
221
|
class Static(StaticFiles):
|
|
@@ -279,6 +281,7 @@ class Static(StaticFiles):
|
|
|
279
281
|
"oauth2_idps": self._app_config.oauth2_idps,
|
|
280
282
|
"basic_auth_disabled": self._app_config.basic_auth_disabled,
|
|
281
283
|
"auto_login_idp_name": self._app_config.auto_login_idp_name,
|
|
284
|
+
"fullstory_org": self._app_config.fullstory_org,
|
|
282
285
|
},
|
|
283
286
|
)
|
|
284
287
|
except Exception as e:
|
|
@@ -964,6 +967,7 @@ def create_app(
|
|
|
964
967
|
oauth2_idps=oauth2_idps,
|
|
965
968
|
basic_auth_disabled=basic_auth_disabled,
|
|
966
969
|
auto_login_idp_name=auto_login_idp_name,
|
|
970
|
+
fullstory_org=Settings.fullstory_org,
|
|
967
971
|
),
|
|
968
972
|
),
|
|
969
973
|
name="static",
|
phoenix/server/main.py
CHANGED
|
@@ -25,6 +25,7 @@ from phoenix.config import (
|
|
|
25
25
|
get_env_db_logging_level,
|
|
26
26
|
get_env_disable_migrations,
|
|
27
27
|
get_env_enable_prometheus,
|
|
28
|
+
get_env_fullstory_org,
|
|
28
29
|
get_env_grpc_port,
|
|
29
30
|
get_env_host,
|
|
30
31
|
get_env_host_root_path,
|
|
@@ -484,11 +485,13 @@ def main() -> None:
|
|
|
484
485
|
|
|
485
486
|
|
|
486
487
|
def initialize_settings() -> None:
|
|
488
|
+
"""Initialize the settings from environment variables."""
|
|
487
489
|
Settings.logging_mode = get_env_logging_mode()
|
|
488
490
|
Settings.logging_level = get_env_logging_level()
|
|
489
491
|
Settings.db_logging_level = get_env_db_logging_level()
|
|
490
492
|
Settings.log_migrations = get_env_log_migrations()
|
|
491
493
|
Settings.disable_migrations = get_env_disable_migrations()
|
|
494
|
+
Settings.fullstory_org = get_env_fullstory_org()
|
|
492
495
|
|
|
493
496
|
|
|
494
497
|
if __name__ == "__main__":
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_components-
|
|
3
|
-
"file": "assets/components-
|
|
2
|
+
"_components-37rV35eH.js": {
|
|
3
|
+
"file": "assets/components-37rV35eH.js",
|
|
4
4
|
"name": "components",
|
|
5
5
|
"imports": [
|
|
6
|
-
"_vendor-
|
|
7
|
-
"_pages-
|
|
8
|
-
"_vendor-arizeai-
|
|
9
|
-
"_vendor-codemirror-
|
|
6
|
+
"_vendor-BKYy4SMr.js",
|
|
7
|
+
"_pages-BWWAYqfd.js",
|
|
8
|
+
"_vendor-arizeai-hGVPFFRq.js",
|
|
9
|
+
"_vendor-codemirror-BlmFw5CA.js",
|
|
10
10
|
"_vendor-three-C5WAXd5r.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
|
-
"_pages-
|
|
14
|
-
"file": "assets/pages-
|
|
13
|
+
"_pages-BWWAYqfd.js": {
|
|
14
|
+
"file": "assets/pages-BWWAYqfd.js",
|
|
15
15
|
"name": "pages",
|
|
16
16
|
"imports": [
|
|
17
|
-
"_vendor-
|
|
18
|
-
"_vendor-arizeai-
|
|
19
|
-
"_components-
|
|
20
|
-
"_vendor-codemirror-
|
|
21
|
-
"_vendor-recharts-
|
|
17
|
+
"_vendor-BKYy4SMr.js",
|
|
18
|
+
"_vendor-arizeai-hGVPFFRq.js",
|
|
19
|
+
"_components-37rV35eH.js",
|
|
20
|
+
"_vendor-codemirror-BlmFw5CA.js",
|
|
21
|
+
"_vendor-recharts-Bz7zqjbW.js"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
|
-
"_vendor-
|
|
25
|
-
"file": "assets/vendor-
|
|
24
|
+
"_vendor-BKYy4SMr.js": {
|
|
25
|
+
"file": "assets/vendor-BKYy4SMr.js",
|
|
26
26
|
"name": "vendor",
|
|
27
27
|
"imports": [
|
|
28
28
|
"_vendor-three-C5WAXd5r.js"
|
|
@@ -35,33 +35,33 @@
|
|
|
35
35
|
"file": "assets/vendor-WIZid84E.css",
|
|
36
36
|
"src": "_vendor-WIZid84E.css"
|
|
37
37
|
},
|
|
38
|
-
"_vendor-arizeai-
|
|
39
|
-
"file": "assets/vendor-arizeai-
|
|
38
|
+
"_vendor-arizeai-hGVPFFRq.js": {
|
|
39
|
+
"file": "assets/vendor-arizeai-hGVPFFRq.js",
|
|
40
40
|
"name": "vendor-arizeai",
|
|
41
41
|
"imports": [
|
|
42
|
-
"_vendor-
|
|
42
|
+
"_vendor-BKYy4SMr.js"
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
|
-
"_vendor-codemirror-
|
|
46
|
-
"file": "assets/vendor-codemirror-
|
|
45
|
+
"_vendor-codemirror-BlmFw5CA.js": {
|
|
46
|
+
"file": "assets/vendor-codemirror-BlmFw5CA.js",
|
|
47
47
|
"name": "vendor-codemirror",
|
|
48
48
|
"imports": [
|
|
49
|
-
"_vendor-
|
|
50
|
-
"_vendor-shiki-
|
|
49
|
+
"_vendor-BKYy4SMr.js",
|
|
50
|
+
"_vendor-shiki-BitvudxD.js"
|
|
51
51
|
]
|
|
52
52
|
},
|
|
53
|
-
"_vendor-recharts-
|
|
54
|
-
"file": "assets/vendor-recharts-
|
|
53
|
+
"_vendor-recharts-Bz7zqjbW.js": {
|
|
54
|
+
"file": "assets/vendor-recharts-Bz7zqjbW.js",
|
|
55
55
|
"name": "vendor-recharts",
|
|
56
56
|
"imports": [
|
|
57
|
-
"_vendor-
|
|
57
|
+
"_vendor-BKYy4SMr.js"
|
|
58
58
|
]
|
|
59
59
|
},
|
|
60
|
-
"_vendor-shiki-
|
|
61
|
-
"file": "assets/vendor-shiki-
|
|
60
|
+
"_vendor-shiki-BitvudxD.js": {
|
|
61
|
+
"file": "assets/vendor-shiki-BitvudxD.js",
|
|
62
62
|
"name": "vendor-shiki",
|
|
63
63
|
"imports": [
|
|
64
|
-
"_vendor-
|
|
64
|
+
"_vendor-BKYy4SMr.js"
|
|
65
65
|
]
|
|
66
66
|
},
|
|
67
67
|
"_vendor-three-C5WAXd5r.js": {
|
|
@@ -69,19 +69,19 @@
|
|
|
69
69
|
"name": "vendor-three"
|
|
70
70
|
},
|
|
71
71
|
"index.tsx": {
|
|
72
|
-
"file": "assets/index-
|
|
72
|
+
"file": "assets/index-CdNW7TcY.js",
|
|
73
73
|
"name": "index",
|
|
74
74
|
"src": "index.tsx",
|
|
75
75
|
"isEntry": true,
|
|
76
76
|
"imports": [
|
|
77
|
-
"_vendor-
|
|
78
|
-
"_vendor-arizeai-
|
|
79
|
-
"_pages-
|
|
80
|
-
"_components-
|
|
77
|
+
"_vendor-BKYy4SMr.js",
|
|
78
|
+
"_vendor-arizeai-hGVPFFRq.js",
|
|
79
|
+
"_pages-BWWAYqfd.js",
|
|
80
|
+
"_components-37rV35eH.js",
|
|
81
81
|
"_vendor-three-C5WAXd5r.js",
|
|
82
|
-
"_vendor-codemirror-
|
|
83
|
-
"_vendor-shiki-
|
|
84
|
-
"_vendor-recharts-
|
|
82
|
+
"_vendor-codemirror-BlmFw5CA.js",
|
|
83
|
+
"_vendor-shiki-BitvudxD.js",
|
|
84
|
+
"_vendor-recharts-Bz7zqjbW.js"
|
|
85
85
|
]
|
|
86
86
|
}
|
|
87
87
|
}
|