Skip to content

Commit

Permalink
[Model Monitoring] Drift detection, grafana proxy, httpdb SDK (#795)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michaelliv committed Mar 21, 2021
1 parent a6e9016 commit 13a701b
Show file tree
Hide file tree
Showing 12 changed files with 1,800 additions and 542 deletions.
377 changes: 282 additions & 95 deletions mlrun/api/api/endpoints/grafana_proxy.py

Large diffs are not rendered by default.

89 changes: 58 additions & 31 deletions mlrun/api/api/endpoints/model_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,87 +4,114 @@
from fastapi import APIRouter, Query, Request, Response

from mlrun.api.crud.model_endpoints import ModelEndpoints, get_access_key
from mlrun.api.schemas import ModelEndpointState, ModelEndpointStateList
from mlrun.api.schemas import ModelEndpoint, ModelEndpointList
from mlrun.errors import MLRunConflictError

router = APIRouter()


@router.post(
"/projects/{project}/model-endpoints/{endpoint_id}/clear",
@router.put(
"/projects/{project}/model-endpoints/{endpoint_id}",
status_code=HTTPStatus.NO_CONTENT.value,
)
def clear_endpoint_record(request: Request, project: str, endpoint_id: str):
async def create_or_patch(
request: Request, project: str, endpoint_id: str, model_endpoint: ModelEndpoint
) -> Response:
"""
Clears endpoint record from KV by endpoint_id
Either create or updates the kv record of a given ModelEndpoint object
"""
access_key = get_access_key(request)
ModelEndpoints.clear_endpoint_record(access_key, project, endpoint_id)
access_key = get_access_key(request.headers)
if project != model_endpoint.metadata.project:
raise MLRunConflictError(
f"Can't store endpoint of project {model_endpoint.metadata.project} into project {project}"
)
if endpoint_id != model_endpoint.metadata.uid:
raise MLRunConflictError(
f"Mismatch between endpoint_id {endpoint_id} and ModelEndpoint.metadata.uid {model_endpoint.metadata.uid}."
f"\nMake sure the supplied function_uri, and model are configured as intended"
)
await ModelEndpoints.create_or_patch(
access_key=access_key, model_endpoint=model_endpoint
)
return Response(status_code=HTTPStatus.NO_CONTENT.value)


@router.get(
"/projects/{project}/model-endpoints", response_model=ModelEndpointStateList
@router.delete(
"/projects/{project}/model-endpoints/{endpoint_id}",
status_code=HTTPStatus.NO_CONTENT.value,
)
def list_endpoints(
async def delete_endpoint_record(
request: Request, project: str, endpoint_id: str
) -> Response:
"""
Clears endpoint record from KV by endpoint_id
"""
access_key = get_access_key(request.headers)
await ModelEndpoints.delete_endpoint_record(
access_key=access_key, project=project, endpoint_id=endpoint_id
)
return Response(status_code=HTTPStatus.NO_CONTENT.value)


@router.get("/projects/{project}/model-endpoints", response_model=ModelEndpointList)
async def list_endpoints(
request: Request,
project: str,
model: Optional[str] = Query(None),
function: Optional[str] = Query(None),
tag: Optional[str] = Query(None),
labels: List[str] = Query([], alias="label"),
start: str = Query(default="now-1h"),
end: str = Query(default="now"),
metrics: List[str] = Query([], alias="metric"),
):
) -> ModelEndpointList:
"""
Returns a list of endpoints of type 'ModelEndpoint', supports filtering by model, function, tag and labels.
Lables can be used to filter on the existance of a label:
`api/projects/{project}/model-endpoints/?label=mylabel`
Labels can be used to filter on the existence of a label:
api/projects/{project}/model-endpoints/?label=mylabel
Or on the value of a given label:
`api/projects/{project}/model-endpoints/?label=mylabel=1`
api/projects/{project}/model-endpoints/?label=mylabel=1
Multiple labels can be queried in a single request by either using `&` seperator:
`api/projects/{project}/model-endpoints/?label=mylabel=1&label=myotherlabel=2`
Multiple labels can be queried in a single request by either using "&" separator:
api/projects/{project}/model-endpoints/?label=mylabel=1&label=myotherlabel=2
Or by using a `,` (comma) seperator:
`api/projects/{project}/model-endpoints/?label=mylabel=1,myotherlabel=2`
Or by using a "," (comma) separator:
api/projects/{project}/model-endpoints/?label=mylabel=1,myotherlabel=2
"""
access_key = get_access_key(request)
endpoint_list = ModelEndpoints.list_endpoints(
access_key = get_access_key(request.headers)
endpoints = await ModelEndpoints.list_endpoints(
access_key=access_key,
project=project,
model=model,
function=function,
tag=tag,
labels=labels,
metrics=metrics,
start=start,
end=end,
)
return ModelEndpointStateList(endpoints=endpoint_list)
return endpoints


@router.get(
"/projects/{project}/model-endpoints/{endpoint_id}",
response_model=ModelEndpointState,
"/projects/{project}/model-endpoints/{endpoint_id}", response_model=ModelEndpoint
)
def get_endpoint(
async def get_endpoint(
request: Request,
project: str,
endpoint_id: str,
start: str = Query(default="now-1h"),
end: str = Query(default="now"),
metrics: List[str] = Query([], alias="metric"),
features: bool = Query(default=False),
):
access_key = get_access_key(request)
return ModelEndpoints.get_endpoint(
feature_analysis: bool = Query(default=False),
) -> ModelEndpoint:
access_key = get_access_key(request.headers)
endpoint = await ModelEndpoints.get_endpoint(
access_key=access_key,
project=project,
endpoint_id=endpoint_id,
metrics=metrics,
start=start,
end=end,
features=features,
feature_analysis=feature_analysis,
)
return endpoint

0 comments on commit 13a701b

Please sign in to comment.