====== Grafana ====== ===== Установка ===== # (не работает, была смена ключей, надо какой то другой ключ импортировать, хз какой) # Добавляем ключи и репозиторий: apt install gnupg2 && wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add - echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list # После этого ставим из репозитория apt update && apt install grafana # После установки включаем и запускаем сервис systemctl enabled grafana-server && systemctl start grafana-server ==== Установка из файла ==== [[https://grafana.com/grafana/download|Тут можно посмотреть точную версию из числа доступных]], там же собсна и инструкция есть, пару команд (пользователя заводить вроде не обязательно): $ wget https://dl.grafana.com/oss/release/grafana_7.1.0_amd64.deb $ sudo dpkg -i grafana_7.1.0_amd64.deb ==== Настройка cli ==== Сервис работает на порту **3000**, учетка **admin**/**admin**\\ **Плагин для работы с Zabbix** # grafana-cli plugins install alexanderzobnin-zabbix-app :!: Путь к заббиксу- http://127.0.0.1/zabbix/api_jsonrpc.php\\ :!: Авторизация похоже через блок "Zabbix API details", блок "Auth" чет не работает\\ **Плагин для изображений в оповещениях**\\ grafana-cli plugins install grafana-image-renderer # иногда может не работать из за нехватки зависимосетей, проверить можно так: cd /var/lib/grafana/plugins/grafana-image-renderer ldd chrome-linux/chrome # Если есть отсутствующие библиотеки, установить хром вручную wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm sudo yum install ./google-chrome-stable_current_*.rpm ==== Настройка gui ==== Список элементов в переменной и исключение по регулярке\\ {{:linux:screenshot_6.jpg?direct&600|}}\\ Переменная, фильтруется другой переменной, прометеус\\ {{:linux:sdvcsdfvfdv.jpg?direct&600|}}\\
:!: Алерты function — функция для расчёта параметра. Возможные значения: * avg() — среднее значение; * min() — минимальное значение; * max() — максимальное значение; * sum() — сумма всех значений; * count() — количество значений; * last() — последнее значение; * median() — среднее значение по медиане; * diff() — разница между значениями; * percent_diff() — разница между значениями в процентах; * count_non_null() — количество значений, отличных от null;
==== Общее ==== **Единицы измерения в графиках**\\ Для данных есть два варианта, "**SI**" (в килобайте 1000 байт) и "**IEC**" (в килобайте 1024 байт)\\ **EIC**, когда в килобайте 1024 байт еще называют "кибибайтом", когда для расчета используется степень двойки (более традиционная форма для ИТ собсна), обозначается "**КиБ или KiB**"\\ ==== Repeat/Перечисление списка элементов ==== Можно сделать автоматический репит графиков, с подстановкой списка из переменной\\ Например переменная со списком хостов, чтобы автоматом создать графики для каждого хоста из списка, в json модели нужно сделать такую иерархию:\\ "summary" это агрегация, создавались в ручную, обычные графики, для перечисления создаем вложенную панель, с указанием "[$HOST]" в имени\\ {{:linux:wiki_0.jpg?direct&800|}} ===== Grafana Loki ===== Система сбора и обработки логов.\\ Для сбора метрик использует агент promtail и хранит данные в TSDB (Time Series Data Base, бд временных рядов).\\ Потребляет мало ресурсов благодаря неполной индексации. Интегрируется с разными системами в т.ч. с самой Grafana.\\ В **promtail** для выборки, хранения и парсинга данных используются метки, эти метки (по типу категорий) можно использовать для анализа/отображения.\\ ===== Alerting =====
:!: Шаблоны в новой графане # Указание шаблона в настройках канала оповещения {{ template "my_tempate" . }} # Колво алертов {{ len .Alerts.Firing }} {{ len .Alerts.Resolved }} # Перечислены оповещения и их статус {{ range .Alerts }} {{ .Status }}: {{ .Labels.alertname }} {{ end }} # Вложенные шаблоны: # определение шаблона {{ define "my_template" }} ... {{ end }} # Использование summary: {{ template "my_template" . }} # Удаление тегов {{ .Labels.Remove (stringSlice "alertname" "AlertGroup" "grafana_folder") }} {{ .Labels.alertname}} # Прием "with" {{ with .ValueString }} {{- . | reReplaceAll `\[\s` "" | reReplaceAll `\],\s` "\n" }} {{ end }} # Значения графика {{ .Values.max_mem }} {{ .ValueString }} {{- printf "%s - %s" .Labels.instance .Annotations.summary }} {{ printf "%.2f" .Labels "instance" }} {{ index $values printf "used_percent" | printf "%.1f" }} # Так же, хороший совет занести нужные данные в summary/description алерта, # затем в шаблоне обращаться к этому полю для получения данных # Поле Description в алерте: "instance={{ index $labels "instance" }} value={{ index $values "B" }}" # В шаблоне: {{ index .Annotations "description" }} # Переменная (?) {{- $name := default .Chart.Name .Values.nameOverride }}
:!: Примеры {{ define "my_template" -}} {{range .Alerts}} {{ .Values.used_percent }} {{ .Labels.alertname}} {{ index .Annotations "description" }} {{- end }} {{ end }} {{ define "print_alert" }} Summary: {{ .CommonAnnotations.Values }} {{ len .Alerts.Firing }} firing alert(s): {{ if .Alerts.Firing -}} {{ range .Alerts.Firing -}} {{ .Labels.Remove (stringSlice "alertname" "AlertGroup" "grafana_folder") }} {{ with .ValueString }} {{- . | reReplaceAll `\[\s` "" | reReplaceAll `\],\s` "\n" | reReplaceAll `\]` "" | reReplaceAll `var='[A-Z0-9a-z]+'\s` "" | reReplaceAll `labels=\{[A-Za-z0-9_\-\=\s\.:,]*\}\s` "" | reReplaceAll `metric='(.*)' ` " **$1**: " | reReplaceAll `value=([0-9\.]+)` "$1" }} {{ end }} {{- end }} {{- end }} {{ len .Alerts.Resolved }} resolved alert(s): {{ if .Alerts.Resolved -}} {{ range .Alerts.Resolved -}} {{ .Labels.Remove (stringSlice "alertname" "AlertGroup" "grafana_folder") }} {{ with .ValueString }} {{- . | reReplaceAll `\[\s` "" | reReplaceAll `\],\s` "\n" | reReplaceAll `\]` "" | reReplaceAll `var='[A-Z0-9a-z]+'\s` "" | reReplaceAll `labels=\{[A-Za-z0-9_\-\=\s\.:,]*\}\s` "" | reReplaceAll `metric='(.*)' ` " **$1**: " | reReplaceAll `value=([0-9\.]+)` "$1" }} {{ end }} {{- end }} {{- end }} {{ end }} {{ define "my_template" -}} {{ if .Alerts.Firing }} **{{ len .Alerts.Firing }} firing alert(s)** {{ template "summarize" .Alerts.Firing }} {{- end }} {{- if .Alerts.Resolved -}} **{{ len .Alerts.Resolved }} resolved alert(s)** {{ template "summarize" .Alerts.Resolved }} {{- end }} {{- end }} {{ define "summarize" -}} {{ range . }} {{- printf "%s - %s" .Labels.instance .Annotations.summary }} {{ end }} {{- end }} {{ define "mm_title_alert_composite" }} {{- if eq ((index .Alerts 0).Labels._alert_type_) "CLASSIC" }} {{- template "mm_title_alert_composite.classic" . }}{{ end }} {{- if eq ((index .Alerts 0).Labels._alert_type_) "MULTI" }} {{- template "mm_title_alert_composite.multi" . }}{{ end }}{{ end }} {{/*MULTI*/}} {{ define "mm_title_alert_composite.classic" }} {{if .Alerts.Firing }} [Alerting] {{end}}{{ if .Alerts.Resolved }} [OK] {{end}}{{ .CommonLabels.alertname }} {{ end }} {{/*MULTI*/}} {{ define "mm_title_alert_composite.multi" }} {{ if and (gt (len .Alerts.Firing) 0) (eq (len .Alerts.Resolved) 0) -}} [FIRING:{{ len .Alerts.Firing }}] {{ .CommonLabels.alertname }} {{ else }}{{ if and (gt (len .Alerts.Resolved) 0) (eq (len .Alerts.Firing) 0) -}} [RESOLVED] {{ .CommonLabels.alertname }} {{ else -}} [FIRING:{{ len .Alerts.Firing }},RESOLVED:{{ len .Alerts.Resolved }}] {{ .CommonLabels.alertname }} {{ end }}{{ end }}{{ end }}
:!: Еще пример Чтобы получить значение, в правиле, в поле "summary" например пишем переменные // после "$values" указывается выражение, можно выбрать любое {{ $labels.group }}: {{ $values.A.Value }} Пример шаблона {{ define "tg_body_alert_composite" -}} {{/* Стремление сделать один шаблон, тут разделение на типы алертов, с одним инстансом или с мульти, тип задается тегом, в правиле алерта */}} {{/* Примечательно, отступы здесь == отступы в сообщении, поэтому некоторые строки здесь выпадают из форматирования и прибиты к левой границе */}} {{- if eq ((index .Alerts 0).Labels._alert_type_) "CLASSIC" }} {{- template "tg_body_alert_composite.classic" . }} {{ else if eq ((index .Alerts 0).Labels._alert_type_) "MULTI" }} {{- template "tg_body_alert_composite.multi" . }} {{ else }} {{- (index .Alerts 0).Labels.alertname }} Label '_alert_type_' is not defined or invalid {{ end }} {{- end }} {{/* Тип алертов с одним инстансом (CLASSIC) */}} {{ define "tg_body_alert_composite.classic" -}} {{/* Возникновение алерта */}} {{- if .Alerts.Firing -}} {{ range .Alerts }}[Alerting] {{ .Labels.alertname }} {{ if .Annotations.description }} {{ .Annotations.description }} {{ end }} Metrics: {{- $value_of_metric := (.ValueString | reReplaceAll `.*metric='` "" | reReplaceAll `' labels.*` "") -}} {{ if ne $value_of_metric "Value" }} {{ with .ValueString }} {{- . | reReplaceAll `\[\s` "" | reReplaceAll `\],\s` "\n" | reReplaceAll `\]` "" | reReplaceAll `var='[A-Z0-9a-z]+'\s` "" | reReplaceAll `labels=\{[A-Za-z0-9_\-\=\s\.:,]*\}\s` "" | reReplaceAll `metric='(.*)' ` " $1: " | reReplaceAll `value=([0-9\.]+)` "$1" }} {{ end }} {{ else }} {{ with .ValueString }} {{- . | reReplaceAll `\[\s` "" | reReplaceAll `\],\s` "\n" | reReplaceAll `\]` "" | reReplaceAll `var='[A-Z0-9a-z]+'\s` "" | reReplaceAll `metric='.*'\s` "" | reReplaceAll `labels={.*=(.*)}` " $1: " | reReplaceAll `value=([0-9\.]+)` "$1" }} {{- end }} {{- end -}} {{- if .PanelURL }} Panel URL: {{ .PanelURL }} {{ end }} {{ end }} {{ end -}} {{/* Решение алерта */}} {{- if .Alerts.Resolved -}} {{ range .Alerts }}[OK] {{ .Labels.alertname }} {{ .Annotations.description }} {{- end }} {{- end -}} {{ end }} {{/* Тип алерта, когда много инстансов (MULTI) */}} {{ define "tg_body_alert_composite.multi" -}} {{ if (index .Alerts 0).Annotations.description -}} {{ (index .Alerts 0).Annotations.description -}} {{ end -}} {{/* Если состояние Firing, перечисляем переданные инстансы в подшаблоне "summarize_large" */}} {{- if .Alerts.Firing }} **{{ len .Alerts.Firing }} firing alert(s)** {{ template "tg_body_alert_composite.multi.summarize_large" .Alerts.Firing }} {{ end -}} {{/* Аналогично для состояния Resolve */}} {{- if .Alerts.Resolved }} **{{ len .Alerts.Resolved }} resolved alert(s)** {{- template "tg_body_alert_composite.multi.summarize_large" .Alerts.Resolved -}} {{ end -}} {{ if (index .Alerts 0).PanelURL }} Panel URL: {{ (index .Alerts 0).PanelURL }} {{- end }} {{- end }} {{/* Подшаблон для перечисления инстансов в цикле */}} {{ define "tg_body_alert_composite.multi.summarize_large" }} {{- range . -}} {{/* Пишем поле "summary" каждого инстанса т.к. в алерте там переменные с данными */}} {{ index .Annotations "summary" -}} {{ end -}} {{ end }}
===== Еще про алерты =====
:!: Параметры Собсна в простом случае, запросом получаем какие то данные, первое выражение для агрегации данных, второе для оценки состояния\\ {{:linux:graf_1.png?direct&600|}}\\ {{:linux:graf_0.png?direct&600|}}\\
:!:
:!:
===== API =====
:!: Auth curl http://admin:admin@localhost:3000/api/org
:!: silence Получить перечень curl -X 'GET' 'http://admin:admin@192.168.0.14:3000/api/alertmanager/grafana/api/v2/silences' \ -H 'accept: application/json' http://192.168.0.14:3000/api/alertmanager/grafana/api/v2/silences Создать новый curl -X 'POST' \ 'http://admin:admin@192.168.0.14:3000/api/alertmanager/grafana/api/v2/silences' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "comment": "comment_string", "createdBy": "automatic_rule", "startsAt": "2024-01-27T07:00:00.000Z", "endsAt": "2024-01-27T09:00:00.000Z", "matchers": [ { "isEqual": true, "isRegex": false, "name": "name", "value": "my_four_alert" } ] }'