github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/production/loki-mixin/dashboards/dashboard-utils.libsonnet (about) 1 local utils = import 'mixin-utils/utils.libsonnet'; 2 3 (import 'grafana-builder/grafana.libsonnet') { 4 // Override the dashboard constructor to add: 5 // - default tags, 6 // - some links that propagate the selected cluster. 7 dashboard(title, uid=''):: 8 super.dashboard(title, uid) + { 9 addRowIf(condition, row):: 10 if condition 11 then self.addRow(row) 12 else self, 13 addLog(name='logs'):: self { 14 templating+: { 15 list+: [ 16 { 17 hide: 0, 18 label: null, 19 name: name, 20 options: [], 21 query: 'loki', 22 refresh: 1, 23 regex: '', 24 type: 'datasource', 25 }, 26 ], 27 }, 28 }, 29 30 addCluster(multi=false):: 31 if multi then 32 self.addMultiTemplate('cluster', 'loki_build_info', $._config.per_cluster_label) 33 else 34 self.addTemplate('cluster', 'loki_build_info', $._config.per_cluster_label), 35 36 addNamespace(multi=false):: 37 if multi then 38 self.addMultiTemplate('namespace', 'loki_build_info{' + $._config.per_cluster_label + '=~"$cluster"}', 'namespace') 39 else 40 self.addTemplate('namespace', 'loki_build_info{' + $._config.per_cluster_label + '=~"$cluster"}', 'namespace'), 41 42 addTag():: 43 self + { 44 tags+: $._config.tags, 45 links+: [ 46 { 47 asDropdown: true, 48 icon: 'external link', 49 includeVars: true, 50 keepTime: true, 51 tags: $._config.tags, 52 targetBlank: false, 53 title: 'Loki Dashboards', 54 type: 'dashboards', 55 }, 56 ], 57 }, 58 59 addClusterSelectorTemplates(multi=true):: 60 local d = self { 61 tags: $._config.tags, 62 links: [ 63 { 64 asDropdown: true, 65 icon: 'external link', 66 includeVars: true, 67 keepTime: true, 68 tags: $._config.tags, 69 targetBlank: false, 70 title: 'Loki Dashboards', 71 type: 'dashboards', 72 }, 73 ], 74 }; 75 76 if multi then 77 d.addMultiTemplate('cluster', 'loki_build_info', $._config.per_cluster_label) 78 .addMultiTemplate('namespace', 'loki_build_info{' + $._config.per_cluster_label + '=~"$cluster"}', 'namespace') 79 else 80 d.addTemplate('cluster', 'loki_build_info', $._config.per_cluster_label) 81 .addTemplate('namespace', 'loki_build_info{' + $._config.per_cluster_label + '=~"$cluster"}', 'namespace'), 82 }, 83 84 jobMatcher(job):: 85 $._config.per_cluster_label + '=~"$cluster", job=~"($namespace)/%s"' % job, 86 87 namespaceMatcher():: 88 $._config.per_cluster_label + '=~"$cluster", namespace=~"$namespace"', 89 90 containerLabelMatcher(containerName):: 91 'label_name=~"%s.*"' % containerName, 92 93 logPanel(title, selector, datasource='$logs'):: { 94 title: title, 95 type: 'logs', 96 datasource: datasource, 97 targets: [ 98 { 99 refId: 'A', 100 expr: selector, 101 }, 102 ], 103 }, 104 fromNowPanel(title, metric_name):: 105 $.panel(title) + 106 { 107 type: 'stat', 108 title: title, 109 fieldConfig: { 110 defaults: { 111 custom: {}, 112 thresholds: { 113 mode: 'absolute', 114 steps: [ 115 { 116 color: 'green', 117 value: null, 118 }, 119 ], 120 }, 121 color: { 122 mode: 'fixed', 123 fixedColor: 'blue', 124 }, 125 unit: 'dateTimeFromNow', 126 }, 127 }, 128 targets: [ 129 { 130 expr: '%s{%s} * 1e3' % [metric_name, $.namespaceMatcher()], 131 refId: 'A', 132 instant: true, 133 format: 'time_series', 134 }, 135 ], 136 options: { 137 reduceOptions: { 138 values: false, 139 calcs: [ 140 'lastNotNull', 141 ], 142 fields: '', 143 }, 144 orientation: 'auto', 145 text: {}, 146 textMode: 'auto', 147 colorMode: 'value', 148 graphMode: 'area', 149 justifyMode: 'auto', 150 }, 151 datasource: '$datasource', 152 }, 153 CPUUsagePanel(title, matcher):: 154 $.panel(title) + 155 $.queryPanel([ 156 'sum by(pod) (rate(container_cpu_usage_seconds_total{%s, %s}[$__rate_interval]))' % [$.namespaceMatcher(), matcher], 157 'min(container_spec_cpu_quota{%s, %s} / container_spec_cpu_period{%s, %s})' % [$.namespaceMatcher(), matcher, $.namespaceMatcher(), matcher], 158 ], ['{{pod}}', 'limit']) + 159 { 160 seriesOverrides: [ 161 { 162 alias: 'limit', 163 color: '#E02F44', 164 fill: 0, 165 }, 166 ], 167 tooltip: { sort: 2 }, // Sort descending. 168 }, 169 containerCPUUsagePanel(title, containerName):: 170 self.CPUUsagePanel(title, 'container="%s"' % containerName), 171 172 memoryWorkingSetPanel(title, matcher):: 173 $.panel(title) + 174 $.queryPanel([ 175 // We use "max" instead of "sum" otherwise during a rolling update of a statefulset we will end up 176 // summing the memory of the old pod (whose metric will be stale for 5m) to the new pod. 177 'max by(pod) (container_memory_working_set_bytes{%s, %s})' % [$.namespaceMatcher(), matcher], 178 'min(container_spec_memory_limit_bytes{%s, %s} > 0)' % [$.namespaceMatcher(), matcher], 179 ], ['{{pod}}', 'limit']) + 180 { 181 seriesOverrides: [ 182 { 183 alias: 'limit', 184 color: '#E02F44', 185 fill: 0, 186 }, 187 ], 188 yaxes: $.yaxes('bytes'), 189 tooltip: { sort: 2 }, // Sort descending. 190 }, 191 containerMemoryWorkingSetPanel(title, containerName):: 192 self.memoryWorkingSetPanel(title, 'container="%s"' % containerName), 193 194 goHeapInUsePanel(title, jobName):: 195 $.panel(title) + 196 $.queryPanel( 197 'sum by(%s) (go_memstats_heap_inuse_bytes{%s})' % [$._config.per_instance_label, $.jobMatcher(jobName)], 198 '{{%s}}' % $._config.per_instance_label 199 ) + 200 { 201 yaxes: $.yaxes('bytes'), 202 tooltip: { sort: 2 }, // Sort descending. 203 }, 204 205 filterNodeDisk(matcher):: 206 ||| 207 ignoring(%s) group_right() (label_replace(count by(%s, %s, device) (container_fs_writes_bytes_total{%s, %s, device!~".*sda.*"}), "device", "$1", "device", "/dev/(.*)") * 0) 208 ||| % [$._config.per_instance_label, $._config.per_node_label, $._config.per_instance_label, $.namespaceMatcher(), matcher], 209 filterNodeDiskContainer(containerName):: 210 self.filterNodeDisk('container="%s"' % containerName), 211 212 newStatPanel(queries, legends='', unit='percentunit', decimals=1, thresholds=[], instant=false, novalue=''):: 213 super.queryPanel(queries, legends) + { 214 type: 'stat', 215 targets: [ 216 target { 217 instant: instant, 218 interval: '', 219 220 // Reset defaults from queryPanel(). 221 format: null, 222 intervalFactor: null, 223 step: null, 224 } 225 for target in super.targets 226 ], 227 fieldConfig: { 228 defaults: { 229 decimals: decimals, 230 noValue: novalue, 231 unit: unit, 232 }, 233 overrides: [], 234 }, 235 }, 236 237 containerDiskSpaceUtilizationPanel(title, containerName):: 238 $.panel(title) + 239 $.queryPanel('max by(persistentvolumeclaim) (kubelet_volume_stats_used_bytes{%s} / kubelet_volume_stats_capacity_bytes{%s}) and count by(persistentvolumeclaim) (kube_persistentvolumeclaim_labels{%s,%s})' % [$.namespaceMatcher(), $.namespaceMatcher(), $.namespaceMatcher(), $.containerLabelMatcher(containerName)], '{{persistentvolumeclaim}}') + 240 { yaxes: $.yaxes('percentunit') }, 241 }