Fix charts

Signed-off-by: András Schmelczer <andras@schmelczer.dev>
This commit is contained in:
Andras Schmelczer 2022-04-10 22:25:47 +02:00
parent 4b92a75841
commit 5b92d22f75
5 changed files with 51 additions and 26 deletions

View file

@ -1,9 +1,11 @@
from pathlib import Path
from typing import Any, Dict, List from typing import Any, Dict, List
from fastapi import FastAPI, status from fastapi import FastAPI, status
from fastapi.middleware.wsgi import WSGIMiddleware from fastapi.middleware.wsgi import WSGIMiddleware
from fastapi.openapi.docs import get_swagger_ui_html from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from starlette.responses import HTMLResponse from starlette.responses import HTMLResponse
from ..context import get_context from ..context import get_context
@ -11,6 +13,8 @@ from ..helper import snake_case_to_text
from ..metrics import create_dash_app from ..metrics import create_dash_app
from ..views import HealthCheckResponse, Query from ..views import HealthCheckResponse, Query
PATH = Path(__file__).parent.resolve()
def create_fastapi_app( def create_fastapi_app(
function_name: str, disable_docs: bool, disable_metrics: bool function_name: str, disable_docs: bool, disable_metrics: bool
@ -40,6 +44,10 @@ def create_fastapi_app(
def redirect_to_entrypoint() -> RedirectResponse: def redirect_to_entrypoint() -> RedirectResponse:
return RedirectResponse("/metrics") return RedirectResponse("/metrics")
app.mount(
"/assets", StaticFiles(directory=PATH / "../metrics/assets"), name="static"
)
@app.post("/query", status_code=status.HTTP_200_OK) @app.post("/query", status_code=status.HTTP_200_OK)
def query_metrics(query: Query) -> List[Dict[str, Any]]: def query_metrics(query: Query) -> List[Dict[str, Any]]:
return get_context().persistence.query( return get_context().persistence.query(

View file

@ -2,6 +2,7 @@ from typing import Any, Callable
import uvicorn import uvicorn
from fastapi import FastAPI, status from fastapi import FastAPI, status
from uvicorn.config import LOGGING_CONFIG
from ..tracing import TracingContext from ..tracing import TracingContext
from ..views import Trace from ..views import Trace
@ -32,8 +33,7 @@ def serve(
host="0.0.0.0", host="0.0.0.0",
port=5050, port=5050,
log_config={ log_config={
"version": 1, **LOGGING_CONFIG,
"disable_existing_loggers": False,
"formatters": { "formatters": {
"default": { "default": {
"()": "good_ai.logger.CustomFormatter", "()": "good_ai.logger.CustomFormatter",
@ -44,26 +44,5 @@ def serve(
"fmt": "%(asctime)s | %(levelname)8s | %(message)s", # noqa: E501 "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,
},
},
}, },
) )

View file

@ -0,0 +1,3 @@
body {
background-color: hotpink;
}

View file

@ -7,6 +7,8 @@ from dash import Dash, dash_table, dcc, html
from dash.dependencies import Input, Output from dash.dependencies import Input, Output
from flask import Flask from flask import Flask
from good_ai.utilities.unique import unique
from ..context import get_context from ..context import get_context
from ..helper import snake_case_to_text from ..helper import snake_case_to_text
from ..views import SortBy 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: def create_dash_app(function_name: str) -> Flask:
flask_app = Flask(__name__)
app = Dash( app = Dash(
function_name, function_name,
requests_pathname_prefix=get_context().metrics_path + "/", requests_pathname_prefix=get_context().metrics_path + "/",
server=flask_app,
title=snake_case_to_text(function_name), title=snake_case_to_text(function_name),
update_title=None,
external_stylesheets=[
"/assets/index.css",
],
) )
documents = get_context().persistence.get_documents() documents = get_context().persistence.get_documents()
@ -117,8 +125,34 @@ def create_dash_app(function_name: str) -> Flask:
) )
df = pd.DataFrame(rows) df = pd.DataFrame(rows)
return px.parallel_coordinates( return go.Figure(
df, labels={c: snake_case_to_text(c) for c in df.columns} 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

View file

@ -1,4 +1,5 @@
from typing import Literal from typing import Literal
from typing_extensions import TypedDict from typing_extensions import TypedDict