{
  "__inputs": [
    {
      "name": "DS_LOKI",
      "label": "Loki",
      "description": "Loki datasource",
      "type": "datasource",
      "pluginId": "loki",
      "pluginName": "Loki"
    }
  ],
  "__requires": [
    { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "11.0.0" },
    { "type": "datasource", "id": "loki", "name": "Loki", "version": "1.0.0" },
    { "type": "panel", "id": "stat", "name": "Stat", "version": "" },
    { "type": "panel", "id": "timeseries", "name": "Time series", "version": "" },
    { "type": "panel", "id": "piechart", "name": "Pie chart", "version": "" },
    { "type": "panel", "id": "bargauge", "name": "Bar gauge", "version": "" },
    { "type": "panel", "id": "logs", "name": "Logs", "version": "" }
  ],
  "title": "Xpeditis — Logs & KPIs",
  "uid": "xpeditis-logs-kpis",
  "description": "Logs applicatifs, KPIs HTTP, temps de réponse et erreurs — Backend & Frontend",
  "tags": ["xpeditis", "logs", "monitoring", "backend"],
  "timezone": "Europe/Paris",
  "refresh": "30s",
  "schemaVersion": 39,
  "time": { "from": "now-1h", "to": "now" },
  "timepicker": {},
  "graphTooltip": 1,
  "editable": true,
  "version": 1,
  "links": [],
  "annotations": { "list": [] },

  "templating": {
    "list": [
      {
        "name": "service",
        "label": "Service",
        "type": "query",
        "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
        "query": "label_values(service)",
        "refresh": 2,
        "includeAll": true,
        "allValue": ".+",
        "multi": true,
        "current": {},
        "hide": 0,
        "sort": 1
      },
      {
        "name": "level",
        "label": "Niveau",
        "type": "query",
        "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
        "query": "label_values(level)",
        "refresh": 2,
        "includeAll": true,
        "allValue": ".+",
        "multi": true,
        "current": {},
        "hide": 0,
        "sort": 1
      }
    ]
  },

  "panels": [
    {
      "id": 1,
      "title": "Requêtes totales",
      "type": "stat",
      "gridPos": { "x": 0, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
        "orientation": "auto",
        "textMode": "auto",
        "colorMode": "background",
        "graphMode": "none",
        "justifyMode": "center"
      },
      "fieldConfig": {
        "defaults": {
          "color": { "mode": "fixed", "fixedColor": "#10183A" },
          "unit": "short",
          "thresholds": { "mode": "absolute", "steps": [{ "color": "#10183A", "value": null }] }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum(count_over_time({service=~\"$service\"} | json | req_method != \"\" [$__range]))",
          "legendFormat": "Requêtes",
          "instant": true,
          "range": false,
          "refId": "A"
        }
      ]
    },

    {
      "id": 2,
      "title": "Erreurs (error + fatal)",
      "type": "stat",
      "gridPos": { "x": 6, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
        "orientation": "auto",
        "textMode": "auto",
        "colorMode": "background",
        "graphMode": "none",
        "justifyMode": "center"
      },
      "fieldConfig": {
        "defaults": {
          "color": { "mode": "fixed", "fixedColor": "red" },
          "unit": "short",
          "thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }] }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum(count_over_time({service=~\"$service\", level=~\"error|fatal\"} [$__range]))",
          "legendFormat": "Erreurs",
          "instant": true,
          "range": false,
          "refId": "A"
        }
      ]
    },

    {
      "id": 3,
      "title": "Warnings",
      "type": "stat",
      "gridPos": { "x": 12, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
        "orientation": "auto",
        "textMode": "auto",
        "colorMode": "background",
        "graphMode": "none",
        "justifyMode": "center"
      },
      "fieldConfig": {
        "defaults": {
          "color": { "mode": "fixed", "fixedColor": "orange" },
          "unit": "short",
          "thresholds": { "mode": "absolute", "steps": [{ "color": "orange", "value": null }] }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum(count_over_time({service=~\"$service\", level=\"warn\"} [$__range]))",
          "legendFormat": "Warnings",
          "instant": true,
          "range": false,
          "refId": "A"
        }
      ]
    },

    {
      "id": 4,
      "title": "Taux d'erreur",
      "type": "stat",
      "gridPos": { "x": 18, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
        "orientation": "auto",
        "textMode": "auto",
        "colorMode": "background",
        "graphMode": "none",
        "justifyMode": "center"
      },
      "fieldConfig": {
        "defaults": {
          "unit": "percentunit",
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "green", "value": null },
              { "color": "orange", "value": 0.01 },
              { "color": "red", "value": 0.05 }
            ]
          },
          "color": { "mode": "thresholds" }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum(rate({service=~\"$service\", level=~\"error|fatal\"} [$__interval])) / sum(rate({service=~\"$service\"} [$__interval]))",
          "legendFormat": "Taux d'erreur",
          "instant": false,
          "range": true,
          "refId": "A"
        }
      ]
    },

    {
      "id": 5,
      "title": "Trafic par service (req/s)",
      "type": "timeseries",
      "gridPos": { "x": 0, "y": 4, "w": 12, "h": 8 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "list", "placement": "bottom" }
      },
      "fieldConfig": {
        "defaults": {
          "unit": "reqps",
          "color": { "mode": "palette-classic" },
          "custom": {
            "lineWidth": 2,
            "fillOpacity": 10,
            "gradientMode": "opacity",
            "spanNulls": false
          }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum by(service) (rate({service=~\"$service\"} | json | req_method != \"\" [$__interval]))",
          "legendFormat": "{{service}}",
          "instant": false,
          "range": true,
          "refId": "A"
        }
      ]
    },

    {
      "id": 6,
      "title": "Erreurs & Warnings dans le temps",
      "type": "timeseries",
      "gridPos": { "x": 12, "y": 4, "w": 12, "h": 8 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "list", "placement": "bottom" }
      },
      "fieldConfig": {
        "defaults": {
          "unit": "short",
          "color": { "mode": "palette-classic" },
          "custom": {
            "lineWidth": 2,
            "fillOpacity": 15,
            "gradientMode": "opacity"
          }
        },
        "overrides": [
          {
            "matcher": { "id": "byName", "options": "error" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "red" } }]
          },
          {
            "matcher": { "id": "byName", "options": "fatal" },
            "properties": [
              { "id": "color", "value": { "mode": "fixed", "fixedColor": "dark-red" } }
            ]
          },
          {
            "matcher": { "id": "byName", "options": "warn" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } }]
          }
        ]
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum by(level) (rate({service=~\"$service\", level=~\"error|fatal|warn\"} [$__interval]))",
          "legendFormat": "{{level}}",
          "instant": false,
          "range": true,
          "refId": "A"
        }
      ]
    },

    {
      "id": 7,
      "title": "Temps de réponse Backend",
      "type": "timeseries",
      "gridPos": { "x": 0, "y": 12, "w": 16, "h": 8 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "list", "placement": "bottom" }
      },
      "fieldConfig": {
        "defaults": {
          "unit": "ms",
          "color": { "mode": "palette-classic" },
          "custom": {
            "lineWidth": 2,
            "fillOpacity": 8,
            "gradientMode": "opacity"
          },
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "green", "value": null },
              { "color": "orange", "value": 500 },
              { "color": "red", "value": 1000 }
            ]
          }
        },
        "overrides": [
          {
            "matcher": { "id": "byName", "options": "Pire cas (1% des requêtes)" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "red" } }]
          },
          {
            "matcher": { "id": "byName", "options": "Lent (5% des requêtes)" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } }]
          },
          {
            "matcher": { "id": "byName", "options": "Temps médian (requête typique)" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#34CCCD" } }]
          }
        ]
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "quantile_over_time(0.50, {service=\"backend\"} | json | responseTime > 0 | unwrap responseTime [$__interval])",
          "legendFormat": "Temps médian (requête typique)",
          "instant": false,
          "range": true,
          "refId": "A"
        },
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "quantile_over_time(0.95, {service=\"backend\"} | json | responseTime > 0 | unwrap responseTime [$__interval])",
          "legendFormat": "Lent (5% des requêtes)",
          "instant": false,
          "range": true,
          "refId": "B"
        },
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "quantile_over_time(0.99, {service=\"backend\"} | json | responseTime > 0 | unwrap responseTime [$__interval])",
          "legendFormat": "Pire cas (1% des requêtes)",
          "instant": false,
          "range": true,
          "refId": "C"
        }
      ]
    },

    {
      "id": 8,
      "title": "Répartition par niveau de log",
      "type": "piechart",
      "gridPos": { "x": 16, "y": 12, "w": 8, "h": 8 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "pieType": "donut",
        "tooltip": { "mode": "single" },
        "legend": { "displayMode": "list", "placement": "bottom", "values": ["percent"] }
      },
      "fieldConfig": {
        "defaults": { "unit": "short", "color": { "mode": "palette-classic" } },
        "overrides": [
          {
            "matcher": { "id": "byName", "options": "error" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "red" } }]
          },
          {
            "matcher": { "id": "byName", "options": "fatal" },
            "properties": [
              { "id": "color", "value": { "mode": "fixed", "fixedColor": "dark-red" } }
            ]
          },
          {
            "matcher": { "id": "byName", "options": "warn" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } }]
          },
          {
            "matcher": { "id": "byName", "options": "info" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "#34CCCD" } }]
          },
          {
            "matcher": { "id": "byName", "options": "debug" },
            "properties": [{ "id": "color", "value": { "mode": "fixed", "fixedColor": "blue" } }]
          }
        ]
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum by(level) (count_over_time({service=~\"$service\", level=~\"$level\"} [$__range]))",
          "legendFormat": "{{level}}",
          "instant": true,
          "range": false,
          "refId": "A"
        }
      ]
    },

    {
      "id": 9,
      "title": "Codes HTTP (5m)",
      "type": "bargauge",
      "gridPos": { "x": 0, "y": 20, "w": 12, "h": 8 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "orientation": "horizontal",
        "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
        "displayMode": "gradient",
        "valueMode": "color",
        "showUnfilled": true,
        "minVizWidth": 10,
        "minVizHeight": 10
      },
      "fieldConfig": {
        "defaults": {
          "unit": "short",
          "color": { "mode": "palette-classic" },
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "green", "value": null },
              { "color": "orange", "value": 1 }
            ]
          }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "sum by(status_code) (count_over_time({service=\"backend\"} | json | res_statusCode != \"\" | label_format status_code=\"{{res_statusCode}}\" [$__range]))",
          "legendFormat": "HTTP {{status_code}}",
          "instant": true,
          "range": false,
          "refId": "A"
        }
      ]
    },

    {
      "id": 10,
      "title": "Top erreurs par contexte NestJS",
      "type": "bargauge",
      "gridPos": { "x": 12, "y": 20, "w": 12, "h": 8 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "orientation": "horizontal",
        "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
        "displayMode": "gradient",
        "showUnfilled": true
      },
      "fieldConfig": {
        "defaults": {
          "unit": "short",
          "color": { "mode": "fixed", "fixedColor": "red" },
          "thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }] }
        },
        "overrides": []
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "topk(10, sum by(context) (count_over_time({service=\"backend\", level=~\"error|fatal\"} | json | context != \"\" [$__range])  ))",
          "legendFormat": "{{context}}",
          "instant": true,
          "range": false,
          "refId": "A"
        }
      ]
    },

    {
      "id": 11,
      "title": "Logs — Backend",
      "type": "logs",
      "gridPos": { "x": 0, "y": 28, "w": 24, "h": 12 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "dedupStrategy": "none",
        "enableLogDetails": true,
        "prettifyLogMessage": true,
        "showCommonLabels": false,
        "showLabels": false,
        "showTime": true,
        "sortOrder": "Descending",
        "wrapLogMessage": false
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "{service=\"backend\", level=~\"$level\"}",
          "legendFormat": "",
          "instant": false,
          "range": true,
          "refId": "A",
          "maxLines": 500
        }
      ]
    },

    {
      "id": 12,
      "title": "Logs — Frontend",
      "type": "logs",
      "gridPos": { "x": 0, "y": 40, "w": 24, "h": 10 },
      "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
      "options": {
        "dedupStrategy": "none",
        "enableLogDetails": true,
        "prettifyLogMessage": false,
        "showCommonLabels": false,
        "showLabels": false,
        "showTime": true,
        "sortOrder": "Descending",
        "wrapLogMessage": false
      },
      "targets": [
        {
          "datasource": { "type": "loki", "uid": "${DS_LOKI}" },
          "expr": "{service=\"frontend\"}",
          "legendFormat": "",
          "instant": false,
          "range": true,
          "refId": "A",
          "maxLines": 200
        }
      ]
    }
  ]
}
