Fix charts
Signed-off-by: András Schmelczer <andras@schmelczer.dev>
This commit is contained in:
parent
6b2b4dc989
commit
498c7f0459
5 changed files with 51 additions and 26 deletions
|
|
@ -1,9 +1,11 @@
|
|||
from pathlib import Path
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from fastapi import FastAPI, status
|
||||
from fastapi.middleware.wsgi import WSGIMiddleware
|
||||
from fastapi.openapi.docs import get_swagger_ui_html
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from starlette.responses import HTMLResponse
|
||||
|
||||
from ..context import get_context
|
||||
|
|
@ -11,6 +13,8 @@ from ..helper import snake_case_to_text
|
|||
from ..metrics import create_dash_app
|
||||
from ..views import HealthCheckResponse, Query
|
||||
|
||||
PATH = Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
def create_fastapi_app(
|
||||
function_name: str, disable_docs: bool, disable_metrics: bool
|
||||
|
|
@ -40,6 +44,10 @@ def create_fastapi_app(
|
|||
def redirect_to_entrypoint() -> RedirectResponse:
|
||||
return RedirectResponse("/metrics")
|
||||
|
||||
app.mount(
|
||||
"/assets", StaticFiles(directory=PATH / "../metrics/assets"), name="static"
|
||||
)
|
||||
|
||||
@app.post("/query", status_code=status.HTTP_200_OK)
|
||||
def query_metrics(query: Query) -> List[Dict[str, Any]]:
|
||||
return get_context().persistence.query(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from typing import Any, Callable
|
|||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, status
|
||||
from uvicorn.config import LOGGING_CONFIG
|
||||
|
||||
from ..tracing import TracingContext
|
||||
from ..views import Trace
|
||||
|
|
@ -32,8 +33,7 @@ def serve(
|
|||
host="0.0.0.0",
|
||||
port=5050,
|
||||
log_config={
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
**LOGGING_CONFIG,
|
||||
"formatters": {
|
||||
"default": {
|
||||
"()": "good_ai.logger.CustomFormatter",
|
||||
|
|
@ -44,26 +44,5 @@ def serve(
|
|||
"fmt": "%(asctime)s | %(levelname)8s | %(message)s", # noqa: E501
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
"default": {
|
||||
"formatter": "default",
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://sys.stderr",
|
||||
},
|
||||
"access": {
|
||||
"formatter": "access",
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://sys.stdout",
|
||||
},
|
||||
},
|
||||
"loggers": {
|
||||
"uvicorn": {"handlers": ["default"], "level": "INFO"},
|
||||
"uvicorn.error": {"level": "INFO"},
|
||||
"uvicorn.access": {
|
||||
"handlers": ["access"],
|
||||
"level": "INFO",
|
||||
"propagate": False,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
3
good_ai/src/good_ai/good_ai/metrics/assets/index.css
Normal file
3
good_ai/src/good_ai/good_ai/metrics/assets/index.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background-color: hotpink;
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ from dash import Dash, dash_table, dcc, html
|
|||
from dash.dependencies import Input, Output
|
||||
from flask import Flask
|
||||
|
||||
from good_ai.utilities.unique import unique
|
||||
|
||||
from ..context import get_context
|
||||
from ..helper import snake_case_to_text
|
||||
from ..views import SortBy
|
||||
|
|
@ -15,10 +17,16 @@ from .get_filter_from_datatable import get_filter_from_datatable
|
|||
|
||||
|
||||
def create_dash_app(function_name: str) -> Flask:
|
||||
flask_app = Flask(__name__)
|
||||
app = Dash(
|
||||
function_name,
|
||||
requests_pathname_prefix=get_context().metrics_path + "/",
|
||||
server=flask_app,
|
||||
title=snake_case_to_text(function_name),
|
||||
update_title=None,
|
||||
external_stylesheets=[
|
||||
"/assets/index.css",
|
||||
],
|
||||
)
|
||||
|
||||
documents = get_context().persistence.get_documents()
|
||||
|
|
@ -117,8 +125,34 @@ def create_dash_app(function_name: str) -> Flask:
|
|||
)
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
return px.parallel_coordinates(
|
||||
df, labels={c: snake_case_to_text(c) for c in df.columns}
|
||||
return go.Figure(
|
||||
go.Parcoords(
|
||||
dimensions=[
|
||||
get_dimension_descriptor(df, c)
|
||||
for c in df.columns
|
||||
if not c.startswith("arg:") and c not in {"id", "created"}
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
return app.server
|
||||
return flask_app
|
||||
|
||||
|
||||
def get_dimension_descriptor(df: pd.DataFrame, column: str) -> Dict[str, Any]:
|
||||
dimension: Dict[str, Any] = {
|
||||
"label": snake_case_to_text(column),
|
||||
}
|
||||
|
||||
values = df[column]
|
||||
|
||||
try:
|
||||
dimension["values"] = [float(v) for v in values]
|
||||
except (TypeError, ValueError):
|
||||
unique_values = unique(values)
|
||||
value_mapping = {str(v): i for i, v in enumerate(unique_values)}
|
||||
|
||||
dimension["values"] = [value_mapping[str(v)] for v in values]
|
||||
dimension["tickvals"] = list(value_mapping.values())
|
||||
dimension["ticktext"] = list(value_mapping.keys())
|
||||
|
||||
return dimension
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from typing import Literal
|
||||
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue