arize-phoenix 4.35.2__py3-none-any.whl → 4.36.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.35.2.dist-info → arize_phoenix-4.36.0.dist-info}/METADATA +1 -1
- {arize_phoenix-4.35.2.dist-info → arize_phoenix-4.36.0.dist-info}/RECORD +37 -33
- phoenix/config.py +92 -2
- phoenix/db/alembic.ini +0 -34
- phoenix/db/engines.py +27 -10
- phoenix/db/insertion/dataset.py +0 -1
- phoenix/db/insertion/types.py +1 -1
- phoenix/db/migrate.py +3 -3
- phoenix/db/migrations/env.py +0 -7
- phoenix/inferences/fixtures.py +0 -1
- phoenix/inferences/inferences.py +0 -1
- phoenix/logging/__init__.py +3 -0
- phoenix/logging/_config.py +90 -0
- phoenix/logging/_filter.py +6 -0
- phoenix/logging/_formatter.py +69 -0
- phoenix/metrics/__init__.py +0 -1
- phoenix/otel/settings.py +4 -4
- phoenix/server/api/routers/v1/datasets.py +0 -1
- phoenix/server/app.py +2 -3
- phoenix/server/main.py +21 -21
- phoenix/server/telemetry.py +2 -2
- phoenix/services.py +0 -1
- phoenix/session/client.py +0 -1
- phoenix/session/evaluation.py +0 -1
- phoenix/session/session.py +0 -1
- phoenix/settings.py +9 -0
- phoenix/trace/exporter.py +0 -1
- phoenix/trace/fixtures.py +0 -2
- phoenix/trace/langchain/instrumentor.py +0 -1
- phoenix/trace/llama_index/callback.py +0 -1
- phoenix/trace/openai/instrumentor.py +0 -1
- phoenix/utilities/logging.py +9 -1
- phoenix/utilities/re.py +3 -3
- phoenix/version.py +1 -1
- {arize_phoenix-4.35.2.dist-info → arize_phoenix-4.36.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.35.2.dist-info → arize_phoenix-4.36.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.35.2.dist-info → arize_phoenix-4.36.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
phoenix/__init__.py,sha256=om_DSpDIu45_r_bdrataF5jIlQ2LcA1fMnno-ouePyQ,1798
|
|
2
2
|
phoenix/auth.py,sha256=ugvGZlseYX9NkpWaSqb8D2kzUBlAPqT45Dx5_VUANqk,1621
|
|
3
|
-
phoenix/config.py,sha256=
|
|
3
|
+
phoenix/config.py,sha256=U_jiiubbqji1ua8He46UGSsllmGCKU4M6f8kHlGErHw,14032
|
|
4
4
|
phoenix/datetime_utils.py,sha256=yDKjwX2Vtqw9h5F_ProtP-TsXidM43uIvmJ_pOzYc9A,3405
|
|
5
5
|
phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
-
phoenix/services.py,sha256=
|
|
8
|
-
phoenix/settings.py,sha256=
|
|
9
|
-
phoenix/version.py,sha256=
|
|
7
|
+
phoenix/services.py,sha256=aTxhcOA1pZHB6U-B3TEcp6fqDF5oT0xCUvEUNMZVTUQ,5175
|
|
8
|
+
phoenix/settings.py,sha256=ht-0oN-sMV6SPXrk7Tu1EZlngpAYkGNLYPhO8DyrdQI,661
|
|
9
|
+
phoenix/version.py,sha256=N8rRKvtYg5iq14cN-RICfSxhdihpUGicOmVloTAbxnk,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
|
|
@@ -14,24 +14,24 @@ phoenix/core/model_schema.py,sha256=F2dbbVnkDLsPYoyZDv1q03uhvP8LcU1wXp0g-exiWs0,
|
|
|
14
14
|
phoenix/core/model_schema_adapter.py,sha256=0Tm_Y_gV-WED8fKBCaFXAEFwE3CTEZS1dowqnTZ7x7g,8426
|
|
15
15
|
phoenix/db/README.md,sha256=Mjrq0tG68uKQ81mN1Vmu3C795EEpZndmnE6CJXsPCXE,1909
|
|
16
16
|
phoenix/db/__init__.py,sha256=pDjEFXukHmJBM-1D8RjmXkvLsz85YWNxMQczt81ec3A,118
|
|
17
|
-
phoenix/db/alembic.ini,sha256=
|
|
17
|
+
phoenix/db/alembic.ini,sha256=GIS6HpHaKaJbbuahZg1Rc1D2_QqyCkV9r58wdARGf6w,3262
|
|
18
18
|
phoenix/db/bulk_inserter.py,sha256=qgg8pt5k4VnHKOE0-KoReXVAfXRhLt-sMZihI-b4X9I,12761
|
|
19
|
-
phoenix/db/engines.py,sha256=
|
|
19
|
+
phoenix/db/engines.py,sha256=GDko9_Xd41PR-lYYg1lgLGlByCFCUn8mtoKzM1Ax6f8,6481
|
|
20
20
|
phoenix/db/helpers.py,sha256=2zSc4n5IJfu-CaOFoBfqTB35M1nTFcAc8tqLsNtF2Jw,3488
|
|
21
|
-
phoenix/db/migrate.py,sha256=
|
|
21
|
+
phoenix/db/migrate.py,sha256=lf6FFGzdyNjwtQ4TFi3mmHNGnnazMtG30PPB2qRF1Xc,2648
|
|
22
22
|
phoenix/db/models.py,sha256=o97p2H4LeX8YHkTWFsbSGQANW9jHWVf6mJvE9KyFybU,23754
|
|
23
23
|
phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
phoenix/db/insertion/constants.py,sha256=8wifm7X-1XvroZ__R2Gc96NsgLhTDn0zXl4lehlXtcA,70
|
|
25
|
-
phoenix/db/insertion/dataset.py,sha256=
|
|
25
|
+
phoenix/db/insertion/dataset.py,sha256=_vxy5e6W5jEuvO2fMKbbNCn9JvHkwI4LRKk_10eKFVg,7171
|
|
26
26
|
phoenix/db/insertion/document_annotation.py,sha256=qp8E63LzlthAScQg6opqln5Qg1d7UdtP3rkYL4riTgU,5983
|
|
27
27
|
phoenix/db/insertion/evaluation.py,sha256=SoI85N3MYUSeNgjKa5WzFw14OfNjNTjExv-2m3sxaR8,6371
|
|
28
28
|
phoenix/db/insertion/helpers.py,sha256=z_Wnckhdf-F7xadWgaAV5ScXnLft8EtaYJCuIkma2Vw,3486
|
|
29
29
|
phoenix/db/insertion/span.py,sha256=-CXn2LlEv2u7xbz7m8X5jALQ-BUNNzTxPJEzSmjhTpA,5958
|
|
30
30
|
phoenix/db/insertion/span_annotation.py,sha256=eQK7fFjKjZGj25Qf_PTU9Q8DZiYJAw4lfcfdLKFsKe0,5259
|
|
31
31
|
phoenix/db/insertion/trace_annotation.py,sha256=36CwcxSvDo2r-_y_GlmMXGnlH4BKVaMu5BWM9w-9l7A,5324
|
|
32
|
-
phoenix/db/insertion/types.py,sha256=
|
|
32
|
+
phoenix/db/insertion/types.py,sha256=4u5gvQnLQ1DE75PkWtmTp-J02m77669V9UBSibRn9P8,8147
|
|
33
33
|
phoenix/db/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
-
phoenix/db/migrations/env.py,sha256=
|
|
34
|
+
phoenix/db/migrations/env.py,sha256=tFO3ceuCx9Es5_2w_BXclaQMmNQKNX21b1UEV5mYdeo,3387
|
|
35
35
|
phoenix/db/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
|
|
36
36
|
phoenix/db/migrations/future_versions/README.md,sha256=3QtDx40SAD-IITjbdlKR2N_CBxT5y37C1OQs05EDt7o,184
|
|
37
37
|
phoenix/db/migrations/future_versions/cd164e83824f_users_and_tokens.py,sha256=J2HD50V8GPuj6UVFOvUCuXtiTOLPU-MxrhRlMcpdBb0,8795
|
|
@@ -51,12 +51,16 @@ phoenix/experiments/evaluators/llm_evaluators.py,sha256=zyGhxXBDNi1qoj_8I95PRSwj
|
|
|
51
51
|
phoenix/experiments/evaluators/utils.py,sha256=XYqB0bOljyR0GewmR_mm9Ndl_q95EkjjDqfXd7YVqTk,9303
|
|
52
52
|
phoenix/inferences/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
53
|
phoenix/inferences/errors.py,sha256=cGp9vxnw4SewFoWBV3ZGMkhE0Kh73lPIv3Ppz_H_RoA,8261
|
|
54
|
-
phoenix/inferences/fixtures.py,sha256=
|
|
55
|
-
phoenix/inferences/inferences.py,sha256=
|
|
54
|
+
phoenix/inferences/fixtures.py,sha256=X2RehNcNqkwNCgEh5JZsS37it_-rtrMppz-eQUEvefY,20851
|
|
55
|
+
phoenix/inferences/inferences.py,sha256=aH2uHRJR4_W7CVy3EMEioaEBM8cTRYBUyVuDDVjwVXw,31106
|
|
56
56
|
phoenix/inferences/schema.py,sha256=UYej9IJ6pFeNW3fq721kJy16ONso_xVDm78Q68G4hl4,6643
|
|
57
57
|
phoenix/inferences/validation.py,sha256=fdmbsjUBwtacRiVFdh9aem-QrgPfq_OlEmPdascWluc,8297
|
|
58
|
+
phoenix/logging/__init__.py,sha256=94Xsv4tcqRghZhpuyCn4kWV7yJ56X52aXjrWU8RM4hY,64
|
|
59
|
+
phoenix/logging/_config.py,sha256=7z4fReUOJ1h3dFDuVcgSF-pXpqeVqbnV5sxFcVQla1k,2881
|
|
60
|
+
phoenix/logging/_filter.py,sha256=jr95RFp0mgCU5tqTYXp5MSDC-Wgc3UHgPbA9J4URSjo,158
|
|
61
|
+
phoenix/logging/_formatter.py,sha256=2S65uTOhpamtxVFjD0Atk8zf_taZhbk6BpYtOm2JEVE,1777
|
|
58
62
|
phoenix/metrics/README.md,sha256=5gekqTU-5gGdMwvcfNp2Wlu8p1ul9kGY_jq0XXQusoI,1964
|
|
59
|
-
phoenix/metrics/__init__.py,sha256=
|
|
63
|
+
phoenix/metrics/__init__.py,sha256=W8lVORvjBo66pFgUmU9P8Fi8i4yI75wOPkhU42sfeQU,2417
|
|
60
64
|
phoenix/metrics/binning.py,sha256=jDd7YcyEhptCp3zWcH6tfyq87vJ3c8L50ocSuxgPAoQ,12739
|
|
61
65
|
phoenix/metrics/metrics.py,sha256=7SfkDmSnpzGATtBXlYHb42r-2BfV8ELMcMgjdw3c8yA,7907
|
|
62
66
|
phoenix/metrics/mixins.py,sha256=moZ5hENIKzUQt2IRhWOd5EFXnoqQkVrpqEqMH7KQzyA,7440
|
|
@@ -65,20 +69,20 @@ phoenix/metrics/timeseries.py,sha256=Cib3E0njJzi0vZpmyADvbakFQA98rIkfDaYAOmsmBz8
|
|
|
65
69
|
phoenix/metrics/wrappers.py,sha256=umZqa_5lf1wZSFe3FgzxF-qp1xbPdKD54W628GlGCUI,8392
|
|
66
70
|
phoenix/otel/__init__.py,sha256=YvEiD-3aGZs9agwLNCXU34ofV3G-Q-dolfsiinOJuT0,407
|
|
67
71
|
phoenix/otel/otel.py,sha256=Pe_M5eIKN3CQT6JS9FE6CnmWeiP1kG7zxkxzUgVJ_rE,19248
|
|
68
|
-
phoenix/otel/settings.py,sha256=
|
|
72
|
+
phoenix/otel/settings.py,sha256=JYGUeV87NFnhJbp34AjoNiSejn3QYMSdPIx4NpA97tM,3272
|
|
69
73
|
phoenix/pointcloud/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
70
74
|
phoenix/pointcloud/clustering.py,sha256=IzcG67kJ2hPP7pcqVmKPSL_6gKRonKdOT3bCtbTOqnk,820
|
|
71
75
|
phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYGrao,2145
|
|
72
76
|
phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
|
|
73
77
|
phoenix/pointcloud/umap_parameters.py,sha256=3UQSjrysVOvq2V4KNpTMqNqNiK0BsTZnPBHWZ4fyJtQ,1708
|
|
74
78
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
phoenix/server/app.py,sha256=
|
|
79
|
+
phoenix/server/app.py,sha256=kQxDuHWLeDxfym3xvlvOzdw5BuzEW7F3fbPznqizMeQ,28502
|
|
76
80
|
phoenix/server/dml_event.py,sha256=MpjCFqljxvgb9OB5Cez9vJesb3oHb3XxXictynBfcis,2851
|
|
77
81
|
phoenix/server/dml_event_handler.py,sha256=yU23-DDwXcL35p5EPwFW0oZh6mxQxJrJAQPKcYZYJz4,8310
|
|
78
82
|
phoenix/server/grpc_server.py,sha256=XWC2pjSefBBOhM6IXz0oQmjPtnonBvkG9ccUWEfHiiw,3446
|
|
79
|
-
phoenix/server/main.py,sha256=
|
|
83
|
+
phoenix/server/main.py,sha256=b5g48hsLM6LQEwc9cgUru6Bosk0OJD4RsRTaIvvrwHM,14617
|
|
80
84
|
phoenix/server/prometheus.py,sha256=j9DHB2fERuq_ZKmwVaqR-9wx5WcPPuU1Cm5Bhg5241Y,2996
|
|
81
|
-
phoenix/server/telemetry.py,sha256=
|
|
85
|
+
phoenix/server/telemetry.py,sha256=4EluDDrhdDPxAjaW6lVSbi73xkB5XeUCZWOmZGdk0hg,2755
|
|
82
86
|
phoenix/server/thread_server.py,sha256=RwXQGP_QhGD7le6WB7xEygEEuwBl5Ck_Zo8xGIYGi9M,2135
|
|
83
87
|
phoenix/server/types.py,sha256=S2dReLNboR2nzjRK5j3MUyUDqu6AQFD7KRwJkeKj1q4,3609
|
|
84
88
|
phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -161,7 +165,7 @@ phoenix/server/api/openapi/schema.py,sha256=oVZoflWMfzOrLKMIrjr3iLnJ13rmN-t_DOe9
|
|
|
161
165
|
phoenix/server/api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
162
166
|
phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
|
|
163
167
|
phoenix/server/api/routers/v1/__init__.py,sha256=nb49zcOdAi3DSGuC9gUubN9Yri-o7-WFdlGak4jGuFw,1462
|
|
164
|
-
phoenix/server/api/routers/v1/datasets.py,sha256=
|
|
168
|
+
phoenix/server/api/routers/v1/datasets.py,sha256=pyLtVEGnjwxh1wJySBOUFrsjtawatfpaF8F3WijK8qU,37049
|
|
165
169
|
phoenix/server/api/routers/v1/evaluations.py,sha256=FSfz9MTi8s65F07abDXlb9-y97fDZSYbqsCXpimwO7g,12628
|
|
166
170
|
phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=RTQnjupjmh07xowjq77ajbuAZhzIEfYxA4ZtECvGwOU,4844
|
|
167
171
|
phoenix/server/api/routers/v1/experiment_runs.py,sha256=0G7GgGcZv9dzK47tsPp-p4k5O7W4F_aNRrsNuJN7mho,6393
|
|
@@ -255,16 +259,16 @@ phoenix/server/static/assets/vendor-three-DwGkEfCM.js,sha256=0D12ZgKzfKCTSdSTKJB
|
|
|
255
259
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
256
260
|
phoenix/server/templates/index.html,sha256=dAm0IClgJUdT5AOmjZvtgMg8F_xGrRGv95SAkUyx_kg,4325
|
|
257
261
|
phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
258
|
-
phoenix/session/client.py,sha256=
|
|
262
|
+
phoenix/session/client.py,sha256=cLKG3dM_MX4Lc3y-NlqnrxhWJSDDsMvLSwjxaTvcfeE,33813
|
|
259
263
|
phoenix/session/data_extractor.py,sha256=gkEM3WWZAlWGMfRgQopAQlid4cSi6GNco-sdrGir0qc,2788
|
|
260
|
-
phoenix/session/evaluation.py,sha256=
|
|
261
|
-
phoenix/session/session.py,sha256=
|
|
264
|
+
phoenix/session/evaluation.py,sha256=aKeV8UVOyq3b7CYOwt3cWuLz0xzvMjX7vlEPILJ_fcs,5311
|
|
265
|
+
phoenix/session/session.py,sha256=p4l1EI_ynaiWlVx_TpjgIofM0hrVbsPq85ViSIlhIqQ,26953
|
|
262
266
|
phoenix/trace/__init__.py,sha256=ujk_uYjM8gmm-YqnyXxF-kekfwid0bcaPMTtNNcaw6U,407
|
|
263
267
|
phoenix/trace/attributes.py,sha256=B_OrzVaxZwFkrAFXZyicYoIti1UdUysURsvUS2GyW1U,12488
|
|
264
268
|
phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
|
|
265
269
|
phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
|
|
266
|
-
phoenix/trace/exporter.py,sha256=
|
|
267
|
-
phoenix/trace/fixtures.py,sha256=
|
|
270
|
+
phoenix/trace/exporter.py,sha256=bUXh8fjJIbHurrnt4bAm-cCWqUN5FqNsIc8DZzzklkQ,4695
|
|
271
|
+
phoenix/trace/fixtures.py,sha256=4pibRxdvwZ4C7ni-2SN5O7_4meFV5cVucVKZrEmfk3w,18117
|
|
268
272
|
phoenix/trace/otel.py,sha256=WA720jvRadiZBAKjsYoPyXzypHwbyEK2OZRVUwtbjB8,9976
|
|
269
273
|
phoenix/trace/projects.py,sha256=2BwlNjFE-uwpqYtCu5YyBiYZk9wRPpM13vh3-Cv7GkA,2157
|
|
270
274
|
phoenix/trace/schemas.py,sha256=HpWSyzec0yDHEQXEDuwyLbhpvKrqkGps8BJqGiIFj8Y,5978
|
|
@@ -279,11 +283,11 @@ phoenix/trace/dsl/filter.py,sha256=9NwATCUOgJ4Pms8XsEcinROUuxZ9UW-ISV09o65Ms70,3
|
|
|
279
283
|
phoenix/trace/dsl/helpers.py,sha256=STQtbmF3yI97GM4yH_V--mrGe1JqldUJJc5LO1o4NWo,3919
|
|
280
284
|
phoenix/trace/dsl/query.py,sha256=Mjk2ntKUmRZCCscpt0dMrzo26NhhwtdhC_s9itR3Ycc,30404
|
|
281
285
|
phoenix/trace/langchain/__init__.py,sha256=F37GfD1pd5Kuw7R7iRUM1zXXpO8xEcycNZh5dwqBXNk,109
|
|
282
|
-
phoenix/trace/langchain/instrumentor.py,sha256=
|
|
286
|
+
phoenix/trace/langchain/instrumentor.py,sha256=a0NuyWqRCiAJNZyE_ymq5WF00I6VZVluuYnga4bdzuI,1371
|
|
283
287
|
phoenix/trace/llama_index/__init__.py,sha256=4fpR5702Qh2t5TaXIx584EkA-BveCPftXPOKvI0Oi3I,105
|
|
284
|
-
phoenix/trace/llama_index/callback.py,sha256=
|
|
288
|
+
phoenix/trace/llama_index/callback.py,sha256=ROGgpbkXDc54Yr2S28WqoZoH4rJrUDsPTdEsP0F7AB4,4451
|
|
285
289
|
phoenix/trace/openai/__init__.py,sha256=J3G0uqCxGdksUpaQVHds_Egv2drvh8UEqoLjiQAOveg,79
|
|
286
|
-
phoenix/trace/openai/instrumentor.py,sha256=
|
|
290
|
+
phoenix/trace/openai/instrumentor.py,sha256=sb3434Npe86VHsT_jyDHlfpXWZYER9H1k_IQ5-CFTvI,1270
|
|
287
291
|
phoenix/trace/v1/__init__.py,sha256=-IbAD0ruESMjvQLvGAg9CTfjBUATFDx1OXseDPis6-0,88
|
|
288
292
|
phoenix/trace/v1/evaluation_pb2.py,sha256=8sXvv2BW_vqD30MOMbmkeE2zpmm7ncik21kl3e-HzeQ,2254
|
|
289
293
|
phoenix/trace/v1/evaluation_pb2.pyi,sha256=cCbbx06gwQmaH14s3J1X25TtaARh-k1abbxQdQCXGm8,4500
|
|
@@ -292,12 +296,12 @@ phoenix/utilities/client.py,sha256=6Swxe4TVA481eKnmkCox83WY52b2nA-DWIzkkGu6wwo,4
|
|
|
292
296
|
phoenix/utilities/deprecation.py,sha256=cFuTVvjSYyRlrdxdJewjJVieIEHPk30BukSRGRydQ3k,1046
|
|
293
297
|
phoenix/utilities/error_handling.py,sha256=7b5rpGFj9EWZ8yrZK1IHvxB89suWk3lggDayUQcvZds,1946
|
|
294
298
|
phoenix/utilities/json.py,sha256=y_w-McDfvlTeGJT28sCtyjzVkwFicakxERG-sGRc8Ak,1948
|
|
295
|
-
phoenix/utilities/logging.py,sha256=
|
|
299
|
+
phoenix/utilities/logging.py,sha256=B8t2WPULOwVyuGLRLbwKsw5N41N26vtgF-lCAYgWTEk,508
|
|
296
300
|
phoenix/utilities/project.py,sha256=8IJuMM4yUMoooPi37sictGj8Etu9rGmq6RFtc9848cQ,436
|
|
297
|
-
phoenix/utilities/re.py,sha256=
|
|
301
|
+
phoenix/utilities/re.py,sha256=nr_B0txj_7CXc45953X6vr2KCRSWMuaXJSEkL8s8Sjc,2036
|
|
298
302
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
299
|
-
arize_phoenix-4.
|
|
300
|
-
arize_phoenix-4.
|
|
301
|
-
arize_phoenix-4.
|
|
302
|
-
arize_phoenix-4.
|
|
303
|
-
arize_phoenix-4.
|
|
303
|
+
arize_phoenix-4.36.0.dist-info/METADATA,sha256=NSFTsweJUI7kA6Z4eGG2Sz5qN-WmPKbTL2JHESzC79A,12003
|
|
304
|
+
arize_phoenix-4.36.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
305
|
+
arize_phoenix-4.36.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
306
|
+
arize_phoenix-4.36.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
307
|
+
arize_phoenix-4.36.0.dist-info/RECORD,,
|
phoenix/config.py
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import os
|
|
2
3
|
import re
|
|
3
4
|
import tempfile
|
|
4
|
-
from
|
|
5
|
+
from enum import Enum
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Dict, List, Optional, Tuple
|
|
7
8
|
|
|
9
|
+
from phoenix.utilities.logging import log_a_list
|
|
10
|
+
|
|
8
11
|
from .utilities.re import parse_env_headers
|
|
9
12
|
|
|
10
|
-
logger = getLogger(__name__)
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
11
14
|
|
|
12
15
|
# Phoenix environment variables
|
|
13
16
|
ENV_PHOENIX_PORT = "PHOENIX_PORT"
|
|
@@ -56,6 +59,24 @@ ENV_PHOENIX_ENABLE_PROMETHEUS = "PHOENIX_ENABLE_PROMETHEUS"
|
|
|
56
59
|
"""
|
|
57
60
|
Whether to enable Prometheus. Defaults to false.
|
|
58
61
|
"""
|
|
62
|
+
ENV_LOGGING_MODE = "PHOENIX_LOGGING_MODE"
|
|
63
|
+
"""
|
|
64
|
+
The logging mode (either 'default' or 'structured').
|
|
65
|
+
"""
|
|
66
|
+
ENV_LOGGING_LEVEL = "PHOENIX_LOGGING_LEVEL"
|
|
67
|
+
"""
|
|
68
|
+
The logging level ('debug', 'info', 'warning', 'error', 'critical') for the Phoenix backend. For
|
|
69
|
+
database logging see ENV_DB_LOGGING_LEVEL. Defaults to info.
|
|
70
|
+
"""
|
|
71
|
+
ENV_DB_LOGGING_LEVEL = "PHOENIX_DB_LOGGING_LEVEL"
|
|
72
|
+
"""
|
|
73
|
+
The logging level ('debug', 'info', 'warning', 'error', 'critical') for the Phoenix ORM.
|
|
74
|
+
Defaults to warning.
|
|
75
|
+
"""
|
|
76
|
+
ENV_LOG_MIGRATIONS = "PHOENIX_LOG_MIGRATIONS"
|
|
77
|
+
"""
|
|
78
|
+
Whether or not to log migrations. Defaults to true.
|
|
79
|
+
"""
|
|
59
80
|
|
|
60
81
|
# Phoenix server OpenTelemetry instrumentation environment variables
|
|
61
82
|
ENV_PHOENIX_SERVER_INSTRUMENTATION_OTLP_TRACE_COLLECTOR_HTTP_ENDPOINT = (
|
|
@@ -331,5 +352,74 @@ def get_web_base_url() -> str:
|
|
|
331
352
|
return get_base_url()
|
|
332
353
|
|
|
333
354
|
|
|
355
|
+
class LoggingMode(Enum):
|
|
356
|
+
DEFAULT = "default"
|
|
357
|
+
STRUCTURED = "structured"
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def get_env_logging_mode() -> LoggingMode:
|
|
361
|
+
if (logging_mode := os.getenv(ENV_LOGGING_MODE)) is None:
|
|
362
|
+
return LoggingMode.DEFAULT
|
|
363
|
+
try:
|
|
364
|
+
return LoggingMode(logging_mode.lower().strip())
|
|
365
|
+
except ValueError:
|
|
366
|
+
raise ValueError(
|
|
367
|
+
f"Invalid value `{logging_mode}` for env var `{ENV_LOGGING_MODE}`. "
|
|
368
|
+
f"Valid values are: {log_a_list([mode.value for mode in LoggingMode],'and')} "
|
|
369
|
+
"(case-insensitive)."
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def get_env_logging_level() -> int:
|
|
374
|
+
return _get_logging_level(
|
|
375
|
+
env_var=ENV_LOGGING_LEVEL,
|
|
376
|
+
default_level=logging.INFO,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def get_env_db_logging_level() -> int:
|
|
381
|
+
return _get_logging_level(
|
|
382
|
+
env_var=ENV_DB_LOGGING_LEVEL,
|
|
383
|
+
default_level=logging.WARNING,
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _get_logging_level(env_var: str, default_level: int) -> int:
|
|
388
|
+
logging_level = os.getenv(env_var)
|
|
389
|
+
if not logging_level:
|
|
390
|
+
return default_level
|
|
391
|
+
|
|
392
|
+
# levelNamesMapping = logging.getLevelNamesMapping() is not supported in python 3.8
|
|
393
|
+
# but is supported in 3.12. Hence, we define the mapping ourselves and will remove
|
|
394
|
+
# this once we drop support for older python versions
|
|
395
|
+
levelNamesMapping = logging._nameToLevel.copy()
|
|
396
|
+
|
|
397
|
+
valid_values = [level for level in levelNamesMapping if level != "NOTSET"]
|
|
398
|
+
|
|
399
|
+
if logging_level.upper() not in valid_values:
|
|
400
|
+
raise ValueError(
|
|
401
|
+
f"Invalid value `{logging_level}` for env var `{env_var}`. "
|
|
402
|
+
f"Valid values are: {log_a_list(valid_values,'and')} (case-insensitive)."
|
|
403
|
+
)
|
|
404
|
+
return levelNamesMapping[logging_level.upper()]
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def get_env_log_migrations() -> bool:
|
|
408
|
+
log_migrations = os.getenv(ENV_LOG_MIGRATIONS)
|
|
409
|
+
# Default to True
|
|
410
|
+
if log_migrations is None:
|
|
411
|
+
return True
|
|
412
|
+
|
|
413
|
+
if log_migrations.lower() == "true":
|
|
414
|
+
return True
|
|
415
|
+
elif log_migrations.lower() == "false":
|
|
416
|
+
return False
|
|
417
|
+
else:
|
|
418
|
+
raise ValueError(
|
|
419
|
+
f"Invalid value for environment variable {ENV_LOG_MIGRATIONS}: "
|
|
420
|
+
f"{log_migrations}. Value values are 'TRUE' and 'FALSE' (case-insensitive)."
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
|
|
334
424
|
DEFAULT_PROJECT_NAME = "default"
|
|
335
425
|
_KUBERNETES_PHOENIX_PORT_PATTERN = re.compile(r"^tcp://\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}:\d+$")
|
phoenix/db/alembic.ini
CHANGED
|
@@ -83,37 +83,3 @@ version_path_separator = os # Use os.pathsep. Default configuration used for ne
|
|
|
83
83
|
# ruff.executable = %(here)s/.venv/bin/ruff
|
|
84
84
|
# ruff.options = --fix REVISION_SCRIPT_FILENAME
|
|
85
85
|
|
|
86
|
-
# Logging configuration
|
|
87
|
-
[loggers]
|
|
88
|
-
keys = root,sqlalchemy,alembic
|
|
89
|
-
|
|
90
|
-
[handlers]
|
|
91
|
-
keys = console
|
|
92
|
-
|
|
93
|
-
[formatters]
|
|
94
|
-
keys = generic
|
|
95
|
-
|
|
96
|
-
[logger_root]
|
|
97
|
-
level = WARN
|
|
98
|
-
handlers = console
|
|
99
|
-
qualname =
|
|
100
|
-
|
|
101
|
-
[logger_sqlalchemy]
|
|
102
|
-
level = WARN
|
|
103
|
-
handlers =
|
|
104
|
-
qualname = sqlalchemy.engine
|
|
105
|
-
|
|
106
|
-
[logger_alembic]
|
|
107
|
-
level = WARN
|
|
108
|
-
handlers =
|
|
109
|
-
qualname = alembic
|
|
110
|
-
|
|
111
|
-
[handler_console]
|
|
112
|
-
class = StreamHandler
|
|
113
|
-
args = (sys.stderr,)
|
|
114
|
-
level = NOTSET
|
|
115
|
-
formatter = generic
|
|
116
|
-
|
|
117
|
-
[formatter_generic]
|
|
118
|
-
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
119
|
-
datefmt = %H:%M:%S
|
phoenix/db/engines.py
CHANGED
|
@@ -13,7 +13,7 @@ from sqlalchemy import URL, StaticPool, event, make_url
|
|
|
13
13
|
from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
14
14
|
from typing_extensions import assert_never
|
|
15
15
|
|
|
16
|
-
from phoenix.config import get_env_database_schema
|
|
16
|
+
from phoenix.config import LoggingMode, get_env_database_schema
|
|
17
17
|
from phoenix.db.helpers import SupportedSQLDialect
|
|
18
18
|
from phoenix.db.migrate import migrate_in_thread
|
|
19
19
|
from phoenix.db.models import init_models
|
|
@@ -64,7 +64,7 @@ def get_async_db_url(connection_str: str) -> URL:
|
|
|
64
64
|
def create_engine(
|
|
65
65
|
connection_str: str,
|
|
66
66
|
migrate: bool = True,
|
|
67
|
-
|
|
67
|
+
log_to_stdout: bool = False,
|
|
68
68
|
) -> AsyncEngine:
|
|
69
69
|
"""
|
|
70
70
|
Factory to create a SQLAlchemy engine from a URL string.
|
|
@@ -74,10 +74,25 @@ def create_engine(
|
|
|
74
74
|
raise ValueError("Failed to parse database from connection string")
|
|
75
75
|
backend = SupportedSQLDialect(url.get_backend_name())
|
|
76
76
|
url = get_async_db_url(url.render_as_string(hide_password=False))
|
|
77
|
+
# If Phoenix is run as an application, we want to pass log_migrations_to_stdout=False
|
|
78
|
+
# and let the configured sqlalchemy logger handle the migration logs
|
|
79
|
+
log_migrations_to_stdout = (
|
|
80
|
+
Settings.log_migrations and Settings.logging_mode != LoggingMode.STRUCTURED
|
|
81
|
+
)
|
|
77
82
|
if backend is SupportedSQLDialect.SQLITE:
|
|
78
|
-
return aio_sqlite_engine(
|
|
83
|
+
return aio_sqlite_engine(
|
|
84
|
+
url=url,
|
|
85
|
+
migrate=migrate,
|
|
86
|
+
log_to_stdout=log_to_stdout,
|
|
87
|
+
log_migrations_to_stdout=log_migrations_to_stdout,
|
|
88
|
+
)
|
|
79
89
|
elif backend is SupportedSQLDialect.POSTGRESQL:
|
|
80
|
-
return aio_postgresql_engine(
|
|
90
|
+
return aio_postgresql_engine(
|
|
91
|
+
url=url,
|
|
92
|
+
migrate=migrate,
|
|
93
|
+
log_to_stdout=log_to_stdout,
|
|
94
|
+
log_migrations_to_stdout=log_migrations_to_stdout,
|
|
95
|
+
)
|
|
81
96
|
else:
|
|
82
97
|
assert_never(backend)
|
|
83
98
|
|
|
@@ -85,8 +100,9 @@ def create_engine(
|
|
|
85
100
|
def aio_sqlite_engine(
|
|
86
101
|
url: URL,
|
|
87
102
|
migrate: bool = True,
|
|
88
|
-
echo: bool = False,
|
|
89
103
|
shared_cache: bool = True,
|
|
104
|
+
log_to_stdout: bool = False,
|
|
105
|
+
log_migrations_to_stdout: bool = True,
|
|
90
106
|
) -> AsyncEngine:
|
|
91
107
|
database = url.database or ":memory:"
|
|
92
108
|
if database.startswith("file:"):
|
|
@@ -105,7 +121,7 @@ def aio_sqlite_engine(
|
|
|
105
121
|
|
|
106
122
|
engine = create_async_engine(
|
|
107
123
|
url=url,
|
|
108
|
-
echo=
|
|
124
|
+
echo=log_to_stdout,
|
|
109
125
|
json_serializer=_dumps,
|
|
110
126
|
async_creator=async_creator,
|
|
111
127
|
poolclass=StaticPool,
|
|
@@ -123,7 +139,7 @@ def aio_sqlite_engine(
|
|
|
123
139
|
else:
|
|
124
140
|
sync_engine = sqlalchemy.create_engine(
|
|
125
141
|
url=url.set(drivername="sqlite"),
|
|
126
|
-
echo=
|
|
142
|
+
echo=log_migrations_to_stdout,
|
|
127
143
|
json_serializer=_dumps,
|
|
128
144
|
creator=lambda: sqlean.connect(f"file:{database}", uri=True),
|
|
129
145
|
)
|
|
@@ -143,14 +159,15 @@ def set_postgresql_search_path(schema: str) -> Callable[[Connection, Any], None]
|
|
|
143
159
|
def aio_postgresql_engine(
|
|
144
160
|
url: URL,
|
|
145
161
|
migrate: bool = True,
|
|
146
|
-
|
|
162
|
+
log_to_stdout: bool = False,
|
|
163
|
+
log_migrations_to_stdout: bool = True,
|
|
147
164
|
) -> AsyncEngine:
|
|
148
|
-
engine = create_async_engine(url=url, echo=
|
|
165
|
+
engine = create_async_engine(url=url, echo=log_to_stdout, json_serializer=_dumps)
|
|
149
166
|
if not migrate:
|
|
150
167
|
return engine
|
|
151
168
|
sync_engine = sqlalchemy.create_engine(
|
|
152
169
|
url=url.set(drivername="postgresql+psycopg"),
|
|
153
|
-
echo=
|
|
170
|
+
echo=log_migrations_to_stdout,
|
|
154
171
|
json_serializer=_dumps,
|
|
155
172
|
)
|
|
156
173
|
if schema := get_env_database_schema():
|
phoenix/db/insertion/dataset.py
CHANGED
phoenix/db/insertion/types.py
CHANGED
|
@@ -29,7 +29,7 @@ from phoenix.db.insertion.helpers import insert_on_conflict
|
|
|
29
29
|
from phoenix.server.dml_event import DmlEvent
|
|
30
30
|
from phoenix.server.types import DbSessionFactory
|
|
31
31
|
|
|
32
|
-
logger = logging.getLogger(
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class Insertable(Protocol):
|
phoenix/db/migrate.py
CHANGED
|
@@ -14,7 +14,6 @@ from phoenix.exceptions import PhoenixMigrationError
|
|
|
14
14
|
from phoenix.settings import Settings
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
|
-
logger.addHandler(logging.NullHandler())
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
def printif(condition: bool, text: str) -> None:
|
|
@@ -48,8 +47,9 @@ def migrate(
|
|
|
48
47
|
alembic_cfg.set_main_option("script_location", scripts_location)
|
|
49
48
|
url = str(engine.url).replace("%", "%%")
|
|
50
49
|
alembic_cfg.set_main_option("sqlalchemy.url", url)
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
with engine.connect() as conn:
|
|
51
|
+
alembic_cfg.attributes["connection"] = conn
|
|
52
|
+
command.upgrade(alembic_cfg, "head")
|
|
53
53
|
engine.dispose()
|
|
54
54
|
printif(log_migrations, "---------------------------")
|
|
55
55
|
printif(log_migrations, "✅ Migrations complete.")
|
phoenix/db/migrations/env.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from logging.config import fileConfig
|
|
3
2
|
|
|
4
3
|
from alembic import context
|
|
5
4
|
from sqlalchemy import Connection, engine_from_config, pool
|
|
@@ -14,14 +13,8 @@ from phoenix.settings import Settings
|
|
|
14
13
|
# access to the values within the .ini file in use.
|
|
15
14
|
config = context.config
|
|
16
15
|
|
|
17
|
-
# Interpret the config file for Python logging.
|
|
18
|
-
# This line sets up loggers basically.
|
|
19
|
-
if config.config_file_name is not None:
|
|
20
|
-
fileConfig(config.config_file_name, disable_existing_loggers=False)
|
|
21
|
-
|
|
22
16
|
# add your model's MetaData object here
|
|
23
17
|
# for 'autogenerate' support
|
|
24
|
-
|
|
25
18
|
target_metadata = Base.metadata
|
|
26
19
|
|
|
27
20
|
# other values from the config, defined by the needs of env.py,
|
phoenix/inferences/fixtures.py
CHANGED
phoenix/inferences/inferences.py
CHANGED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import atexit
|
|
2
|
+
import logging
|
|
3
|
+
import logging.config
|
|
4
|
+
import logging.handlers
|
|
5
|
+
import queue
|
|
6
|
+
from sys import stderr, stdout
|
|
7
|
+
|
|
8
|
+
from typing_extensions import assert_never
|
|
9
|
+
|
|
10
|
+
from phoenix.config import LoggingMode
|
|
11
|
+
from phoenix.logging._filter import NonErrorFilter
|
|
12
|
+
from phoenix.settings import Settings
|
|
13
|
+
|
|
14
|
+
from ._formatter import PhoenixJSONFormatter
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def setup_logging() -> None:
|
|
18
|
+
"""
|
|
19
|
+
Configures logging for the specified logging mode.
|
|
20
|
+
"""
|
|
21
|
+
logging_mode = Settings.logging_mode
|
|
22
|
+
if logging_mode is LoggingMode.DEFAULT:
|
|
23
|
+
_setup_library_logging()
|
|
24
|
+
elif logging_mode is LoggingMode.STRUCTURED:
|
|
25
|
+
_setup_application_logging()
|
|
26
|
+
else:
|
|
27
|
+
assert_never(logging_mode)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _setup_library_logging() -> None:
|
|
31
|
+
"""
|
|
32
|
+
Configures logging if Phoenix is used as a library
|
|
33
|
+
"""
|
|
34
|
+
logger = logging.getLogger("phoenix")
|
|
35
|
+
logger.setLevel(Settings.logging_level)
|
|
36
|
+
db_logger = logging.getLogger("sqlalchemy")
|
|
37
|
+
db_logger.setLevel(Settings.db_logging_level)
|
|
38
|
+
logger.info("Default logging ready")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _setup_application_logging() -> None:
|
|
42
|
+
"""
|
|
43
|
+
Configures logging if Phoenix is used as an application
|
|
44
|
+
"""
|
|
45
|
+
sql_engine_logger = logging.getLogger("sqlalchemy.engine.Engine")
|
|
46
|
+
# Remove all existing handlers
|
|
47
|
+
for handler in sql_engine_logger.handlers[:]:
|
|
48
|
+
sql_engine_logger.removeHandler(handler)
|
|
49
|
+
handler.close()
|
|
50
|
+
|
|
51
|
+
phoenix_logger = logging.getLogger("phoenix")
|
|
52
|
+
phoenix_logger.setLevel(Settings.logging_level)
|
|
53
|
+
phoenix_logger.propagate = False # Do not pass records to the root logger
|
|
54
|
+
sql_logger = logging.getLogger("sqlalchemy")
|
|
55
|
+
sql_logger.setLevel(Settings.db_logging_level)
|
|
56
|
+
sql_logger.propagate = False # Do not pass records to the root logger
|
|
57
|
+
|
|
58
|
+
log_queue = queue.Queue() # type:ignore
|
|
59
|
+
queue_handler = logging.handlers.QueueHandler(log_queue)
|
|
60
|
+
phoenix_logger.addHandler(queue_handler)
|
|
61
|
+
sql_logger.addHandler(queue_handler)
|
|
62
|
+
|
|
63
|
+
fmt_keys = {
|
|
64
|
+
"level": "levelname",
|
|
65
|
+
"message": "message",
|
|
66
|
+
"timestamp": "timestamp",
|
|
67
|
+
"logger": "name",
|
|
68
|
+
"module": "module",
|
|
69
|
+
"function": "funcName",
|
|
70
|
+
"line": "lineno",
|
|
71
|
+
"thread_name": "threadName",
|
|
72
|
+
}
|
|
73
|
+
formatter = PhoenixJSONFormatter(fmt_keys=fmt_keys)
|
|
74
|
+
|
|
75
|
+
# stdout handler
|
|
76
|
+
stdout_handler = logging.StreamHandler(stdout)
|
|
77
|
+
stdout_handler.setFormatter(formatter)
|
|
78
|
+
stdout_handler.setLevel(Settings.logging_level)
|
|
79
|
+
stdout_handler.addFilter(NonErrorFilter())
|
|
80
|
+
|
|
81
|
+
# stderr handler
|
|
82
|
+
stderr_handler = logging.StreamHandler(stderr)
|
|
83
|
+
stderr_handler.setFormatter(formatter)
|
|
84
|
+
stderr_handler.setLevel(logging.WARNING)
|
|
85
|
+
|
|
86
|
+
queue_listener = logging.handlers.QueueListener(log_queue, stdout_handler, stderr_handler)
|
|
87
|
+
if queue_listener is not None:
|
|
88
|
+
queue_listener.start()
|
|
89
|
+
atexit.register(queue_listener.stop)
|
|
90
|
+
phoenix_logger.info("Structured logging ready")
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Dict, Optional
|
|
5
|
+
|
|
6
|
+
LOG_RECORD_BUILTIN_ATTRS = {
|
|
7
|
+
"args",
|
|
8
|
+
"asctime",
|
|
9
|
+
"created",
|
|
10
|
+
"exc_info",
|
|
11
|
+
"exc_text",
|
|
12
|
+
"filename",
|
|
13
|
+
"funcName",
|
|
14
|
+
"levelname",
|
|
15
|
+
"levelno",
|
|
16
|
+
"lineno",
|
|
17
|
+
"module",
|
|
18
|
+
"msecs",
|
|
19
|
+
"message",
|
|
20
|
+
"msg",
|
|
21
|
+
"name",
|
|
22
|
+
"pathname",
|
|
23
|
+
"process",
|
|
24
|
+
"processName",
|
|
25
|
+
"relativeCreated",
|
|
26
|
+
"stack_info",
|
|
27
|
+
"thread",
|
|
28
|
+
"threadName",
|
|
29
|
+
"taskName",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class PhoenixJSONFormatter(logging.Formatter):
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
*,
|
|
37
|
+
fmt_keys: Optional[Dict[str, str]] = None,
|
|
38
|
+
):
|
|
39
|
+
super().__init__()
|
|
40
|
+
self.fmt_keys = fmt_keys if fmt_keys is not None else {}
|
|
41
|
+
|
|
42
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
43
|
+
message = self._prepare_log_dict(record)
|
|
44
|
+
return json.dumps(message, default=str)
|
|
45
|
+
|
|
46
|
+
def _prepare_log_dict(self, record: logging.LogRecord) -> Dict[str, str]:
|
|
47
|
+
always_fields = {
|
|
48
|
+
"message": record.getMessage(),
|
|
49
|
+
"timestamp": dt.datetime.fromtimestamp(record.created, tz=dt.timezone.utc).isoformat(),
|
|
50
|
+
}
|
|
51
|
+
if record.exc_info is not None:
|
|
52
|
+
always_fields["exc_info"] = self.formatException(record.exc_info)
|
|
53
|
+
|
|
54
|
+
if record.stack_info is not None:
|
|
55
|
+
always_fields["stack_info"] = self.formatStack(record.stack_info)
|
|
56
|
+
|
|
57
|
+
message = {
|
|
58
|
+
key: msg_val
|
|
59
|
+
if (msg_val := always_fields.pop(val, None)) is not None
|
|
60
|
+
else getattr(record, val)
|
|
61
|
+
for key, val in self.fmt_keys.items()
|
|
62
|
+
}
|
|
63
|
+
message.update(always_fields)
|
|
64
|
+
|
|
65
|
+
for key, val in record.__dict__.items():
|
|
66
|
+
if key not in LOG_RECORD_BUILTIN_ATTRS:
|
|
67
|
+
message[key] = val
|
|
68
|
+
|
|
69
|
+
return message
|
phoenix/metrics/__init__.py
CHANGED
phoenix/otel/settings.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import os
|
|
2
3
|
import urllib
|
|
3
|
-
from logging import getLogger
|
|
4
4
|
from re import compile
|
|
5
5
|
from typing import Dict, List, Optional
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
8
|
|
|
9
9
|
# Environment variables specific to the subpackage
|
|
10
10
|
ENV_PHOENIX_COLLECTOR_ENDPOINT = "PHOENIX_COLLECTOR_ENDPOINT"
|
|
@@ -72,13 +72,13 @@ def parse_env_headers(s: str) -> Dict[str, str]:
|
|
|
72
72
|
encoded_header = f"{urllib.parse.quote(name)}={urllib.parse.quote(value)}"
|
|
73
73
|
match = _HEADER_PATTERN.fullmatch(encoded_header.strip())
|
|
74
74
|
if not match:
|
|
75
|
-
|
|
75
|
+
logger.warning(
|
|
76
76
|
"Header format invalid! Header values in environment variables must be "
|
|
77
77
|
"URL encoded: %s",
|
|
78
78
|
f"{name}: ****",
|
|
79
79
|
)
|
|
80
80
|
continue
|
|
81
|
-
|
|
81
|
+
logger.warning(
|
|
82
82
|
"Header values in environment variables should be URL encoded, attempting to "
|
|
83
83
|
"URL encode header: {name}: ****"
|
|
84
84
|
)
|
phoenix/server/app.py
CHANGED
|
@@ -118,8 +118,6 @@ if TYPE_CHECKING:
|
|
|
118
118
|
from opentelemetry.trace import TracerProvider
|
|
119
119
|
|
|
120
120
|
logger = logging.getLogger(__name__)
|
|
121
|
-
logger.setLevel(logging.INFO)
|
|
122
|
-
logger.addHandler(logging.NullHandler())
|
|
123
121
|
|
|
124
122
|
router = APIRouter(include_in_schema=False)
|
|
125
123
|
|
|
@@ -542,7 +540,7 @@ def create_engine_and_run_migrations(
|
|
|
542
540
|
database_url: str,
|
|
543
541
|
) -> AsyncEngine:
|
|
544
542
|
try:
|
|
545
|
-
return create_engine(database_url)
|
|
543
|
+
return create_engine(connection_str=database_url, migrate=True, log_to_stdout=False)
|
|
546
544
|
except PhoenixMigrationError as e:
|
|
547
545
|
msg = (
|
|
548
546
|
"\n\n⚠️⚠️ Phoenix failed to migrate the database to the latest version. ⚠️⚠️\n\n"
|
|
@@ -604,6 +602,7 @@ def create_app(
|
|
|
604
602
|
secret: Optional[str] = None,
|
|
605
603
|
scaffolder_config: Optional[ScaffolderConfig] = None,
|
|
606
604
|
) -> FastAPI:
|
|
605
|
+
logger.info(f"Server umap params: {umap_params}")
|
|
607
606
|
startup_callbacks_list: List[_Callback] = list(startup_callbacks)
|
|
608
607
|
shutdown_callbacks_list: List[_Callback] = list(shutdown_callbacks)
|
|
609
608
|
initial_batch_of_spans: Iterable[Tuple[Span, str]] = (
|
phoenix/server/main.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import atexit
|
|
2
2
|
import codecs
|
|
3
|
-
import logging
|
|
4
3
|
import os
|
|
5
4
|
import sys
|
|
6
5
|
from argparse import ArgumentParser
|
|
@@ -20,18 +19,22 @@ from phoenix.config import (
|
|
|
20
19
|
get_auth_settings,
|
|
21
20
|
get_env_database_connection_str,
|
|
22
21
|
get_env_database_schema,
|
|
22
|
+
get_env_db_logging_level,
|
|
23
23
|
get_env_enable_prometheus,
|
|
24
24
|
get_env_grpc_port,
|
|
25
25
|
get_env_host,
|
|
26
26
|
get_env_host_root_path,
|
|
27
|
+
get_env_log_migrations,
|
|
28
|
+
get_env_logging_level,
|
|
29
|
+
get_env_logging_mode,
|
|
27
30
|
get_env_port,
|
|
28
31
|
get_pids_path,
|
|
29
|
-
get_working_dir,
|
|
30
32
|
)
|
|
31
33
|
from phoenix.core.model_schema_adapter import create_model_from_inferences
|
|
32
34
|
from phoenix.db import get_printable_db_url
|
|
33
35
|
from phoenix.inferences.fixtures import FIXTURES, get_inferences
|
|
34
36
|
from phoenix.inferences.inferences import EMPTY_INFERENCES, Inferences
|
|
37
|
+
from phoenix.logging import setup_logging
|
|
35
38
|
from phoenix.pointcloud.umap_parameters import (
|
|
36
39
|
DEFAULT_MIN_DIST,
|
|
37
40
|
DEFAULT_N_NEIGHBORS,
|
|
@@ -59,9 +62,6 @@ from phoenix.trace.fixtures import (
|
|
|
59
62
|
from phoenix.trace.otel import decode_otlp_span, encode_span_to_otlp
|
|
60
63
|
from phoenix.trace.schemas import Span
|
|
61
64
|
|
|
62
|
-
logger = logging.getLogger(__name__)
|
|
63
|
-
logger.addHandler(logging.NullHandler())
|
|
64
|
-
|
|
65
65
|
_WELCOME_MESSAGE = Environment(loader=BaseLoader()).from_string("""
|
|
66
66
|
|
|
67
67
|
██████╗ ██╗ ██╗ ██████╗ ███████╗███╗ ██╗██╗██╗ ██╗
|
|
@@ -121,19 +121,16 @@ def _get_pid_file() -> Path:
|
|
|
121
121
|
|
|
122
122
|
DEFAULT_UMAP_PARAMS_STR = f"{DEFAULT_MIN_DIST},{DEFAULT_N_NEIGHBORS},{DEFAULT_N_SAMPLES}"
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
|
|
125
|
+
def main() -> None:
|
|
125
126
|
primary_inferences_name: str
|
|
126
127
|
reference_inferences_name: Optional[str]
|
|
127
128
|
trace_dataset_name: Optional[str] = None
|
|
128
|
-
simulate_streaming: Optional[bool] = None
|
|
129
129
|
|
|
130
130
|
primary_inferences: Inferences = EMPTY_INFERENCES
|
|
131
131
|
reference_inferences: Optional[Inferences] = None
|
|
132
132
|
corpus_inferences: Optional[Inferences] = None
|
|
133
133
|
|
|
134
|
-
# Initialize the settings for the Server
|
|
135
|
-
Settings.log_migrations = True
|
|
136
|
-
|
|
137
134
|
# automatically remove the pid file when the process is being gracefully terminated
|
|
138
135
|
atexit.register(_remove_pid_file)
|
|
139
136
|
|
|
@@ -230,7 +227,7 @@ if __name__ == "__main__":
|
|
|
230
227
|
db_connection_str = (
|
|
231
228
|
args.database_url if args.database_url else get_env_database_connection_str()
|
|
232
229
|
)
|
|
233
|
-
export_path = Path(args.export_path) if args.export_path else EXPORT_DIR
|
|
230
|
+
export_path = Path(args.export_path) if args.export_path else Path(EXPORT_DIR)
|
|
234
231
|
|
|
235
232
|
force_fixture_ingestion = False
|
|
236
233
|
scaffold_datasets = False
|
|
@@ -260,7 +257,6 @@ if __name__ == "__main__":
|
|
|
260
257
|
reference_inferences = None
|
|
261
258
|
elif args.command == "trace-fixture":
|
|
262
259
|
trace_dataset_name = args.fixture
|
|
263
|
-
simulate_streaming = args.simulate_streaming
|
|
264
260
|
elif args.command == "demo":
|
|
265
261
|
fixture_name = args.fixture
|
|
266
262
|
primary_inferences, reference_inferences, corpus_inferences = get_inferences(
|
|
@@ -268,7 +264,6 @@ if __name__ == "__main__":
|
|
|
268
264
|
args.no_internet,
|
|
269
265
|
)
|
|
270
266
|
trace_dataset_name = args.trace_fixture
|
|
271
|
-
simulate_streaming = args.simulate_streaming
|
|
272
267
|
elif args.command == "serve":
|
|
273
268
|
# We use sets to avoid duplicates
|
|
274
269
|
if args.with_fixture:
|
|
@@ -290,12 +285,6 @@ if __name__ == "__main__":
|
|
|
290
285
|
force_fixture_ingestion = args.force_fixture_ingestion
|
|
291
286
|
scaffold_datasets = args.scaffold_datasets
|
|
292
287
|
host: Optional[str] = args.host or get_env_host()
|
|
293
|
-
display_host = host or "localhost"
|
|
294
|
-
# If the host is "::", the convention is to bind to all interfaces. However, uvicorn
|
|
295
|
-
# does not support this directly unless the host is set to None.
|
|
296
|
-
if host and ":" in host:
|
|
297
|
-
# format IPv6 hosts in brackets
|
|
298
|
-
display_host = f"[{host}]"
|
|
299
288
|
if host == "::":
|
|
300
289
|
# TODO(dustin): why is this necessary? it's not type compliant
|
|
301
290
|
host = None
|
|
@@ -336,13 +325,11 @@ if __name__ == "__main__":
|
|
|
336
325
|
n_samples=int(umap_params_list[2]),
|
|
337
326
|
)
|
|
338
327
|
|
|
339
|
-
logger.info(f"Server umap params: {umap_params}")
|
|
340
328
|
if enable_prometheus := get_env_enable_prometheus():
|
|
341
329
|
from phoenix.server.prometheus import start_prometheus
|
|
342
330
|
|
|
343
331
|
start_prometheus()
|
|
344
332
|
|
|
345
|
-
working_dir = get_working_dir().resolve()
|
|
346
333
|
engine = create_engine_and_run_migrations(db_connection_str)
|
|
347
334
|
instrumentation_cleanups = instrument_engine_if_enabled(engine)
|
|
348
335
|
factory = DbSessionFactory(db=_db(engine), dialect=engine.dialect.name)
|
|
@@ -394,3 +381,16 @@ if __name__ == "__main__":
|
|
|
394
381
|
|
|
395
382
|
# Start the server
|
|
396
383
|
server.run()
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def initialize_settings() -> None:
|
|
387
|
+
Settings.logging_mode = get_env_logging_mode()
|
|
388
|
+
Settings.logging_level = get_env_logging_level()
|
|
389
|
+
Settings.db_logging_level = get_env_db_logging_level()
|
|
390
|
+
Settings.log_migrations = get_env_log_migrations()
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
if __name__ == "__main__":
|
|
394
|
+
initialize_settings()
|
|
395
|
+
setup_logging()
|
|
396
|
+
main()
|
phoenix/server/telemetry.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import os
|
|
2
3
|
from typing import TYPE_CHECKING
|
|
3
4
|
|
|
@@ -8,9 +9,8 @@ from phoenix.config import (
|
|
|
8
9
|
|
|
9
10
|
if TYPE_CHECKING:
|
|
10
11
|
from opentelemetry.trace import TracerProvider
|
|
11
|
-
from logging import getLogger
|
|
12
12
|
|
|
13
|
-
logger = getLogger(__name__)
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def normalize_http_collector_endpoint(endpoint: str) -> str:
|
phoenix/services.py
CHANGED
phoenix/session/client.py
CHANGED
phoenix/session/evaluation.py
CHANGED
phoenix/session/session.py
CHANGED
phoenix/settings.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from dataclasses import dataclass, field
|
|
2
3
|
|
|
4
|
+
from phoenix.config import LoggingMode
|
|
5
|
+
|
|
3
6
|
|
|
4
7
|
@dataclass
|
|
5
8
|
class _Settings:
|
|
@@ -7,6 +10,12 @@ class _Settings:
|
|
|
7
10
|
|
|
8
11
|
# By default, don't log migrations
|
|
9
12
|
log_migrations: bool = field(default=False)
|
|
13
|
+
# By default, Phoenix does not configure its loggers and acts as a library
|
|
14
|
+
logging_mode: LoggingMode = field(default=LoggingMode.DEFAULT)
|
|
15
|
+
# By default, log level is INFO
|
|
16
|
+
logging_level: int = field(default=logging.INFO)
|
|
17
|
+
# By default, log level is WARNING
|
|
18
|
+
db_logging_level: int = field(default=logging.WARNING)
|
|
10
19
|
|
|
11
20
|
|
|
12
21
|
# Singleton instance of the settings
|
phoenix/trace/exporter.py
CHANGED
phoenix/trace/fixtures.py
CHANGED
|
@@ -13,7 +13,6 @@ from phoenix.trace.errors import IncompatibleLibraryVersionError
|
|
|
13
13
|
from phoenix.trace.exporter import _OpenInferenceExporter
|
|
14
14
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
|
-
logger.addHandler(logging.NullHandler())
|
|
17
16
|
|
|
18
17
|
LLAMA_INDEX_MODERN_VERSION = (0, 10, 0)
|
|
19
18
|
INSTRUMENTATION_MODERN_VERSION = (1, 0, 0)
|
phoenix/utilities/logging.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# A collection of printing and logging utilities
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any, List
|
|
4
4
|
|
|
5
5
|
from tqdm.auto import tqdm
|
|
6
6
|
|
|
@@ -8,3 +8,11 @@ from tqdm.auto import tqdm
|
|
|
8
8
|
def printif(condition: bool, *args: Any, **kwargs: Any) -> None:
|
|
9
9
|
if condition:
|
|
10
10
|
tqdm.write(*args, **kwargs)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def log_a_list(list_of_str: List[str], join_word: str) -> str:
|
|
14
|
+
if list_of_str is None or len(list_of_str) == 0:
|
|
15
|
+
return ""
|
|
16
|
+
if len(list_of_str) == 1:
|
|
17
|
+
return list_of_str[0]
|
|
18
|
+
return f"{', '.join(map(str, list_of_str[:-1]))} {join_word} {list_of_str[-1]}"
|
phoenix/utilities/re.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import logging
|
|
2
2
|
from re import compile, split
|
|
3
3
|
from typing import Dict, List
|
|
4
4
|
from urllib.parse import unquote
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
7
|
|
|
8
8
|
# Optional whitespace
|
|
9
9
|
_OWS = r"[ \t]*"
|
|
@@ -35,7 +35,7 @@ def parse_env_headers(s: str) -> Dict[str, str]:
|
|
|
35
35
|
continue
|
|
36
36
|
match = _HEADER_PATTERN.fullmatch(header.strip())
|
|
37
37
|
if not match:
|
|
38
|
-
|
|
38
|
+
logger.warning(
|
|
39
39
|
"Header format invalid! Header values in environment variables must be "
|
|
40
40
|
"URL encoded: %s",
|
|
41
41
|
header,
|
phoenix/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "4.
|
|
1
|
+
__version__ = "4.36.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|