From d7d738fd3631b3cea246daa956a3ca5297899acc Mon Sep 17 00:00:00 2001 From: abolfazl1381 Date: Mon, 16 Dec 2024 20:27:06 +0330 Subject: [PATCH] feat(grafana): add grafana alertmanager --- app/main.py | 3 +- app/media/MyGrafana/alertmanager.yml | 16 +++++ .../grafana_datasources/alertmanager.yml | 21 +++++++ .../grafana_datasources/elasticsearch.yml | 14 +++++ app/media/grafana_datasources/loki.yml | 19 ++++++ app/media/grafana_datasources/mimir.yml | 16 +++++ app/media/grafana_datasources/mysql.yml | 20 ++++++ app/media/grafana_datasources/postgresql.yml | 19 ++++++ app/media/grafana_datasources/prometheus.yml | 23 +++++++ app/media/grafana_datasources/tempo.yml | 25 ++++++++ app/models/__init__.py | 3 +- app/models/alert_managers_models.py | 28 +++++++++ app/routes/grafana_data_sources.py | 17 ++++++ .../grafana_data_sources/alertmanager.py | 61 +++++++++++++++++++ 14 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 app/media/MyGrafana/alertmanager.yml create mode 100644 app/media/grafana_datasources/alertmanager.yml create mode 100644 app/media/grafana_datasources/elasticsearch.yml create mode 100644 app/media/grafana_datasources/loki.yml create mode 100644 app/media/grafana_datasources/mimir.yml create mode 100644 app/media/grafana_datasources/mysql.yml create mode 100644 app/media/grafana_datasources/postgresql.yml create mode 100644 app/media/grafana_datasources/prometheus.yml create mode 100644 app/media/grafana_datasources/tempo.yml create mode 100644 app/models/alert_managers_models.py create mode 100644 app/routes/grafana_data_sources.py create mode 100644 app/template_generators/grafana_data_sources/alertmanager.py diff --git a/app/main.py b/app/main.py index 1980475c..5068cfdf 100644 --- a/app/main.py +++ b/app/main.py @@ -5,4 +5,5 @@ from app.routes.jcasc import * from app.routes.docker import * from app.routes.jenkins import * -from app.routes.gitlab import * \ No newline at end of file +from app.routes.gitlab import * +from app.routes.grafana_data_sources import * \ No newline at end of file diff --git a/app/media/MyGrafana/alertmanager.yml b/app/media/MyGrafana/alertmanager.yml new file mode 100644 index 00000000..5459b49f --- /dev/null +++ b/app/media/MyGrafana/alertmanager.yml @@ -0,0 +1,16 @@ +apiVersion: 1 +datasources: +- name: string + uid: string + type: alertmanager + url: string + access: proxy + orgId: 1 + jsonData: + implementation: cortex + handleGrafanaManagedAlerts: true + editable: true + basicAuth: true + basicAuthUser: string + secureJsonData: + basicAuthPassword: string diff --git a/app/media/grafana_datasources/alertmanager.yml b/app/media/grafana_datasources/alertmanager.yml new file mode 100644 index 00000000..7835d885 --- /dev/null +++ b/app/media/grafana_datasources/alertmanager.yml @@ -0,0 +1,21 @@ +apiVersion: 1 + +datasources: + - name: Alertmanager + uid: alertmanager + type: alertmanager + url: http://localhost:9093 + access: proxy + orgId: 1 + jsonData: + # Valid options for implementation include mimir, cortex and prometheus + implementation: [prometheus|cortex|mimir] + # Whether or not Grafana should send alert instances to this Alertmanager + handleGrafanaManagedAlerts: [false|true] + + editable: [true|false] + # optionally + basicAuth: true + basicAuthUser: my_user + secureJsonData: + basicAuthPassword: test_password diff --git a/app/media/grafana_datasources/elasticsearch.yml b/app/media/grafana_datasources/elasticsearch.yml new file mode 100644 index 00000000..91a45312 --- /dev/null +++ b/app/media/grafana_datasources/elasticsearch.yml @@ -0,0 +1,14 @@ +apiVersion: 1 + +datasources: + - name: elasticsearch-v7-filebeat + type: elasticsearch + access: proxy + url: http://localhost:9200 + editable: [true|false] + jsonData: + index: '[filebeat-]YYYY.MM.DD' + interval: Daily + timeField: '@timestamp' + logMessageField: message + logLevelField: fields.level diff --git a/app/media/grafana_datasources/loki.yml b/app/media/grafana_datasources/loki.yml new file mode 100644 index 00000000..0dc90212 --- /dev/null +++ b/app/media/grafana_datasources/loki.yml @@ -0,0 +1,19 @@ +apiVersion: 1 + +datasources: + - name: Loki + uid: loki + type: loki + orgId: 1 + access: proxy + editable: [true|false] + url: http://localhost:3100 + jsonData: + timeout: 60 + maxLines: 1000 + + # optionally + basicAuth: true + basicAuthUser: my_user + secureJsonData: + basicAuthPassword: test_password diff --git a/app/media/grafana_datasources/mimir.yml b/app/media/grafana_datasources/mimir.yml new file mode 100644 index 00000000..ebbb9c8c --- /dev/null +++ b/app/media/grafana_datasources/mimir.yml @@ -0,0 +1,16 @@ +apiVersion: 1 + +datasources: + - name: Mimir + uid: mimir + type: prometheus + access: proxy + orgId: 1 + url: http://mimir-nginx.mimir.svc.cluster.local/prometheus + editable: [true|false] + version: 1 + jsonData: + httpHeaderName1: "X-Scope-OrgID" + alertmanagerUid: "alertmanager" + secureJsonData: + httpHeaderValue1: "pods" diff --git a/app/media/grafana_datasources/mysql.yml b/app/media/grafana_datasources/mysql.yml new file mode 100644 index 00000000..fc5a6fe5 --- /dev/null +++ b/app/media/grafana_datasources/mysql.yml @@ -0,0 +1,20 @@ +apiVersion: 1 + +datasources: + - name: MySQL + type: mysql + url: localhost:3306 + user: grafana + editable: [true|false] + jsonData: + tlsAuth: true + tlsSkipVerify: true + database: grafana + maxOpenConns: 100 # Grafana v5.4+ + maxIdleConns: 100 # Grafana v5.4+ + maxIdleConnsAuto: true # Grafana v9.5.1+ + connMaxLifetime: 14400 # Grafana v5.4+ + secureJsonData: + password: ${GRAFANA_MYSQL_PASSWORD} + tlsClientCert: ${GRAFANA_TLS_CLIENT_CERT} + tlsCACert: ${GRAFANA_TLS_CA_CERT} diff --git a/app/media/grafana_datasources/postgresql.yml b/app/media/grafana_datasources/postgresql.yml new file mode 100644 index 00000000..bdd8b891 --- /dev/null +++ b/app/media/grafana_datasources/postgresql.yml @@ -0,0 +1,19 @@ +apiVersion: 1 + +datasources: + - name: Postgres + type: postgres + url: localhost:5432 + user: grafana # Database user’s login/username + editable: [true|false] + secureJsonData: + password: 'Password!' + jsonData: + database: grafana + sslmode: 'disable' # disable/require/verify-ca/verify-full + maxOpenConns: 100 # Grafana v5.4+ + maxIdleConns: 100 # Grafana v5.4+ + maxIdleConnsAuto: true # Grafana v9.5.1+ + connMaxLifetime: 14400 # Grafana v5.4+ + postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10 + timescaledb: false diff --git a/app/media/grafana_datasources/prometheus.yml b/app/media/grafana_datasources/prometheus.yml new file mode 100644 index 00000000..657a1c98 --- /dev/null +++ b/app/media/grafana_datasources/prometheus.yml @@ -0,0 +1,23 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + uid: prometheus + type: prometheus + access: proxy + # Access mode - proxy (server in the UI) or direct (browser in the UI). + url: http://localhost:9090 + editable: [true|false] + jsonData: + httpMethod: POST + manageAlerts: true + prometheusType: Prometheus + prometheusVersion: 2.44.0 + cacheLevel: 'High' + disableRecordingRules: false + incrementalQueryOverlapWindow: 10m + exemplarTraceIdDestinations: + # Field with internal link pointing to data source in Grafana. + # datasourceUid value can be anything, but it should be unique across all defined data source uids. + - datasourceUid: my_jaeger_uid + name: traceID diff --git a/app/media/grafana_datasources/tempo.yml b/app/media/grafana_datasources/tempo.yml new file mode 100644 index 00000000..cb8794ce --- /dev/null +++ b/app/media/grafana_datasources/tempo.yml @@ -0,0 +1,25 @@ +apiVersion: 1 + +datasources: + - name: Tempo + type: tempo + access: proxy + orgId: 1 + url: http://tempo-query-frontend.tempo.svc.cluster.local:3100 + basicAuth: false + version: 1 + editable: true + apiVersion: 1 + uid: tempo + jsonData: + httpMethod: GET + tracesToLogsV2: # If you are going to link your tracing data with logs, configure <> + datasourceUid: 'loki' + spanStartTimeShift: '-2m' + spanEndTimeShift: '2m' + filterByTraceID: true + filterBySpanID: true + serviceMap: # If you are going to add serviceGraph feature to tempo, configure <> + datasourceUid: 'Mimir-OtelMetrics-Tenant' + nodeGraph: # If you are going to add nodeGraph feature to tempo, enable <> + enabled: true diff --git a/app/models/__init__.py b/app/models/__init__.py index a529a87f..a819a217 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -6,4 +6,5 @@ from .compose_models import * from .docker_installation_models import * from .jenkins import * -from .gitlab_models import * \ No newline at end of file +from .gitlab_models import * +from .alert_managers_models import * \ No newline at end of file diff --git a/app/models/alert_managers_models.py b/app/models/alert_managers_models.py new file mode 100644 index 00000000..29539ccc --- /dev/null +++ b/app/models/alert_managers_models.py @@ -0,0 +1,28 @@ +from typing import List, Optional +from pydantic import BaseModel, validator, ValidationError + +class BasicAuth(BaseModel): + basicAuthUser:str + basicAuthPassword:str + + +class AlertManagerInput(BaseModel): + name:str + url:str + uid:str + implementation:str + + handleGrafanaManagedAlerts:bool = True + editable: bool = True + basic_auth:Optional[BasicAuth] + + @validator("implementation") + def validator_implementation(cls,value): + valid = ['prometheus','cortex','mimir'] + if value not in valid: + raise ValueError(f"implementation must be in {valid}") + return value + + + + diff --git a/app/routes/grafana_data_sources.py b/app/routes/grafana_data_sources.py new file mode 100644 index 00000000..9a7c22a7 --- /dev/null +++ b/app/routes/grafana_data_sources.py @@ -0,0 +1,17 @@ +from app.app_instance import app +from app.models import (AlertManagerInput,Output) +from app.template_generators.grafana_data_sources.alertmanager import alert_manager_template +import shutil +import os + +@app.post("/api/grafana/alertmanager") +async def alertmanager_template(request:AlertManagerInput) -> Output: + + dir = 'app/media/MyGrafana' + if os.path.exists(dir): + shutil.rmtree(dir) + + alert_manager_template(request) + + return Output(output='output') + diff --git a/app/template_generators/grafana_data_sources/alertmanager.py b/app/template_generators/grafana_data_sources/alertmanager.py new file mode 100644 index 00000000..694783e7 --- /dev/null +++ b/app/template_generators/grafana_data_sources/alertmanager.py @@ -0,0 +1,61 @@ +import yaml +import os + +def alert_manager_template(input): + if input.basic_auth is None: + json_template = { + "apiVersion": 1, + "datasources": [ + { + "name": input.name, + "uid": input.uid, + "type": "alertmanager", + "url": input.url, + "access": "proxy", + "orgId": 1, + "jsonData": { + "implementation": input.implementation, + "handleGrafanaManagedAlerts": input.handleGrafanaManagedAlerts + }, + "editable": input.editable, + + } + ] + } + dir = "app/media/MyGrafana" + os.makedirs(dir) + os.path.join(dir, 'alertmanager.yml') + + file=open("app/media/MyGrafana/alertmanager.yml","w") + yaml.dump(json_template,file,default_flow_style=False,sort_keys=False) + + else: + json_template = { + "apiVersion": 1, + "datasources": [ + { + "name": input.name, + "uid": input.uid, + "type": "alertmanager", + "url": input.url, + "access": "proxy", + "orgId": 1, + "jsonData": { + "implementation": input.implementation, + "handleGrafanaManagedAlerts": input.handleGrafanaManagedAlerts + }, + "editable": input.editable, + "basicAuth": True, + "basicAuthUser": input.basic_auth.basicAuthUser, + "secureJsonData": { + "basicAuthPassword": input.basic_auth.basicAuthPassword + } + } + ] + } + dir = "app/media/MyGrafana" + os.makedirs(dir) + os.path.join(dir, 'alertmanager.yml') + + file=open("app/media/MyGrafana/alertmanager.yml","w") + yaml.dump(json_template,file,default_flow_style=False,sort_keys=False)