Skip to content

Commit

Permalink
Merge pull request grafana/cortex-jsonnet#272 from grafana/add-slow-q…
Browse files Browse the repository at this point in the history
…ueries-dashboard

Add slow queries dashboard
  • Loading branch information
pracucci authored Mar 16, 2021
2 parents d281bd6 + 419eaba commit c616398
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 0 deletions.
1 change: 1 addition & 0 deletions jsonnet/mimir-mixin/dashboards.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
(import 'dashboards/alertmanager.libsonnet') +
(import 'dashboards/scaling.libsonnet') +
(import 'dashboards/writes.libsonnet') +
(import 'dashboards/slow-queries.libsonnet') +

(if std.member($._config.storage_engine, 'blocks')
then
Expand Down
185 changes: 185 additions & 0 deletions jsonnet/mimir-mixin/dashboards/slow-queries.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
local utils = import 'mixin-utils/utils.libsonnet';

(import 'dashboard-utils.libsonnet') {
'cortex-slow-queries.json':
($.dashboard('Cortex / Slow Queries') + { uid: 'e6f3091e29d2636e3b8393447e925668' })
.addClusterSelectorTemplates(false)
.addRow(
$.row('')
.addPanel(
{
title: 'Slow queries',
type: 'table',
datasource: '${lokidatasource}',

// Query logs from Loki.
targets: [
{
// Filter out the remote read endpoint.
expr: '{cluster=~"$cluster",namespace=~"$namespace",name="query-frontend"} |= "query stats" != "/api/v1/read" | logfmt | org_id=~"${tenant_id}" | response_time > ${min_duration}',
instant: false,
legendFormat: '',
range: true,
refId: 'A',
},
],

// Use Grafana transformations to display fields in a table.
transformations: [
{
// Convert labels to fields.
id: 'labelsToFields',
options: {},
},
{
// Compute the query time range.
id: 'calculateField',
options: {
alias: 'Time range',
mode: 'binary',
binary: {
left: 'param_end',
operator: '-',
reducer: 'sum',
right: 'param_start',
},
reduce: { reducer: 'sum' },
replaceFields: false,
},
},
{
id: 'organize',
options: {
// Hide fields we don't care.
local hiddenFields = ['caller', 'cluster', 'container', 'host', 'id', 'job', 'level', 'line', 'method', 'msg', 'name', 'namespace', 'param_end', 'param_start', 'param_time', 'path', 'pod', 'pod_template_hash', 'query_wall_time_seconds', 'stream', 'traceID', 'tsNs'],

excludeByName: {
[field]: true
for field in hiddenFields
},

// Order fields.
local orderedFields = ['ts', 'org_id', 'param_query', 'Time range', 'param_step', 'response_time'],

indexByName: {
[orderedFields[i]]: i
for i in std.range(0, std.length(orderedFields) - 1)
},

// Rename fields.
renameByName: {
org_id: 'Tenant ID',
param_query: 'Query',
param_step: 'Step',
response_time: 'Duration',
},
},
},
],

fieldConfig: {
// Configure overrides to nicely format field values.
overrides: [
{
matcher: { id: 'byName', options: 'Time range' },
properties: [
{
id: 'mappings',
value: [
{
from: '',
id: 1,
text: 'Instant query',
to: '',
type: 1,
value: '0',
},
],
},
{ id: 'unit', value: 's' },
],
},
{
matcher: { id: 'byName', options: 'Step' },
properties: [{ id: 'unit', value: 's' }],
},
],
},
},
)
)
+ {
templating+: {
list+: [
// Add the Loki datasource.
{
type: 'datasource',
name: 'lokidatasource',
label: 'Logs datasource',
query: 'loki',
hide: 0,
includeAll: false,
multi: false,
},
// Add a variable to configure the min duration.
{
local defaultValue = '5s',

type: 'textbox',
name: 'min_duration',
label: 'Min duration',
hide: 0,
options: [
{
selected: true,
text: defaultValue,
value: defaultValue,
},
],
current: {
// Default value.
selected: true,
text: defaultValue,
value: defaultValue,
},
query: defaultValue,
},
// Add a variable to configure the tenant to filter on.
{
local defaultValue = '.*',

type: 'textbox',
name: 'tenant_id',
label: 'Tenant ID',
hide: 0,
options: [
{
selected: true,
text: defaultValue,
value: defaultValue,
},
],
current: {
// Default value.
selected: true,
text: defaultValue,
value: defaultValue,
},
query: defaultValue,
},
],
},
} + {
templating+: {
list: [
// Do not allow to include all clusters/namespaces otherwise this dashboard
// risks to explode because it shows resources per pod.
l + (if (l.name == 'cluster' || l.name == 'namespace') then { includeAll: false } else {})
for l in super.list
],
},
} + {
// No auto-refresh by default.
refresh: '',
},
}

0 comments on commit c616398

Please sign in to comment.