Grafana as Code
Transfer our dashboard into a code representation via grafanalib.
This commit is contained in:
2
deploy/grafana-dashboard/.gitignore
vendored
Normal file
2
deploy/grafana-dashboard/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Ignore the generated json encoded dashboard.
|
||||||
|
./main.json
|
16
deploy/grafana-dashboard/Readme.md
Normal file
16
deploy/grafana-dashboard/Readme.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Grafana Dashboard Deployment
|
||||||
|
|
||||||
|
## Grafanalib
|
||||||
|
|
||||||
|
We use [Grafanalib](https://github.com/weaveworks/grafanalib) for the definition of our dashboard.
|
||||||
|
You need to install the python package: `pip install grafanalib`.
|
||||||
|
|
||||||
|
### Generation
|
||||||
|
|
||||||
|
Generate the Grafana dashboard by running `main.py`.
|
||||||
|
The generated Json definition can be imported in the Grafana UI.
|
||||||
|
|
||||||
|
### Deployment
|
||||||
|
|
||||||
|
You can copy the generated json into the field under the dashboards setting -> "JSON Model".
|
||||||
|
The version number needs to match!
|
51
deploy/grafana-dashboard/availability_row.py
Normal file
51
deploy/grafana-dashboard/availability_row.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
from grafanalib.core import RowPanel, BarGauge, GridPos, TimeSeries, ORIENTATION_VERTICAL, \
|
||||||
|
GAUGE_DISPLAY_MODE_BASIC
|
||||||
|
from grafanalib.influxdb import InfluxDBTarget
|
||||||
|
|
||||||
|
from util import read_query
|
||||||
|
|
||||||
|
prewarming_pool_size = BarGauge(
|
||||||
|
title="Prewarming Pool Size",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("prewarming-pool-size"))],
|
||||||
|
gridPos=GridPos(h=10, w=11, x=0, y=3),
|
||||||
|
allValues=True,
|
||||||
|
orientation=ORIENTATION_VERTICAL,
|
||||||
|
displayMode=GAUGE_DISPLAY_MODE_BASIC,
|
||||||
|
max=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
idle_runner = TimeSeries(
|
||||||
|
title="Idle Runner",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("idle-runner"))],
|
||||||
|
gridPos=GridPos(h=10, w=13, x=11, y=3),
|
||||||
|
lineInterpolation="stepAfter",
|
||||||
|
)
|
||||||
|
|
||||||
|
runner_startup_duration = TimeSeries(
|
||||||
|
title="Runner startup duration",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("runner-startup-duration"))],
|
||||||
|
gridPos=GridPos(h=10, w=12, x=0, y=13),
|
||||||
|
unit="ns",
|
||||||
|
)
|
||||||
|
|
||||||
|
used_runner = TimeSeries(
|
||||||
|
title="Used Runner",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("used-runner"))],
|
||||||
|
gridPos=GridPos(h=10, w=12, x=12, y=13),
|
||||||
|
)
|
||||||
|
|
||||||
|
availability_row = RowPanel(
|
||||||
|
title="Availability",
|
||||||
|
collapsed=True,
|
||||||
|
gridPos=GridPos(h=1, w=24, x=0, y=2),
|
||||||
|
panels=[
|
||||||
|
prewarming_pool_size,
|
||||||
|
idle_runner,
|
||||||
|
runner_startup_duration,
|
||||||
|
used_runner
|
||||||
|
]
|
||||||
|
)
|
21
deploy/grafana-dashboard/color_mapping.py
Normal file
21
deploy/grafana-dashboard/color_mapping.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
def color_mapping(name, color):
|
||||||
|
return {
|
||||||
|
"fieldConfig": {
|
||||||
|
"overrides": [{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": name
|
||||||
|
},
|
||||||
|
"properties": [{
|
||||||
|
"id": "color",
|
||||||
|
"value": {
|
||||||
|
"fixedColor": color,
|
||||||
|
"mode": "fixed"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
grey_all_mapping = color_mapping("all", "#4c4b5a")
|
112
deploy/grafana-dashboard/general_row.py
Normal file
112
deploy/grafana-dashboard/general_row.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from grafanalib.core import RowPanel, GridPos, Stat, TimeSeries, Heatmap, BarGauge, GAUGE_DISPLAY_MODE_GRADIENT
|
||||||
|
from grafanalib.influxdb import InfluxDBTarget
|
||||||
|
|
||||||
|
from color_mapping import grey_all_mapping
|
||||||
|
from util import read_query
|
||||||
|
|
||||||
|
requests_per_minute = TimeSeries(
|
||||||
|
title="Requests per minute",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("requests-per-minute"))],
|
||||||
|
gridPos=GridPos(h=9, w=8, x=0, y=1),
|
||||||
|
scaleDistributionType="log",
|
||||||
|
extraJson=grey_all_mapping
|
||||||
|
)
|
||||||
|
|
||||||
|
request_latency = Heatmap(
|
||||||
|
title="Request Latency",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
dataFormat="timeseries",
|
||||||
|
targets=[InfluxDBTarget(query=read_query("request-latency"))],
|
||||||
|
gridPos=GridPos(h=9, w=8, x=8, y=1),
|
||||||
|
extraJson={
|
||||||
|
"options": {},
|
||||||
|
"yAxis": {
|
||||||
|
"format": "ns"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
service_time = TimeSeries(
|
||||||
|
title="Service time (99.9%)",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("service-time"))],
|
||||||
|
gridPos=GridPos(h=9, w=8, x=16, y=1),
|
||||||
|
scaleDistributionType="log",
|
||||||
|
scaleDistributionLog=10,
|
||||||
|
unit="ns"
|
||||||
|
)
|
||||||
|
|
||||||
|
current_environment_count = Stat(
|
||||||
|
title="Current environment count",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("current-environment-count"))],
|
||||||
|
gridPos=GridPos(h=6, w=8, x=0, y=10),
|
||||||
|
alignment='center'
|
||||||
|
)
|
||||||
|
|
||||||
|
currently_used_runners = Stat(
|
||||||
|
title="Currently used runners",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("currently-used-runners"))],
|
||||||
|
gridPos=GridPos(h=6, w=8, x=8, y=10),
|
||||||
|
alignment="center"
|
||||||
|
)
|
||||||
|
|
||||||
|
number_of_executions = BarGauge(
|
||||||
|
title="Number of Executions",
|
||||||
|
dataSource="Poseidon",
|
||||||
|
targets=[InfluxDBTarget(query=read_query("number-of-executions"))],
|
||||||
|
gridPos=GridPos(h=6, w=8, x=16, y=10),
|
||||||
|
allValues=True,
|
||||||
|
displayMode=GAUGE_DISPLAY_MODE_GRADIENT,
|
||||||
|
max=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
execution_duration = BarGauge(
|
||||||
|
title="Execution duration",
|
||||||
|
dataSource="Poseidon",
|
||||||
|
targets=[InfluxDBTarget(query=read_query("execution-duration"))],
|
||||||
|
gridPos=GridPos(h=11, w=8, x=0, y=16),
|
||||||
|
allValues=True,
|
||||||
|
displayMode=GAUGE_DISPLAY_MODE_GRADIENT,
|
||||||
|
format="ns",
|
||||||
|
max=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
executions_per_runner = BarGauge(
|
||||||
|
title="Executions per runner",
|
||||||
|
dataSource="Poseidon",
|
||||||
|
targets=[InfluxDBTarget(query=read_query("executions-per-runner"))],
|
||||||
|
gridPos=GridPos(h=11, w=8, x=8, y=16),
|
||||||
|
allValues=True,
|
||||||
|
displayMode=GAUGE_DISPLAY_MODE_GRADIENT,
|
||||||
|
max=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
executions_per_minute = BarGauge(
|
||||||
|
title="Executions per minute",
|
||||||
|
dataSource="Poseidon",
|
||||||
|
targets=[InfluxDBTarget(query=read_query("executions-per-minute"))],
|
||||||
|
gridPos=GridPos(h=11, w=8, x=16, y=16),
|
||||||
|
allValues=True,
|
||||||
|
displayMode=GAUGE_DISPLAY_MODE_GRADIENT,
|
||||||
|
max=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
general_row = RowPanel(
|
||||||
|
title="General",
|
||||||
|
collapsed=True,
|
||||||
|
gridPos=GridPos(h=1, w=24, x=0, y=0),
|
||||||
|
panels=[
|
||||||
|
requests_per_minute,
|
||||||
|
request_latency,
|
||||||
|
service_time,
|
||||||
|
current_environment_count,
|
||||||
|
currently_used_runners,
|
||||||
|
number_of_executions,
|
||||||
|
execution_duration,
|
||||||
|
executions_per_runner,
|
||||||
|
executions_per_minute
|
||||||
|
]
|
||||||
|
)
|
File diff suppressed because it is too large
Load Diff
5
deploy/grafana-dashboard/main.py
Normal file
5
deploy/grafana-dashboard/main.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
from grafanalib._gen import generate_dashboard
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
generate_dashboard(args=['-o', 'main.json', 'poseidon.dashboard.py'])
|
25
deploy/grafana-dashboard/poseidon.dashboard.py
Normal file
25
deploy/grafana-dashboard/poseidon.dashboard.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from grafanalib.core import Dashboard, Templating, Time
|
||||||
|
|
||||||
|
from availability_row import availability_row
|
||||||
|
from general_row import general_row
|
||||||
|
from runner_insights_row import runner_insights_row
|
||||||
|
from variables import stage_variable, environment_variable
|
||||||
|
|
||||||
|
dashboard = Dashboard(
|
||||||
|
title="Poseidon autogen",
|
||||||
|
timezone="browser",
|
||||||
|
panels=[
|
||||||
|
general_row,
|
||||||
|
runner_insights_row,
|
||||||
|
availability_row
|
||||||
|
],
|
||||||
|
templating=Templating(list=[
|
||||||
|
stage_variable,
|
||||||
|
environment_variable
|
||||||
|
]),
|
||||||
|
editable=True,
|
||||||
|
refresh="30s",
|
||||||
|
time=Time('now-6h', 'now'),
|
||||||
|
uid="P21Bh1SVk",
|
||||||
|
version=1
|
||||||
|
).auto_panel_ids()
|
@ -0,0 +1,19 @@
|
|||||||
|
import "date"
|
||||||
|
|
||||||
|
// The need for the date truncation is caused by Poseidon sending all influx events at the same time when starting up. This way not the last but a random value is displayed.
|
||||||
|
// Since in this startup process the highest value is the correct one, we choose the highest value of the last events.
|
||||||
|
|
||||||
|
data = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> group(columns: ["stage"], mode:"by")
|
||||||
|
|> map(fn: (r) => ({ r with _time: date.truncate(t: r._time, unit: 1m) }))
|
||||||
|
|
||||||
|
deploy_times = data
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["stage", "_time"])
|
||||||
|
|
||||||
|
join(tables: {key1: data, key2: deploy_times}, on: ["stage", "_time"], method: "inner")
|
||||||
|
|> max()
|
||||||
|
|> keep(columns: ["stage", "_value"])
|
||||||
|
|> rename(columns: {_value: ""})
|
@ -0,0 +1,8 @@
|
|||||||
|
from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_used_runners")
|
||||||
|
|> filter(fn: (r) => r["_field"] == "count")
|
||||||
|
|> group(columns: ["stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["_value", "stage"])
|
||||||
|
|> rename(columns: {_value: ""})
|
6
deploy/grafana-dashboard/queries/environment-ids.flux
Normal file
6
deploy/grafana-dashboard/queries/environment-ids.flux
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "duration")
|
||||||
|
|> keep(columns: ["environment_id"])
|
||||||
|
|> distinct(column: "environment_id")
|
||||||
|
|> keep(columns: ["_value"])
|
@ -0,0 +1,27 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "duration")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_/execute" or r["_measurement"] == "poseidon_/files" or r["_measurement"] == "poseidon_/websocket")
|
||||||
|
|> filter(fn: (r) => exists r.environment_id)
|
||||||
|
|> keep(columns: ["_time", "_value", "environment_id", "stage"])
|
||||||
|
|> aggregateWindow(every: v.windowPeriod, fn: mean)
|
||||||
|
|> map(fn: (r) => ({r with _value: r._value * 3.0})) // Each execution has three requests
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
28
deploy/grafana-dashboard/queries/execution-duration.flux
Normal file
28
deploy/grafana-dashboard/queries/execution-duration.flux
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "duration")
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_/execute" or r["_measurement"] == "poseidon_/files" or r["_measurement"] == "poseidon_/websocket")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> filter(fn: (r) => exists r.environment_id)
|
||||||
|
|> keep(columns: ["_value", "runner_id", "environment_id", "stage"])
|
||||||
|
|> group(columns: ["environment_id", "stage"])
|
||||||
|
|> mean()
|
||||||
|
|> map(fn: (r) => ({r with _value: r._value * 3.0})) // Each execution has three requests
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
@ -0,0 +1,27 @@
|
|||||||
|
import "strings"
|
||||||
|
import "date"
|
||||||
|
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: date.truncate(t: v.timeRangeStart, unit: 1m), stop: date.truncate(t: v.timeRangeStop, unit: 1m))
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_aws_executions" or r["_measurement"] == "poseidon_nomad_executions")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["environment_id", "stage"], mode:"by")
|
||||||
|
|> aggregateWindow(every: 1m, fn: count, createEmpty: true)
|
||||||
|
|> aggregateWindow(every: duration(v: int(v: v.windowPeriod) * 5), fn: mean, createEmpty: true)
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
28
deploy/grafana-dashboard/queries/executions-per-minute.flux
Normal file
28
deploy/grafana-dashboard/queries/executions-per-minute.flux
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import "date"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
data = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: date.truncate(t: v.timeRangeStart, unit: 1m), stop: date.truncate(t: v.timeRangeStop, unit: 1m))
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_aws_executions" or r["_measurement"] == "poseidon_nomad_executions")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["environment_id", "stage"], mode:"by")
|
||||||
|
|> aggregateWindow(every: 1m, fn: count, createEmpty: true)
|
||||||
|
|> keep(columns: ["_value", "environment_id", "stage"])
|
||||||
|
|> mean()
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: data, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
@ -0,0 +1,37 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
data = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|
||||||
|
runner_deletions = data
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_used_runners")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "deletion")
|
||||||
|
|> keep(columns: ["_time", "id", "stage"])
|
||||||
|
|> rename(columns: {id: "runner_id"})
|
||||||
|
|
||||||
|
executions = data
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_nomad_executions" or r["_measurement"] == "poseidon_aws_executions")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> keep(columns: ["_value", "environment_id", "runner_id"])
|
||||||
|
|> count()
|
||||||
|
|
||||||
|
result = join(tables: {key1: executions, key2: runner_deletions}, on: ["runner_id"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "_time", "environment_id", "stage"])
|
||||||
|
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
37
deploy/grafana-dashboard/queries/executions-per-runner.flux
Normal file
37
deploy/grafana-dashboard/queries/executions-per-runner.flux
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
data = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|
||||||
|
runner_deletions = data
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_used_runners")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "deletion")
|
||||||
|
|> keep(columns: ["id", "stage"])
|
||||||
|
|> rename(columns: {id: "runner_id"})
|
||||||
|
|
||||||
|
executions = data
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_nomad_executions" or r["_measurement"] == "poseidon_aws_executions")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> keep(columns: ["_value", "environment_id", "runner_id"])
|
||||||
|
|> count()
|
||||||
|
|
||||||
|
result = join(tables: {key1: executions, key2: runner_deletions}, on: ["runner_id"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "environment_id", "stage"])
|
||||||
|
|> mean()
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
25
deploy/grafana-dashboard/queries/idle-runner.flux
Normal file
25
deploy/grafana-dashboard/queries/idle-runner.flux
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
myWindowPeriod = if int(v: v.windowPeriod) >= int(v: 30s) then duration(v: int(v: v.windowPeriod) * 5) else v.windowPeriod
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_nomad_idle_runners" and r["_field"] == "count")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> keep(columns: ["_value", "_time", "environment_id", "stage"])
|
||||||
|
|> aggregateWindow(every: myWindowPeriod, fn: min, createEmpty: false)
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
26
deploy/grafana-dashboard/queries/number-of-executions.flux
Normal file
26
deploy/grafana-dashboard/queries/number-of-executions.flux
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_aws_executions" or r["_measurement"] == "poseidon_nomad_executions")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["environment_id", "stage"], mode:"by")
|
||||||
|
|> count()
|
||||||
|
|> keep(columns: ["_value", "environment_id", "stage"])
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["isDeletion"] == "false")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
25
deploy/grafana-dashboard/queries/prewarming-pool-size.flux
Normal file
25
deploy/grafana-dashboard/queries/prewarming-pool-size.flux
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_poolsize")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> group(columns: ["environment_id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["_value", "environment_id", "stage"])
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
25
deploy/grafana-dashboard/queries/request-body-size.flux
Normal file
25
deploy/grafana-dashboard/queries/request-body-size.flux
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
myWindowPeriod = if int(v: v.windowPeriod) > int(v: 1m) then duration(v: int(v: v.windowPeriod) * 10) else duration(v: int(v: v.windowPeriod) * 5)
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "request_size")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> keep(columns: ["_time", "_value", "environment_id", "stage"])
|
||||||
|
|> aggregateWindow(every: myWindowPeriod, fn: mean, createEmpty: false)
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
7
deploy/grafana-dashboard/queries/request-latency.flux
Normal file
7
deploy/grafana-dashboard/queries/request-latency.flux
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "duration")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> keep(columns: ["_time", "_value"])
|
||||||
|
|> aggregateWindow(every: v.windowPeriod, fn: mean)
|
17
deploy/grafana-dashboard/queries/requests-per-minute.flux
Normal file
17
deploy/grafana-dashboard/queries/requests-per-minute.flux
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import "date"
|
||||||
|
|
||||||
|
data = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: date.truncate(t: v.timeRangeStart, unit: 1m), stop: date.truncate(t: v.timeRangeStop, unit: 1m))
|
||||||
|
|> filter(fn: (r) => r._field == "duration")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> keep(columns: ["_time", "_value", "status"])
|
||||||
|
|
||||||
|
all = data |> set(key: "status", value: "all")
|
||||||
|
|
||||||
|
result = union(tables: [data, all])
|
||||||
|
|> aggregateWindow(every: 1m, fn: count, createEmpty: true)
|
||||||
|
|
||||||
|
if int(v: v.windowPeriod) > int(v: 1m)
|
||||||
|
then result |> aggregateWindow(every: duration(v: int(v: v.windowPeriod) * 2), fn: mean, createEmpty: true)
|
||||||
|
else result |> aggregateWindow(every: duration(v: int(v: v.windowPeriod) * 5), fn: mean, createEmpty: false)
|
29
deploy/grafana-dashboard/queries/runner-per-minute.flux
Normal file
29
deploy/grafana-dashboard/queries/runner-per-minute.flux
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import "strings"
|
||||||
|
import "date"
|
||||||
|
|
||||||
|
myWindowPeriod = if int(v: v.windowPeriod) > int(v: 2m) then duration(v: int(v: v.windowPeriod) * 30) else duration(v: int(v: v.windowPeriod) * 15)
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: date.truncate(t: v.timeRangeStart, unit: 1m), stop: date.truncate(t: v.timeRangeStop, unit: 1m))
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_used_runners")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["environment_id", "stage"], mode:"by")
|
||||||
|
|> aggregateWindow(every: 1m, fn: count, createEmpty: true)
|
||||||
|
|> keep(columns: ["_value", "_time", "environment_id", "stage"])
|
||||||
|
|> aggregateWindow(every: myWindowPeriod, fn: mean, createEmpty: true)
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
@ -0,0 +1,25 @@
|
|||||||
|
import "strings"
|
||||||
|
|
||||||
|
result = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_nomad_idle_runners")
|
||||||
|
|> filter(fn: (r) => r["_field"] == "startup_duration")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> keep(columns: ["_value", "_time", "environment_id", "stage"])
|
||||||
|
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|
||||||
|
|
||||||
|
envMapping = from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: -1y)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_environments")
|
||||||
|
|> filter(fn: (r) => r["event_type"] == "creation")
|
||||||
|
|> group(columns: ["id", "stage"], mode:"by")
|
||||||
|
|> last()
|
||||||
|
|> keep(columns: ["id", "image", "stage"])
|
||||||
|
|> rename(columns: {id: "environment_id"})
|
||||||
|
|> map(fn: (r) => ({ r with image: strings.trimPrefix(v: r.image, prefix: "openhpi/co_execenv_") + "(" + strings.substring(v: r.stage, start: 0, end: 1) + r.environment_id + ")" }))
|
||||||
|
|
||||||
|
join(tables: {key1: result, key2: envMapping}, on: ["environment_id", "stage"], method: "inner")
|
||||||
|
|> keep(columns: ["_value", "image", "_time"])
|
||||||
|
|> group(columns: ["image"], mode: "by")
|
||||||
|
|> rename(columns: {_value: ""})
|
7
deploy/grafana-dashboard/queries/service-time.flux
Normal file
7
deploy/grafana-dashboard/queries/service-time.flux
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "duration")
|
||||||
|
|> filter(fn: (r) => contains(value: r["environment_id"], set: ${environment_ids:json}))
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> keep(columns: ["_time", "_value", "_measurement"])
|
||||||
|
|> aggregateWindow(every: duration(v: int(v: v.windowPeriod) * 10), fn: (tables=<-, column) => tables |> quantile(q: 0.999))
|
6
deploy/grafana-dashboard/queries/stages.flux
Normal file
6
deploy/grafana-dashboard/queries/stages.flux
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_field"] == "duration")
|
||||||
|
|> keep(columns: ["stage"])
|
||||||
|
|> distinct(column: "stage")
|
||||||
|
|> keep(columns: ["_value"])
|
8
deploy/grafana-dashboard/queries/used-runner.flux
Normal file
8
deploy/grafana-dashboard/queries/used-runner.flux
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from(bucket: "poseidon/autogen")
|
||||||
|
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|
||||||
|
|> filter(fn: (r) => r["_measurement"] == "poseidon_used_runners")
|
||||||
|
|> filter(fn: (r) => r["_field"] == "count")
|
||||||
|
|> filter(fn: (r) => (not exists r.stage) or contains(value: r["stage"], set: ${stages:json}))
|
||||||
|
|> group(columns: ["stage"], mode:"by")
|
||||||
|
|> keep(columns: ["_value", "_time", "stage"])
|
||||||
|
|> aggregateWindow(every: duration(v: int(v: v.windowPeriod) * 5), fn: mean, createEmpty: false)
|
66
deploy/grafana-dashboard/runner_insights_row.py
Normal file
66
deploy/grafana-dashboard/runner_insights_row.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
from grafanalib.core import RowPanel, GridPos, Histogram, TimeSeries
|
||||||
|
from grafanalib.influxdb import InfluxDBTarget
|
||||||
|
|
||||||
|
from util import read_query
|
||||||
|
|
||||||
|
execution_duration_extra_json = {
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"unit": "ns"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
execution_duration = Histogram(
|
||||||
|
title="Execution duration",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("execution-duration-hist"))],
|
||||||
|
gridPos=GridPos(h=8, w=24, x=0, y=2),
|
||||||
|
bucketSize=100000000,
|
||||||
|
colorMode="palette-classic",
|
||||||
|
extraJson=execution_duration_extra_json
|
||||||
|
)
|
||||||
|
|
||||||
|
executions_per_runner = Histogram(
|
||||||
|
title="Executions per runner",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("executions-per-runner-hist"))],
|
||||||
|
gridPos=GridPos(h=10, w=11, x=0, y=10),
|
||||||
|
bucketSize=1,
|
||||||
|
colorMode="palette-classic",
|
||||||
|
)
|
||||||
|
|
||||||
|
executions_per_minute = TimeSeries(
|
||||||
|
title="Executions per minute",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("executions-per-minute-time"))],
|
||||||
|
gridPos=GridPos(h=10, w=13, x=11, y=10),
|
||||||
|
)
|
||||||
|
|
||||||
|
request_body_size = TimeSeries(
|
||||||
|
title="Request Body Size",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("request-body-size"))],
|
||||||
|
gridPos=GridPos(h=10, w=11, x=0, y=20),
|
||||||
|
scaleDistributionType="log",
|
||||||
|
unit="bytes",
|
||||||
|
)
|
||||||
|
|
||||||
|
runner_per_minute = TimeSeries(
|
||||||
|
title="Runner per minute",
|
||||||
|
dataSource='Poseidon',
|
||||||
|
targets=[InfluxDBTarget(query=read_query("runner-per-minute"))],
|
||||||
|
gridPos=GridPos(h=10, w=13, x=11, y=20),
|
||||||
|
)
|
||||||
|
|
||||||
|
runner_insights_row = RowPanel(
|
||||||
|
title="Runner Insights",
|
||||||
|
collapsed=True,
|
||||||
|
gridPos=GridPos(h=1, w=24, x=0, y=1),
|
||||||
|
panels=[
|
||||||
|
execution_duration,
|
||||||
|
executions_per_runner,
|
||||||
|
executions_per_minute,
|
||||||
|
request_body_size,
|
||||||
|
runner_per_minute
|
||||||
|
]
|
||||||
|
)
|
5
deploy/grafana-dashboard/util.py
Normal file
5
deploy/grafana-dashboard/util.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
def read_query(name):
|
||||||
|
with open("queries/" + name + ".flux", 'r') as file:
|
||||||
|
return file.read()
|
25
deploy/grafana-dashboard/variables.py
Normal file
25
deploy/grafana-dashboard/variables.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from grafanalib.core import Template
|
||||||
|
|
||||||
|
from util import read_query
|
||||||
|
|
||||||
|
stage_variable = Template(
|
||||||
|
dataSource="Poseidon",
|
||||||
|
label="Stage",
|
||||||
|
name="stages",
|
||||||
|
query=read_query("stages"),
|
||||||
|
refresh=1,
|
||||||
|
includeAll=True,
|
||||||
|
multi=True,
|
||||||
|
default="production"
|
||||||
|
)
|
||||||
|
|
||||||
|
environment_variable = Template(
|
||||||
|
dataSource="Poseidon",
|
||||||
|
label="Environment IDs",
|
||||||
|
name="environment_ids",
|
||||||
|
query=read_query("environment-ids"),
|
||||||
|
refresh=1,
|
||||||
|
includeAll=True,
|
||||||
|
multi=True,
|
||||||
|
default="$__all"
|
||||||
|
)
|
Reference in New Issue
Block a user