Skip to content

Commit

Permalink
dash board (#6)
Browse files Browse the repository at this point in the history
* chore(deps): update gradle dependencies

* feat(dash-board): init dash app
  • Loading branch information
bbortt committed Apr 1, 2024
1 parent ad47067 commit 65d8245
Show file tree
Hide file tree
Showing 12 changed files with 978 additions and 15 deletions.
15 changes: 14 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2
dash-board:
name: 'App: dash-board'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Poetry
run: curl -sSL https://install.python-poetry.org | python -
- name: Install Dependencies
working-directory: apps/dash-board
run: poetry install
k6-report-ingress:
name: 'App: k6-report-ingress'
runs-on: ubuntu-latest
Expand Down Expand Up @@ -97,7 +110,7 @@ jobs:
timeout-minutes: 5
run: |
# Start the application in the background
java -jar "$(find build/artifacts -type f -name '*.jar' -not -name '*-plain.jar')" &
java --enable-preview -jar "$(find build/artifacts -type f -name '*.jar' -not -name '*-plain.jar')" &
APP_PID=$!
# Wait for the application to be ready
Expand Down
3 changes: 2 additions & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/poetry.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions .idea/runConfigurations/dash_board.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file added apps/dash-board/README.md
Empty file.
100 changes: 100 additions & 0 deletions apps/dash-board/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import os

import dash
import pandas as pd
import plotly.graph_objs as go
from dash import dcc, html
from dash.dependencies import Input, Output
from dotenv import load_dotenv
from psycopg2 import pool

load_dotenv()

db_pool = pool.SimpleConnectionPool(minconn=1, maxconn=10,
dbname=os.getenv('DB_NAME', 'k6_dashboard'),
user=os.getenv('DB_USER', 'k6_dashboard'),
password=os.getenv('DB_PASSWORD', 'KrPPCHdYSXz6wMct5tUK'),
host=os.getenv('DB_HOST', 'localhost'))


def fetch_data(query, params=None):
# Get a connection from the pool
connection = db_pool.getconn()
try:
cursor = connection.cursor()
if params:
cursor.execute(query, params)
else:
cursor.execute(query)
result = cursor.fetchall()
finally:
cursor.close()
# Put the connection back in the pool instead of closing it
db_pool.putconn(connection)
return result


# Fetch unique test run IDs for dropdown options
test_run_ids_query = "SELECT DISTINCT tags->>'testid' AS testid FROM samples"
test_run_ids = fetch_data(test_run_ids_query)
test_run_id_options = [{'label': id[0], 'value': id[0]} for id in test_run_ids]

app = dash.Dash('K6 Dashboard')

app.layout = html.Div([
html.H1('K6 DASH Board'),
dcc.Dropdown(
id='test-run-dropdown',
options=test_run_id_options,
# Set default value to the first test run ID
value=[test_run_id_options[0]['value']] if test_run_id_options else None,
# Enable multiple selections
multi=True
),
# Div to hold the dynamically generated graphs
html.Div(id='response-time-graph')
])

test_run_query = """
SELECT date_trunc('second', ts) AS time,
avg(value) AS avg_rt,
percentile_cont(0.95) WITHIN GROUP (ORDER BY value) AS perc_95_rt
FROM samples
WHERE metric = 'http_req_duration'
AND (tags ->> 'status')::integer < 400
AND tags ->> 'testid' = %s
GROUP BY 1
ORDER BY 1;
"""


@app.callback(
Output('response-time-graph', 'children'),
[Input('test-run-dropdown', 'value')]
)
def update_graph(selected_test_run_ids):
graphs = [] # List to hold the graph components

for test_run_id in selected_test_run_ids:
data = fetch_data(test_run_query, (test_run_id,))

# Convert query results to a DataFrame
agg_df = pd.DataFrame(data, columns=['time', 'avg_rt', 'perc_95_rt'])

# Create a Plotly graph object for the average and 95th percentile response times
figure = go.Figure()
figure.add_trace(
go.Scatter(x=agg_df['time'], y=agg_df['avg_rt'], mode='lines+markers', name='Avg Response Time (ms)'))
figure.add_trace(go.Scatter(x=agg_df['time'], y=agg_df['perc_95_rt'], mode='lines+markers',
name='95th Percentile Response Time (ms)'))
figure.update_layout(title=f'Response Time for Test Run {test_run_id}', xaxis_title='Timestamp',
yaxis_title='Response Time (ms)')

# Append the figure wrapped in a dcc.Graph component to the graphs list
graphs.append(dcc.Graph(figure=figure))

return graphs # Return the list of Graph components to be dynamically displayed


if __name__ == '__main__':
app.run_server(debug=True)
10 changes: 10 additions & 0 deletions apps/dash-board/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id "base"
}


group = "io.github.bbortt.k6.dashboard"


dependencies {
}

0 comments on commit 65d8245

Please sign in to comment.