mlrun 1.7.0rc4__py3-none-any.whl → 1.7.2__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 mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +11 -1
- mlrun/__main__.py +39 -121
- mlrun/{datastore/helpers.py → alerts/__init__.py} +2 -5
- mlrun/alerts/alert.py +248 -0
- mlrun/api/schemas/__init__.py +4 -3
- mlrun/artifacts/__init__.py +8 -3
- mlrun/artifacts/base.py +39 -254
- mlrun/artifacts/dataset.py +9 -190
- mlrun/artifacts/manager.py +73 -46
- mlrun/artifacts/model.py +30 -158
- mlrun/artifacts/plots.py +23 -380
- mlrun/common/constants.py +73 -1
- mlrun/common/db/sql_session.py +3 -2
- mlrun/common/formatters/__init__.py +21 -0
- mlrun/common/formatters/artifact.py +46 -0
- mlrun/common/formatters/base.py +113 -0
- mlrun/common/formatters/feature_set.py +44 -0
- mlrun/common/formatters/function.py +46 -0
- mlrun/common/formatters/pipeline.py +53 -0
- mlrun/common/formatters/project.py +51 -0
- mlrun/common/formatters/run.py +29 -0
- mlrun/common/helpers.py +11 -1
- mlrun/{runtimes → common/runtimes}/constants.py +32 -4
- mlrun/common/schemas/__init__.py +31 -4
- mlrun/common/schemas/alert.py +202 -0
- mlrun/common/schemas/api_gateway.py +196 -0
- mlrun/common/schemas/artifact.py +28 -1
- mlrun/common/schemas/auth.py +13 -2
- mlrun/common/schemas/client_spec.py +2 -1
- mlrun/common/schemas/common.py +7 -4
- mlrun/common/schemas/constants.py +3 -0
- mlrun/common/schemas/feature_store.py +58 -28
- mlrun/common/schemas/frontend_spec.py +8 -0
- mlrun/common/schemas/function.py +11 -0
- mlrun/common/schemas/hub.py +7 -9
- mlrun/common/schemas/model_monitoring/__init__.py +21 -4
- mlrun/common/schemas/model_monitoring/constants.py +136 -42
- mlrun/common/schemas/model_monitoring/grafana.py +9 -5
- mlrun/common/schemas/model_monitoring/model_endpoints.py +89 -41
- mlrun/common/schemas/notification.py +69 -12
- mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
- mlrun/common/schemas/pipeline.py +7 -0
- mlrun/common/schemas/project.py +67 -16
- mlrun/common/schemas/runs.py +17 -0
- mlrun/common/schemas/schedule.py +1 -1
- mlrun/common/schemas/workflow.py +10 -2
- mlrun/common/types.py +14 -1
- mlrun/config.py +233 -58
- mlrun/data_types/data_types.py +11 -1
- mlrun/data_types/spark.py +5 -4
- mlrun/data_types/to_pandas.py +75 -34
- mlrun/datastore/__init__.py +8 -10
- mlrun/datastore/alibaba_oss.py +131 -0
- mlrun/datastore/azure_blob.py +131 -43
- mlrun/datastore/base.py +107 -47
- mlrun/datastore/datastore.py +17 -7
- mlrun/datastore/datastore_profile.py +91 -7
- mlrun/datastore/dbfs_store.py +3 -7
- mlrun/datastore/filestore.py +1 -3
- mlrun/datastore/google_cloud_storage.py +92 -32
- mlrun/datastore/hdfs.py +5 -0
- mlrun/datastore/inmem.py +6 -3
- mlrun/datastore/redis.py +3 -2
- mlrun/datastore/s3.py +30 -12
- mlrun/datastore/snowflake_utils.py +45 -0
- mlrun/datastore/sources.py +274 -59
- mlrun/datastore/spark_utils.py +30 -0
- mlrun/datastore/store_resources.py +9 -7
- mlrun/datastore/storeytargets.py +151 -0
- mlrun/datastore/targets.py +387 -119
- mlrun/datastore/utils.py +68 -5
- mlrun/datastore/v3io.py +28 -50
- mlrun/db/auth_utils.py +152 -0
- mlrun/db/base.py +245 -20
- mlrun/db/factory.py +1 -4
- mlrun/db/httpdb.py +909 -231
- mlrun/db/nopdb.py +279 -14
- mlrun/errors.py +35 -5
- mlrun/execution.py +111 -38
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +46 -53
- mlrun/feature_store/common.py +6 -11
- mlrun/feature_store/feature_set.py +48 -23
- mlrun/feature_store/feature_vector.py +13 -2
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/base.py +9 -4
- mlrun/feature_store/retrieval/dask_merger.py +2 -0
- mlrun/feature_store/retrieval/job.py +13 -4
- mlrun/feature_store/retrieval/local_merger.py +2 -0
- mlrun/feature_store/retrieval/spark_merger.py +24 -32
- mlrun/feature_store/steps.py +38 -19
- mlrun/features.py +6 -14
- mlrun/frameworks/_common/plan.py +3 -3
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +4 -4
- mlrun/frameworks/pytorch/__init__.py +2 -2
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
- mlrun/frameworks/tf_keras/__init__.py +5 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/k8s_utils.py +57 -12
- mlrun/launcher/__init__.py +1 -1
- mlrun/launcher/base.py +6 -5
- mlrun/launcher/client.py +13 -11
- mlrun/launcher/factory.py +1 -1
- mlrun/launcher/local.py +15 -5
- mlrun/launcher/remote.py +10 -3
- mlrun/lists.py +6 -2
- mlrun/model.py +297 -48
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +152 -357
- mlrun/model_monitoring/applications/__init__.py +10 -0
- mlrun/model_monitoring/applications/_application_steps.py +190 -0
- mlrun/model_monitoring/applications/base.py +108 -0
- mlrun/model_monitoring/applications/context.py +341 -0
- mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
- mlrun/model_monitoring/applications/histogram_data_drift.py +227 -91
- mlrun/model_monitoring/applications/results.py +99 -0
- mlrun/model_monitoring/controller.py +130 -303
- mlrun/model_monitoring/{stores/models/sqlite.py → db/__init__.py} +5 -10
- mlrun/model_monitoring/db/stores/__init__.py +136 -0
- mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
- mlrun/model_monitoring/db/stores/base/store.py +213 -0
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
- mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
- mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
- mlrun/model_monitoring/db/tsdb/base.py +448 -0
- mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
- mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +298 -0
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +522 -0
- mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
- mlrun/model_monitoring/features_drift_table.py +34 -22
- mlrun/model_monitoring/helpers.py +177 -39
- mlrun/model_monitoring/model_endpoint.py +3 -2
- mlrun/model_monitoring/stream_processing.py +165 -398
- mlrun/model_monitoring/tracking_policy.py +7 -1
- mlrun/model_monitoring/writer.py +161 -125
- mlrun/package/packagers/default_packager.py +2 -2
- mlrun/package/packagers_manager.py +1 -0
- mlrun/package/utils/_formatter.py +2 -2
- mlrun/platforms/__init__.py +11 -10
- mlrun/platforms/iguazio.py +67 -228
- mlrun/projects/__init__.py +6 -1
- mlrun/projects/operations.py +47 -20
- mlrun/projects/pipelines.py +396 -249
- mlrun/projects/project.py +1176 -406
- mlrun/render.py +28 -22
- mlrun/run.py +208 -181
- mlrun/runtimes/__init__.py +76 -11
- mlrun/runtimes/base.py +54 -24
- mlrun/runtimes/daskjob.py +9 -2
- mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
- mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
- mlrun/runtimes/funcdoc.py +1 -29
- mlrun/runtimes/kubejob.py +34 -128
- mlrun/runtimes/local.py +39 -10
- mlrun/runtimes/mpijob/__init__.py +0 -20
- mlrun/runtimes/mpijob/abstract.py +8 -8
- mlrun/runtimes/mpijob/v1.py +1 -1
- mlrun/runtimes/nuclio/__init__.py +1 -0
- mlrun/runtimes/nuclio/api_gateway.py +769 -0
- mlrun/runtimes/nuclio/application/__init__.py +15 -0
- mlrun/runtimes/nuclio/application/application.py +758 -0
- mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
- mlrun/runtimes/nuclio/function.py +188 -68
- mlrun/runtimes/nuclio/serving.py +57 -60
- mlrun/runtimes/pod.py +191 -58
- mlrun/runtimes/remotesparkjob.py +11 -8
- mlrun/runtimes/sparkjob/spark3job.py +17 -18
- mlrun/runtimes/utils.py +40 -73
- mlrun/secrets.py +6 -2
- mlrun/serving/__init__.py +8 -1
- mlrun/serving/remote.py +2 -3
- mlrun/serving/routers.py +89 -64
- mlrun/serving/server.py +54 -26
- mlrun/serving/states.py +187 -56
- mlrun/serving/utils.py +19 -11
- mlrun/serving/v2_serving.py +136 -63
- mlrun/track/tracker.py +2 -1
- mlrun/track/trackers/mlflow_tracker.py +5 -0
- mlrun/utils/async_http.py +26 -6
- mlrun/utils/db.py +18 -0
- mlrun/utils/helpers.py +375 -105
- mlrun/utils/http.py +2 -2
- mlrun/utils/logger.py +75 -9
- mlrun/utils/notifications/notification/__init__.py +14 -10
- mlrun/utils/notifications/notification/base.py +48 -0
- mlrun/utils/notifications/notification/console.py +2 -0
- mlrun/utils/notifications/notification/git.py +24 -1
- mlrun/utils/notifications/notification/ipython.py +2 -0
- mlrun/utils/notifications/notification/slack.py +96 -21
- mlrun/utils/notifications/notification/webhook.py +63 -2
- mlrun/utils/notifications/notification_pusher.py +146 -16
- mlrun/utils/regex.py +9 -0
- mlrun/utils/retryer.py +3 -2
- mlrun/utils/v3io_clients.py +2 -3
- mlrun/utils/version/version.json +2 -2
- mlrun-1.7.2.dist-info/METADATA +390 -0
- mlrun-1.7.2.dist-info/RECORD +351 -0
- {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/WHEEL +1 -1
- mlrun/feature_store/retrieval/conversion.py +0 -271
- mlrun/kfpops.py +0 -868
- mlrun/model_monitoring/application.py +0 -310
- mlrun/model_monitoring/batch.py +0 -974
- mlrun/model_monitoring/controller_handler.py +0 -37
- mlrun/model_monitoring/prometheus.py +0 -216
- mlrun/model_monitoring/stores/__init__.py +0 -111
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -574
- mlrun/model_monitoring/stores/model_endpoint_store.py +0 -145
- mlrun/model_monitoring/stores/models/__init__.py +0 -27
- mlrun/model_monitoring/stores/models/base.py +0 -84
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
- mlrun/platforms/other.py +0 -305
- mlrun-1.7.0rc4.dist-info/METADATA +0 -269
- mlrun-1.7.0rc4.dist-info/RECORD +0 -321
- {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/top_level.txt +0 -0
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
from typing import Optional
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
import pydantic
|
|
18
18
|
|
|
19
19
|
from .auth import AuthorizationResourceTypes, Credentials
|
|
20
20
|
from .object import (
|
|
@@ -27,32 +27,42 @@ from .object import (
|
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
30
|
+
class FeatureStoreBaseModel(pydantic.BaseModel):
|
|
31
|
+
"""
|
|
32
|
+
Intermediate base class, in order to override pydantic's configuration, as per
|
|
33
|
+
https://docs.pydantic.dev/1.10/usage/model_config/#change-behaviour-globally
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
class Config:
|
|
37
|
+
copy_on_model_validation = "none"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Feature(FeatureStoreBaseModel):
|
|
31
41
|
name: str
|
|
32
42
|
value_type: str
|
|
33
43
|
labels: Optional[dict] = {}
|
|
34
44
|
|
|
35
45
|
class Config:
|
|
36
|
-
extra = Extra.allow
|
|
46
|
+
extra = pydantic.Extra.allow
|
|
37
47
|
|
|
38
48
|
|
|
39
|
-
class Entity(
|
|
49
|
+
class Entity(FeatureStoreBaseModel):
|
|
40
50
|
name: str
|
|
41
51
|
value_type: str
|
|
42
52
|
labels: Optional[dict] = {}
|
|
43
53
|
|
|
44
54
|
class Config:
|
|
45
|
-
extra = Extra.allow
|
|
55
|
+
extra = pydantic.Extra.allow
|
|
46
56
|
|
|
47
57
|
|
|
48
58
|
class FeatureSetSpec(ObjectSpec):
|
|
49
59
|
entities: list[Entity] = []
|
|
50
60
|
features: list[Feature] = []
|
|
51
|
-
engine: Optional[str] = Field(default="storey")
|
|
61
|
+
engine: Optional[str] = pydantic.Field(default="storey")
|
|
52
62
|
|
|
53
63
|
|
|
54
|
-
class FeatureSet(
|
|
55
|
-
kind: ObjectKind = Field(ObjectKind.feature_set, const=True)
|
|
64
|
+
class FeatureSet(FeatureStoreBaseModel):
|
|
65
|
+
kind: ObjectKind = pydantic.Field(ObjectKind.feature_set, const=True)
|
|
56
66
|
metadata: ObjectMetadata
|
|
57
67
|
spec: FeatureSetSpec
|
|
58
68
|
status: ObjectStatus
|
|
@@ -62,7 +72,7 @@ class FeatureSet(BaseModel):
|
|
|
62
72
|
return AuthorizationResourceTypes.feature_set
|
|
63
73
|
|
|
64
74
|
|
|
65
|
-
class EntityRecord(
|
|
75
|
+
class EntityRecord(FeatureStoreBaseModel):
|
|
66
76
|
name: str
|
|
67
77
|
value_type: str
|
|
68
78
|
labels: list[LabelRecord]
|
|
@@ -71,7 +81,7 @@ class EntityRecord(BaseModel):
|
|
|
71
81
|
orm_mode = True
|
|
72
82
|
|
|
73
83
|
|
|
74
|
-
class FeatureRecord(
|
|
84
|
+
class FeatureRecord(FeatureStoreBaseModel):
|
|
75
85
|
name: str
|
|
76
86
|
value_type: str
|
|
77
87
|
labels: list[LabelRecord]
|
|
@@ -88,44 +98,64 @@ class FeatureSetRecord(ObjectRecord):
|
|
|
88
98
|
orm_mode = True
|
|
89
99
|
|
|
90
100
|
|
|
91
|
-
class FeatureSetsOutput(
|
|
101
|
+
class FeatureSetsOutput(FeatureStoreBaseModel):
|
|
92
102
|
feature_sets: list[FeatureSet]
|
|
93
103
|
|
|
94
104
|
|
|
95
|
-
class FeatureSetsTagsOutput(
|
|
105
|
+
class FeatureSetsTagsOutput(FeatureStoreBaseModel):
|
|
96
106
|
tags: list[str] = []
|
|
97
107
|
|
|
98
108
|
|
|
99
|
-
class FeatureSetDigestSpec(
|
|
109
|
+
class FeatureSetDigestSpec(FeatureStoreBaseModel):
|
|
100
110
|
entities: list[Entity]
|
|
101
111
|
features: list[Feature]
|
|
102
112
|
|
|
103
113
|
|
|
104
|
-
class FeatureSetDigestOutput(
|
|
114
|
+
class FeatureSetDigestOutput(FeatureStoreBaseModel):
|
|
105
115
|
metadata: ObjectMetadata
|
|
106
116
|
spec: FeatureSetDigestSpec
|
|
107
117
|
|
|
108
118
|
|
|
109
|
-
class
|
|
119
|
+
class FeatureSetDigestSpecV2(FeatureStoreBaseModel):
|
|
120
|
+
entities: list[Entity]
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class FeatureSetDigestOutputV2(FeatureStoreBaseModel):
|
|
124
|
+
feature_set_index: int
|
|
125
|
+
metadata: ObjectMetadata
|
|
126
|
+
spec: FeatureSetDigestSpecV2
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class FeatureListOutput(FeatureStoreBaseModel):
|
|
110
130
|
feature: Feature
|
|
111
131
|
feature_set_digest: FeatureSetDigestOutput
|
|
112
132
|
|
|
113
133
|
|
|
114
|
-
class FeaturesOutput(
|
|
134
|
+
class FeaturesOutput(FeatureStoreBaseModel):
|
|
115
135
|
features: list[FeatureListOutput]
|
|
116
136
|
|
|
117
137
|
|
|
118
|
-
class
|
|
138
|
+
class FeaturesOutputV2(FeatureStoreBaseModel):
|
|
139
|
+
features: list[Feature]
|
|
140
|
+
feature_set_digests: list[FeatureSetDigestOutputV2]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class EntityListOutput(FeatureStoreBaseModel):
|
|
119
144
|
entity: Entity
|
|
120
145
|
feature_set_digest: FeatureSetDigestOutput
|
|
121
146
|
|
|
122
147
|
|
|
123
|
-
class
|
|
148
|
+
class EntitiesOutputV2(FeatureStoreBaseModel):
|
|
149
|
+
entities: list[Entity]
|
|
150
|
+
feature_set_digests: list[FeatureSetDigestOutputV2]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class EntitiesOutput(FeatureStoreBaseModel):
|
|
124
154
|
entities: list[EntityListOutput]
|
|
125
155
|
|
|
126
156
|
|
|
127
|
-
class FeatureVector(
|
|
128
|
-
kind: ObjectKind = Field(ObjectKind.feature_vector, const=True)
|
|
157
|
+
class FeatureVector(FeatureStoreBaseModel):
|
|
158
|
+
kind: ObjectKind = pydantic.Field(ObjectKind.feature_vector, const=True)
|
|
129
159
|
metadata: ObjectMetadata
|
|
130
160
|
spec: ObjectSpec
|
|
131
161
|
status: ObjectStatus
|
|
@@ -139,39 +169,39 @@ class FeatureVectorRecord(ObjectRecord):
|
|
|
139
169
|
pass
|
|
140
170
|
|
|
141
171
|
|
|
142
|
-
class FeatureVectorsOutput(
|
|
172
|
+
class FeatureVectorsOutput(FeatureStoreBaseModel):
|
|
143
173
|
feature_vectors: list[FeatureVector]
|
|
144
174
|
|
|
145
175
|
|
|
146
|
-
class FeatureVectorsTagsOutput(
|
|
176
|
+
class FeatureVectorsTagsOutput(FeatureStoreBaseModel):
|
|
147
177
|
tags: list[str] = []
|
|
148
178
|
|
|
149
179
|
|
|
150
|
-
class DataSource(
|
|
180
|
+
class DataSource(FeatureStoreBaseModel):
|
|
151
181
|
kind: str
|
|
152
182
|
name: str
|
|
153
183
|
path: str
|
|
154
184
|
|
|
155
185
|
class Config:
|
|
156
|
-
extra = Extra.allow
|
|
186
|
+
extra = pydantic.Extra.allow
|
|
157
187
|
|
|
158
188
|
|
|
159
|
-
class DataTarget(
|
|
189
|
+
class DataTarget(FeatureStoreBaseModel):
|
|
160
190
|
kind: str
|
|
161
191
|
name: str
|
|
162
192
|
path: Optional[str]
|
|
163
193
|
|
|
164
194
|
class Config:
|
|
165
|
-
extra = Extra.allow
|
|
195
|
+
extra = pydantic.Extra.allow
|
|
166
196
|
|
|
167
197
|
|
|
168
|
-
class FeatureSetIngestInput(
|
|
198
|
+
class FeatureSetIngestInput(FeatureStoreBaseModel):
|
|
169
199
|
source: Optional[DataSource]
|
|
170
200
|
targets: Optional[list[DataTarget]]
|
|
171
201
|
infer_options: Optional[int]
|
|
172
202
|
credentials: Credentials = Credentials()
|
|
173
203
|
|
|
174
204
|
|
|
175
|
-
class FeatureSetIngestOutput(
|
|
205
|
+
class FeatureSetIngestOutput(FeatureStoreBaseModel):
|
|
176
206
|
feature_set: FeatureSet
|
|
177
207
|
run_object: dict
|
|
@@ -50,6 +50,12 @@ class FeatureFlags(pydantic.BaseModel):
|
|
|
50
50
|
preemption_nodes: PreemptionNodesFeatureFlag
|
|
51
51
|
|
|
52
52
|
|
|
53
|
+
class ArtifactLimits(pydantic.BaseModel):
|
|
54
|
+
max_chunk_size: int
|
|
55
|
+
max_preview_size: int
|
|
56
|
+
max_download_size: int
|
|
57
|
+
|
|
58
|
+
|
|
53
59
|
class FrontendSpec(pydantic.BaseModel):
|
|
54
60
|
jobs_dashboard_url: typing.Optional[str]
|
|
55
61
|
model_monitoring_dashboard_url: typing.Optional[str]
|
|
@@ -70,3 +76,5 @@ class FrontendSpec(pydantic.BaseModel):
|
|
|
70
76
|
feature_store_data_prefixes: typing.Optional[dict[str, str]]
|
|
71
77
|
allowed_artifact_path_prefixes_list: list[str]
|
|
72
78
|
ce: typing.Optional[dict]
|
|
79
|
+
internal_labels: list[str] = []
|
|
80
|
+
artifact_limits: ArtifactLimits
|
mlrun/common/schemas/function.py
CHANGED
|
@@ -45,6 +45,9 @@ class FunctionState:
|
|
|
45
45
|
# same goes for the build which is not coming from the pod, but is used and we can't just omit it for BC reasons
|
|
46
46
|
build = "build"
|
|
47
47
|
|
|
48
|
+
# for pipeline steps
|
|
49
|
+
skipped = "skipped"
|
|
50
|
+
|
|
48
51
|
@classmethod
|
|
49
52
|
def get_function_state_from_pod_state(cls, pod_state: str):
|
|
50
53
|
if pod_state == "succeeded":
|
|
@@ -60,6 +63,7 @@ class FunctionState:
|
|
|
60
63
|
return [
|
|
61
64
|
cls.ready,
|
|
62
65
|
cls.error,
|
|
66
|
+
cls.skipped,
|
|
63
67
|
]
|
|
64
68
|
|
|
65
69
|
|
|
@@ -115,6 +119,13 @@ class FunctionSpec(pydantic.BaseModel):
|
|
|
115
119
|
service_account: typing.Optional[ServiceAccount]
|
|
116
120
|
state_thresholds: typing.Optional[StateThresholds]
|
|
117
121
|
|
|
122
|
+
class Config:
|
|
123
|
+
extra = pydantic.Extra.allow
|
|
124
|
+
|
|
118
125
|
|
|
119
126
|
class Function(pydantic.BaseModel):
|
|
120
127
|
spec: typing.Optional[FunctionSpec]
|
|
128
|
+
application: typing.Optional[dict[str, typing.Any]]
|
|
129
|
+
|
|
130
|
+
class Config:
|
|
131
|
+
extra = pydantic.Extra.allow
|
mlrun/common/schemas/hub.py
CHANGED
|
@@ -59,28 +59,26 @@ class HubSource(BaseModel):
|
|
|
59
59
|
return f"{self.spec.path}/{self.spec.object_type}/{self.spec.channel}/{relative_path}"
|
|
60
60
|
|
|
61
61
|
def get_catalog_uri(self):
|
|
62
|
-
return self.get_full_uri(mlrun.
|
|
62
|
+
return self.get_full_uri(mlrun.mlconf.hub.catalog_filename)
|
|
63
63
|
|
|
64
64
|
@classmethod
|
|
65
65
|
def generate_default_source(cls):
|
|
66
|
-
if not mlrun.
|
|
66
|
+
if not mlrun.mlconf.hub.default_source.create:
|
|
67
67
|
return None
|
|
68
68
|
|
|
69
69
|
now = datetime.now(timezone.utc)
|
|
70
70
|
hub_metadata = HubObjectMetadata(
|
|
71
|
-
name=mlrun.
|
|
72
|
-
description=mlrun.
|
|
71
|
+
name=mlrun.mlconf.hub.default_source.name,
|
|
72
|
+
description=mlrun.mlconf.hub.default_source.description,
|
|
73
73
|
created=now,
|
|
74
74
|
updated=now,
|
|
75
75
|
)
|
|
76
76
|
return cls(
|
|
77
77
|
metadata=hub_metadata,
|
|
78
78
|
spec=HubSourceSpec(
|
|
79
|
-
path=mlrun.
|
|
80
|
-
channel=mlrun.
|
|
81
|
-
object_type=HubSourceType(
|
|
82
|
-
mlrun.config.config.hub.default_source.object_type
|
|
83
|
-
),
|
|
79
|
+
path=mlrun.mlconf.hub.default_source.url,
|
|
80
|
+
channel=mlrun.mlconf.hub.default_source.channel,
|
|
81
|
+
object_type=HubSourceType(mlrun.mlconf.hub.default_source.object_type),
|
|
84
82
|
),
|
|
85
83
|
status=ObjectStatus(state="created"),
|
|
86
84
|
)
|
|
@@ -11,10 +11,9 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
14
|
|
|
17
15
|
from .constants import (
|
|
16
|
+
V3IO_MODEL_MONITORING_DB,
|
|
18
17
|
ControllerPolicy,
|
|
19
18
|
DriftStatus,
|
|
20
19
|
EndpointType,
|
|
@@ -22,19 +21,33 @@ from .constants import (
|
|
|
22
21
|
EventFieldType,
|
|
23
22
|
EventKeyMetrics,
|
|
24
23
|
EventLiveStats,
|
|
24
|
+
FeatureSetFeatures,
|
|
25
25
|
FileTargetKind,
|
|
26
26
|
FunctionURI,
|
|
27
|
+
MetricData,
|
|
28
|
+
ModelEndpointMonitoringMetricType,
|
|
27
29
|
ModelEndpointTarget,
|
|
30
|
+
ModelEndpointTargetSchemas,
|
|
28
31
|
ModelMonitoringMode,
|
|
29
32
|
ModelMonitoringStoreKinds,
|
|
30
33
|
MonitoringFunctionNames,
|
|
34
|
+
PredictionsQueryConstants,
|
|
31
35
|
ProjectSecretKeys,
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
ResultData,
|
|
37
|
+
ResultKindApp,
|
|
38
|
+
ResultStatusApp,
|
|
39
|
+
SchedulingKeys,
|
|
40
|
+
SpecialApps,
|
|
41
|
+
TDEngineSuperTables,
|
|
42
|
+
TSDBTarget,
|
|
43
|
+
V3IOTSDBTables,
|
|
34
44
|
VersionedModel,
|
|
45
|
+
WriterEvent,
|
|
46
|
+
WriterEventKind,
|
|
35
47
|
)
|
|
36
48
|
from .grafana import (
|
|
37
49
|
GrafanaColumn,
|
|
50
|
+
GrafanaColumnType,
|
|
38
51
|
GrafanaDataPoint,
|
|
39
52
|
GrafanaNumberColumn,
|
|
40
53
|
GrafanaStringColumn,
|
|
@@ -47,6 +60,10 @@ from .model_endpoints import (
|
|
|
47
60
|
ModelEndpoint,
|
|
48
61
|
ModelEndpointList,
|
|
49
62
|
ModelEndpointMetadata,
|
|
63
|
+
ModelEndpointMonitoringMetric,
|
|
64
|
+
ModelEndpointMonitoringMetricNoData,
|
|
65
|
+
ModelEndpointMonitoringMetricValues,
|
|
66
|
+
ModelEndpointMonitoringResultValues,
|
|
50
67
|
ModelEndpointSpec,
|
|
51
68
|
ModelEndpointStatus,
|
|
52
69
|
)
|
|
@@ -13,14 +13,22 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import hashlib
|
|
16
|
-
|
|
16
|
+
import re
|
|
17
|
+
from dataclasses import dataclass, field
|
|
17
18
|
from enum import Enum, IntEnum
|
|
18
19
|
from typing import Optional
|
|
19
20
|
|
|
21
|
+
import mlrun.common.constants
|
|
20
22
|
import mlrun.common.helpers
|
|
21
23
|
from mlrun.common.types import StrEnum
|
|
22
24
|
|
|
23
25
|
|
|
26
|
+
class MonitoringStrEnum(StrEnum):
|
|
27
|
+
@classmethod
|
|
28
|
+
def list(cls):
|
|
29
|
+
return list(map(lambda c: c.value, cls))
|
|
30
|
+
|
|
31
|
+
|
|
24
32
|
class EventFieldType:
|
|
25
33
|
FUNCTION_URI = "function_uri"
|
|
26
34
|
FUNCTION = "function"
|
|
@@ -46,9 +54,11 @@ class EventFieldType:
|
|
|
46
54
|
PREDICTIONS = "predictions"
|
|
47
55
|
NAMED_PREDICTIONS = "named_predictions"
|
|
48
56
|
ERROR_COUNT = "error_count"
|
|
57
|
+
MODEL_ERROR = "model_error"
|
|
49
58
|
ENTITIES = "entities"
|
|
50
59
|
FIRST_REQUEST = "first_request"
|
|
51
60
|
LAST_REQUEST = "last_request"
|
|
61
|
+
LAST_REQUEST_TIMESTAMP = "last_request_timestamp"
|
|
52
62
|
METRIC = "metric"
|
|
53
63
|
METRICS = "metrics"
|
|
54
64
|
BATCH_INTERVALS_DICT = "batch_intervals_dict"
|
|
@@ -72,28 +82,53 @@ class EventFieldType:
|
|
|
72
82
|
FEATURE_SET_URI = "monitoring_feature_set_uri"
|
|
73
83
|
ALGORITHM = "algorithm"
|
|
74
84
|
VALUE = "value"
|
|
75
|
-
DRIFT_DETECTED_THRESHOLD = "drift_detected_threshold"
|
|
76
|
-
POSSIBLE_DRIFT_THRESHOLD = "possible_drift_threshold"
|
|
77
85
|
SAMPLE_PARQUET_PATH = "sample_parquet_path"
|
|
86
|
+
TIME = "time"
|
|
87
|
+
TABLE_COLUMN = "table_column"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class FeatureSetFeatures(MonitoringStrEnum):
|
|
91
|
+
LATENCY = EventFieldType.LATENCY
|
|
92
|
+
ERROR_COUNT = EventFieldType.ERROR_COUNT
|
|
93
|
+
METRICS = EventFieldType.METRICS
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def time_stamp(cls):
|
|
97
|
+
return EventFieldType.TIMESTAMP
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def entity(cls):
|
|
101
|
+
return EventFieldType.ENDPOINT_ID
|
|
78
102
|
|
|
79
103
|
|
|
80
104
|
class ApplicationEvent:
|
|
81
105
|
APPLICATION_NAME = "application_name"
|
|
82
|
-
CURRENT_STATS = "current_stats"
|
|
83
|
-
FEATURE_STATS = "feature_stats"
|
|
84
|
-
SAMPLE_PARQUET_PATH = "sample_parquet_path"
|
|
85
106
|
START_INFER_TIME = "start_infer_time"
|
|
86
107
|
END_INFER_TIME = "end_infer_time"
|
|
87
|
-
LAST_REQUEST = "last_request"
|
|
88
108
|
ENDPOINT_ID = "endpoint_id"
|
|
89
109
|
OUTPUT_STREAM_URI = "output_stream_uri"
|
|
90
110
|
|
|
91
111
|
|
|
92
|
-
class WriterEvent(
|
|
112
|
+
class WriterEvent(MonitoringStrEnum):
|
|
93
113
|
APPLICATION_NAME = "application_name"
|
|
94
114
|
ENDPOINT_ID = "endpoint_id"
|
|
95
115
|
START_INFER_TIME = "start_infer_time"
|
|
96
116
|
END_INFER_TIME = "end_infer_time"
|
|
117
|
+
EVENT_KIND = "event_kind" # metric or result
|
|
118
|
+
DATA = "data"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class WriterEventKind(MonitoringStrEnum):
|
|
122
|
+
METRIC = "metric"
|
|
123
|
+
RESULT = "result"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class MetricData(MonitoringStrEnum):
|
|
127
|
+
METRIC_NAME = "metric_name"
|
|
128
|
+
METRIC_VALUE = "metric_value"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ResultData(MonitoringStrEnum):
|
|
97
132
|
RESULT_NAME = "result_name"
|
|
98
133
|
RESULT_VALUE = "result_value"
|
|
99
134
|
RESULT_KIND = "result_kind"
|
|
@@ -101,10 +136,6 @@ class WriterEvent(StrEnum):
|
|
|
101
136
|
RESULT_EXTRA_DATA = "result_extra_data"
|
|
102
137
|
CURRENT_STATS = "current_stats"
|
|
103
138
|
|
|
104
|
-
@classmethod
|
|
105
|
-
def list(cls):
|
|
106
|
-
return list(map(lambda c: c.value, cls))
|
|
107
|
-
|
|
108
139
|
|
|
109
140
|
class EventLiveStats:
|
|
110
141
|
LATENCY_AVG_5M = "latency_avg_5m"
|
|
@@ -122,21 +153,40 @@ class EventKeyMetrics:
|
|
|
122
153
|
REAL_TIME = "real_time"
|
|
123
154
|
|
|
124
155
|
|
|
125
|
-
class
|
|
126
|
-
TSDB = "tsdb"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class ModelEndpointTarget:
|
|
156
|
+
class ModelEndpointTarget(MonitoringStrEnum):
|
|
130
157
|
V3IO_NOSQL = "v3io-nosql"
|
|
131
158
|
SQL = "sql"
|
|
132
159
|
|
|
133
160
|
|
|
161
|
+
class StreamKind(MonitoringStrEnum):
|
|
162
|
+
V3IO_STREAM = "v3io_stream"
|
|
163
|
+
KAFKA = "kafka"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class TSDBTarget(MonitoringStrEnum):
|
|
167
|
+
V3IO_TSDB = "v3io-tsdb"
|
|
168
|
+
TDEngine = "tdengine"
|
|
169
|
+
|
|
170
|
+
|
|
134
171
|
class ProjectSecretKeys:
|
|
135
172
|
ENDPOINT_STORE_CONNECTION = "MODEL_MONITORING_ENDPOINT_STORE_CONNECTION"
|
|
136
173
|
ACCESS_KEY = "MODEL_MONITORING_ACCESS_KEY"
|
|
137
|
-
PIPELINES_ACCESS_KEY = "MODEL_MONITORING_PIPELINES_ACCESS_KEY"
|
|
138
|
-
KAFKA_BOOTSTRAP_SERVERS = "KAFKA_BOOTSTRAP_SERVERS"
|
|
139
174
|
STREAM_PATH = "STREAM_PATH"
|
|
175
|
+
TSDB_CONNECTION = "TSDB_CONNECTION"
|
|
176
|
+
|
|
177
|
+
@classmethod
|
|
178
|
+
def mandatory_secrets(cls):
|
|
179
|
+
return [
|
|
180
|
+
cls.ENDPOINT_STORE_CONNECTION,
|
|
181
|
+
cls.STREAM_PATH,
|
|
182
|
+
cls.TSDB_CONNECTION,
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ModelEndpointTargetSchemas(MonitoringStrEnum):
|
|
187
|
+
V3IO = "v3io"
|
|
188
|
+
MYSQL = "mysql"
|
|
189
|
+
SQLITE = "sqlite"
|
|
140
190
|
|
|
141
191
|
|
|
142
192
|
class ModelMonitoringStoreKinds:
|
|
@@ -146,15 +196,24 @@ class ModelMonitoringStoreKinds:
|
|
|
146
196
|
|
|
147
197
|
class SchedulingKeys:
|
|
148
198
|
LAST_ANALYZED = "last_analyzed"
|
|
199
|
+
ENDPOINT_ID = "endpoint_id"
|
|
200
|
+
APPLICATION_NAME = "application_name"
|
|
201
|
+
UID = "uid"
|
|
149
202
|
|
|
150
203
|
|
|
151
204
|
class FileTargetKind:
|
|
152
205
|
ENDPOINTS = "endpoints"
|
|
153
206
|
EVENTS = "events"
|
|
207
|
+
PREDICTIONS = "predictions"
|
|
154
208
|
STREAM = "stream"
|
|
155
209
|
PARQUET = "parquet"
|
|
156
210
|
APPS_PARQUET = "apps_parquet"
|
|
157
211
|
LOG_STREAM = "log_stream"
|
|
212
|
+
APP_RESULTS = "app_results"
|
|
213
|
+
APP_METRICS = "app_metrics"
|
|
214
|
+
MONITORING_SCHEDULES = "monitoring_schedules"
|
|
215
|
+
MONITORING_APPLICATION = "monitoring_application"
|
|
216
|
+
ERRORS = "errors"
|
|
158
217
|
|
|
159
218
|
|
|
160
219
|
class ModelMonitoringMode(str, Enum):
|
|
@@ -168,29 +227,23 @@ class EndpointType(IntEnum):
|
|
|
168
227
|
LEAF_EP = 3 # end point that is a child of a router
|
|
169
228
|
|
|
170
229
|
|
|
171
|
-
class
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
ERRORS_TOTAL = "errors_total"
|
|
176
|
-
DRIFT_METRICS = "drift_metrics"
|
|
177
|
-
DRIFT_STATUS = "drift_status"
|
|
230
|
+
class MonitoringFunctionNames(MonitoringStrEnum):
|
|
231
|
+
STREAM = "model-monitoring-stream"
|
|
232
|
+
APPLICATION_CONTROLLER = "model-monitoring-controller"
|
|
233
|
+
WRITER = "model-monitoring-writer"
|
|
178
234
|
|
|
179
235
|
|
|
180
|
-
class
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
236
|
+
class V3IOTSDBTables(MonitoringStrEnum):
|
|
237
|
+
APP_RESULTS = "app-results"
|
|
238
|
+
METRICS = "metrics"
|
|
239
|
+
EVENTS = "events"
|
|
240
|
+
ERRORS = "errors"
|
|
185
241
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
MonitoringFunctionNames.BATCH,
|
|
192
|
-
MonitoringFunctionNames.APPLICATION_CONTROLLER,
|
|
193
|
-
]
|
|
242
|
+
|
|
243
|
+
class TDEngineSuperTables(MonitoringStrEnum):
|
|
244
|
+
APP_RESULTS = "app_results"
|
|
245
|
+
METRICS = "metrics"
|
|
246
|
+
PREDICTIONS = "predictions"
|
|
194
247
|
|
|
195
248
|
|
|
196
249
|
@dataclass
|
|
@@ -236,7 +289,7 @@ class EndpointUID:
|
|
|
236
289
|
function_hash_key: str
|
|
237
290
|
model: str
|
|
238
291
|
model_version: str
|
|
239
|
-
uid:
|
|
292
|
+
uid: str = field(init=False)
|
|
240
293
|
|
|
241
294
|
def __post_init__(self):
|
|
242
295
|
function_ref = (
|
|
@@ -269,6 +322,7 @@ class ResultKindApp(Enum):
|
|
|
269
322
|
concept_drift = 1
|
|
270
323
|
model_performance = 2
|
|
271
324
|
system_performance = 3
|
|
325
|
+
mm_app_anomaly = 4
|
|
272
326
|
|
|
273
327
|
|
|
274
328
|
class ResultStatusApp(IntEnum):
|
|
@@ -283,12 +337,52 @@ class ResultStatusApp(IntEnum):
|
|
|
283
337
|
|
|
284
338
|
|
|
285
339
|
class ModelMonitoringAppLabel:
|
|
286
|
-
KEY =
|
|
340
|
+
KEY = mlrun.common.constants.MLRunInternalLabels.mlrun_type
|
|
287
341
|
VAL = "mlrun__model-monitoring-application"
|
|
288
342
|
|
|
343
|
+
def __str__(self) -> str:
|
|
344
|
+
return f"{self.KEY}={self.VAL}"
|
|
345
|
+
|
|
289
346
|
|
|
290
347
|
class ControllerPolicy:
|
|
291
348
|
BASE_PERIOD = "base_period"
|
|
292
349
|
|
|
293
350
|
|
|
294
|
-
|
|
351
|
+
class HistogramDataDriftApplicationConstants:
|
|
352
|
+
NAME = "histogram-data-drift"
|
|
353
|
+
GENERAL_RESULT_NAME = "general_drift"
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class PredictionsQueryConstants:
|
|
357
|
+
DEFAULT_AGGREGATION_GRANULARITY = "10m"
|
|
358
|
+
INVOCATIONS = "invocations"
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class SpecialApps:
|
|
362
|
+
MLRUN_INFRA = "mlrun-infra"
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
_RESERVED_FUNCTION_NAMES = MonitoringFunctionNames.list() + [SpecialApps.MLRUN_INFRA]
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
V3IO_MODEL_MONITORING_DB = "v3io"
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class ModelEndpointMonitoringMetricType(StrEnum):
|
|
372
|
+
RESULT = "result"
|
|
373
|
+
METRIC = "metric"
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
_FQN_PART_PATTERN = r"[a-zA-Z0-9_-]+"
|
|
377
|
+
FQN_PATTERN = (
|
|
378
|
+
rf"^(?P<project>{_FQN_PART_PATTERN})\."
|
|
379
|
+
rf"(?P<app>{_FQN_PART_PATTERN})\."
|
|
380
|
+
rf"(?P<type>{ModelEndpointMonitoringMetricType.RESULT}|{ModelEndpointMonitoringMetricType.METRIC})\."
|
|
381
|
+
rf"(?P<name>{_FQN_PART_PATTERN})$"
|
|
382
|
+
)
|
|
383
|
+
FQN_REGEX = re.compile(FQN_PATTERN)
|
|
384
|
+
|
|
385
|
+
# refer to `mlrun.utils.regex.project_name`
|
|
386
|
+
PROJECT_PATTERN = r"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
|
|
387
|
+
|
|
388
|
+
MODEL_ENDPOINT_ID_PATTERN = r"^[a-zA-Z0-9_-]+$"
|
|
@@ -11,12 +11,18 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
#
|
|
15
14
|
|
|
16
15
|
from typing import Optional, Union
|
|
17
16
|
|
|
18
17
|
from pydantic import BaseModel
|
|
19
18
|
|
|
19
|
+
import mlrun.common.types
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class GrafanaColumnType(mlrun.common.types.StrEnum):
|
|
23
|
+
NUMBER = "number"
|
|
24
|
+
STRING = "string"
|
|
25
|
+
|
|
20
26
|
|
|
21
27
|
class GrafanaColumn(BaseModel):
|
|
22
28
|
text: str
|
|
@@ -24,13 +30,11 @@ class GrafanaColumn(BaseModel):
|
|
|
24
30
|
|
|
25
31
|
|
|
26
32
|
class GrafanaNumberColumn(GrafanaColumn):
|
|
27
|
-
|
|
28
|
-
type: str = "number"
|
|
33
|
+
type: str = GrafanaColumnType.NUMBER
|
|
29
34
|
|
|
30
35
|
|
|
31
36
|
class GrafanaStringColumn(GrafanaColumn):
|
|
32
|
-
|
|
33
|
-
type: str = "string"
|
|
37
|
+
type: str = GrafanaColumnType.STRING
|
|
34
38
|
|
|
35
39
|
|
|
36
40
|
class GrafanaTable(BaseModel):
|