#!/bin/bash # Script pour générer automatiquement les dashboards Grafana # basés sur les modules définis dans les variables d'environnement # Fonction pour charger les variables d'environnement load_env_files() { local env_files=(".env.secrets" ".env" ".env.auto" ".env.post") for env_file in "${env_files[@]}"; do if [ -f "$env_file" ]; then echo "📄 Chargement de $env_file..." source "$env_file" 2>/dev/null || true else echo "⚠️ Fichier $env_file non trouvé, ignoré." fi done } # Fonction pour générer un dashboard de base pour un service generate_service_dashboard() { local SERVICE="$1" local SERVICE_NAME="$2" local DASHBOARD_TYPE="$3" echo "🔧 Génération du dashboard pour $SERVICE ($SERVICE_NAME)" # Créer le répertoire si nécessaire mkdir -p "4NK_modules/grafana/dashboards" # Générer le nom du fichier local DASHBOARD_FILE="4NK_modules/grafana/dashboards/${SERVICE_NAME}.json" # Générer le contenu JSON du dashboard cat > "$DASHBOARD_FILE" << EOF { "annotations": { "list": [] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": null, "links": [], "liveNow": false, "panels": [ { "datasource": { "type": "loki", "uid": "loki" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "vis": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, "id": 1, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom" }, "tooltip": { "mode": "single" } }, "targets": [ { "datasource": { "type": "loki", "uid": "loki" }, "editorMode": "code", "expr": "sum(rate({container=\"\$${SERVICE}_DOCKER_NAME\"} |= \"INFO\" [5m])) by (container)", "queryType": "", "refId": "A" } ], "title": "Logs INFO - $SERVICE_NAME", "type": "timeseries" }, { "datasource": { "type": "loki", "uid": "loki" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "vis": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, "id": 2, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom" }, "tooltip": { "mode": "single" } }, "targets": [ { "datasource": { "type": "loki", "uid": "loki" }, "editorMode": "code", "expr": "sum(rate({container=\"\$${SERVICE}_DOCKER_NAME\"} |= \"ERROR\" [5m])) by (container)", "queryType": "", "refId": "A" } ], "title": "Erreurs - $SERVICE_NAME", "type": "timeseries" }, { "datasource": { "type": "loki", "uid": "loki" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 0, "y": 8 }, "id": 3, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "10.0.0", "targets": [ { "datasource": { "type": "loki", "uid": "loki" }, "editorMode": "code", "expr": "count_over_time({container=\"\$${SERVICE}_DOCKER_NAME\"} |= \"ERROR\" [1h])", "queryType": "", "refId": "A" } ], "title": "Erreurs (1h)", "type": "stat" }, { "datasource": { "type": "loki", "uid": "loki" }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 12 }, "id": 4, "options": { "showTime": false, "showLabels": false, "showCommonLabels": false, "wrapLogMessage": false, "prettifyLogMessage": false, "enableLogDetails": true, "dedupStrategy": "none", "sortOrder": "Descending" }, "targets": [ { "datasource": { "type": "loki", "uid": "loki" }, "editorMode": "code", "expr": "{container=\"\$${SERVICE}_DOCKER_NAME\"} |= \"ERROR\" | line_format \"{{.timestamp}} - {{.message}}\"", "queryType": "", "refId": "A" } ], "title": "Logs d'Erreur - $SERVICE_NAME", "type": "logs" } ], "refresh": "5s", "schemaVersion": 37, "style": "dark", "tags": [ "$SERVICE_NAME", "auto-generated" ], "templating": { "list": [] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "$SERVICE_NAME - Monitoring", "uid": "$(echo $SERVICE_NAME | tr '[:upper:]' '[:lower:]' | tr '_' '-')", "version": 1, "weekStart": "" } EOF echo "✅ Dashboard généré: $DASHBOARD_FILE" } # Fonction pour générer un dashboard overview generate_overview_dashboard() { echo "🔧 Génération du dashboard overview" mkdir -p "4NK_modules/grafana/dashboards" cat > "4NK_modules/grafana/dashboards/services-overview.json" << EOF { "annotations": { "list": [] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": null, "links": [], "liveNow": false, "panels": [ { "datasource": { "type": "loki", "uid": "loki" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "vis": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 0 }, "id": 1, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom" }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "loki", "uid": "loki" }, "editorMode": "code", "expr": "sum by (container) (count_over_time({container=~\"\$${BITCOIN}_DOCKER_NAME|\$${BLINDBIT_ORACLE}_DOCKER_NAME|\$${SDK_RELAY}_DOCKER_NAME|\$${SDK_STORAGE}_DOCKER_NAME|\$${IHM_CLIENT}_DOCKER_NAME|\$${LECOFFRE_FRONT}_DOCKER_NAME\"} |= \"ERROR\" [5m]))", "queryType": "", "refId": "A" } ], "title": "Erreurs par Service (5 dernières minutes)", "type": "timeseries" } ], "refresh": "30s", "schemaVersion": 36, "style": "dark", "tags": ["overview", "auto-generated"], "templating": { "list": [] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Services Overview - Auto Generated", "uid": "services-overview-auto", "version": 1, "weekStart": "" } EOF echo "✅ Dashboard overview généré" } # Fonction pour générer le fichier promtail.yml generate_promtail_config() { echo "🔧 Génération du fichier promtail.yml" # Créer le répertoire si nécessaire mkdir -p "4NK_modules/promtail" # Générer le fichier promtail.yml cat > "4NK_modules/promtail/promtail.yml" << 'EOF' server: http_listen_port: $PROMTAIL_PORT grpc_listen_port: 0 positions: filename: /tmp/positions.yaml clients: - url: $LOKI_URL/loki/api/v1/push scrape_configs: EOF # Générer les configurations pour chaque service for SERVICE_VAR in "${SERVICES[@]}"; do # Ajouter la configuration pour ce service cat >> "4NK_modules/promtail/promtail.yml" << EOF # ${SERVICE_VAR} Logs - job_name: \$${SERVICE_VAR}_DOCKER_NAME static_configs: - targets: - localhost labels: job: \$${SERVICE_VAR}_DOCKER_NAME service: \$${SERVICE_VAR}_DOCKER_NAME __path__: \$${SERVICE_VAR}_LOGS_DIR/*.log EOF done # Ajouter la configuration Docker cat >> "4NK_modules/promtail/promtail.yml" << 'EOF' # Docker Container Logs - job_name: docker docker_sd_configs: - host: unix:///var/run/docker.sock refresh_interval: 5s filters: - name: label values: ["com.centurylinklabs.watchtower.enable=true"] relabel_configs: - source_labels: ['__meta_docker_container_name'] regex: '/?(.*)' target_label: 'container_name' - source_labels: ['__meta_docker_container_log_stream'] target_label: 'logstream' - source_labels: ['__meta_docker_container_label_logging_job_name'] target_label: 'job' EOF echo "✅ Configuration promtail.yml générée" } # Fonction pour générer les fichiers de configuration logrotate generate_logrotate_configs() { echo "🔧 Génération des configurations logrotate" # Créer le répertoire si nécessaire mkdir -p "logrotade" # Générer les configurations pour chaque service for SERVICE_VAR in "${SERVICES[@]}"; do local CONFIG_FILE="logrotade/${SERVICE_VAR,,}.conf" echo "📄 Génération de $CONFIG_FILE" cat > "$CONFIG_FILE" << EOF \$${SERVICE_VAR}_LOGS_DIR/*.log { daily missingok rotate 7 compress delaycompress notifempty create 644 root root postrotate # Redémarrer le service si nécessaire docker restart \$${SERVICE_VAR}_DOCKER_NAME 2>/dev/null || true endscript } EOF done echo "✅ Configurations logrotate générées pour ${#SERVICES[@]} services" } # Fonction pour déterminer le type de service get_service_type() { local service="$1" case "$service" in "BITCOIN"|"BLINDBIT_ORACLE") echo "blockchain" ;; "SDK_RELAY"|"SDK_STORAGE") echo "sdk" ;; "IHM_CLIENT"|"LECOFFRE_FRONT") echo "frontend" ;; "4NK_MINER") echo "mining" ;; "REDIS"|"POSTGRESQL"|"LOKI"|"PROMTAIL"|"GRAFANA") echo "infrastructure" ;; *) echo "service" ;; esac } # Fonction pour déterminer le nom du dashboard get_dashboard_name() { local service="$1" case "$service" in "BITCOIN") echo "bitcoin" ;; "BLINDBIT_ORACLE") echo "blindbit-oracle" ;; "SDK_RELAY") echo "sdk-relay" ;; "SDK_STORAGE") echo "sdk-storage" ;; "IHM_CLIENT") echo "ihm-client" ;; "LECOFFRE_FRONT") echo "lecoffre-front" ;; "4NK_MINER") echo "4nk-miner" ;; "4NK_CERTIFICATOR") echo "4nk-certificator" ;; "4NK_WEB_STATUS") echo "4nk-web-status" ;; "4NK_VAULT") echo "4nk-vault" ;; *) echo "${service,,}" ;; # Convertir en minuscules esac } # Fonction principale main() { echo "🚀 GÉNÉRATION AUTOMATIQUE DES DASHBOARDS GRAFANA" echo "==================================================" # Charger les variables d'environnement load_env_files # Créer le répertoire des dashboards mkdir -p "4NK_modules/grafana/dashboards" echo "📋 Génération des dashboards pour ${#SERVICES[@]} services..." # Générer les dashboards en boucle depuis la variable SERVICES for SERVICE_VAR in "${SERVICES[@]}"; do # Déterminer le nom du dashboard et le type de service local DASHBOARD_NAME=$(get_dashboard_name "$SERVICE_VAR") local SERVICE_TYPE=$(get_service_type "$SERVICE_VAR") echo "🔄 Traitement de $SERVICE_VAR -> $DASHBOARD_NAME ($SERVICE_TYPE)" # Générer le dashboard pour ce service generate_service_dashboard "$SERVICE_VAR" "$DASHBOARD_NAME" "$SERVICE_TYPE" done # Générer le dashboard overview echo "🔄 Génération du dashboard overview..." generate_overview_dashboard # Générer la configuration Promtail echo "🔄 Génération de la configuration Promtail..." generate_promtail_config # Générer les configurations logrotate echo "🔄 Génération des configurations logrotate..." generate_logrotate_configs echo "" echo "✅ GÉNÉRATION TERMINÉE !" echo "📁 Dashboards générés dans: 4NK_modules/grafana/dashboards/" echo "📁 Configuration Promtail: 4NK_modules/promtail/promtail.yml" echo "📁 Configurations logrotate: logrotade/*.conf" echo "🔧 Les dashboards utilisent les variables d'environnement pour les noms de containers" echo "📊 Services traités: ${#SERVICES[@]}" } # Exécuter le script principal main "$@"