{
  "version": 8,
  "dashboardId": "api-metrics",
  "title": "接口监控 (QPS / 耗时 / 错误率)",
  "description": "app-server 接口 QPS、P50/P95/P99 耗时、5xx 错误率。数据流 app_requests。",
  "role": "",
  "tabs": [
    {
      "tabId": "default",
      "name": "Default",
      "panels": [
        {
          "id": "panel_qps",
          "type": "line",
          "title": "各接口 每分钟请求数 (QPS 源)",
          "description": "",
          "config": {
            "show_legends": true,
            "legends_position": null,
            "decimals": 2.0,
            "axis_border_show": false,
            "base_map": null,
            "map_view": null
          },
          "queryType": "sql",
          "queries": [
            {
              "query": "SELECT histogram(_timestamp, '1 minute') as ts, route, count(*) as reqs FROM app_requests GROUP BY ts, route ORDER BY ts",
              "vrlFunctionQuery": "",
              "customQuery": true,
              "fields": {
                "stream": "app_requests",
                "stream_type": "logs",
                "x": [
                  {
                    "label": "ts",
                    "alias": "ts",
                    "column": "ts",
                    "color": null,
                    "sortBy": "ASC"
                  }
                ],
                "y": [
                  {
                    "label": "reqs",
                    "alias": "reqs",
                    "column": "reqs",
                    "color": null
                  }
                ],
                "z": [],
                "breakdown": [
                  {
                    "label": "route",
                    "alias": "route",
                    "column": "route",
                    "color": null
                  }
                ],
                "filter": {
                  "filterType": "group",
                  "logicalOperator": "AND",
                  "conditions": []
                }
              },
              "config": {
                "promql_legend": "",
                "layer_type": "scatter",
                "weight_fixed": 1.0
              }
            }
          ],
          "layout": {
            "x": 0,
            "y": 0,
            "w": 24,
            "h": 9,
            "i": 1
          }
        },
        {
          "id": "panel_p95",
          "type": "line",
          "title": "各接口 P95 耗时 (ms)",
          "description": "",
          "config": {
            "show_legends": true,
            "legends_position": null,
            "decimals": 2.0,
            "axis_border_show": false,
            "base_map": null,
            "map_view": null
          },
          "queryType": "sql",
          "queries": [
            {
              "query": "SELECT histogram(_timestamp, '1 minute') as ts, route, approx_percentile_cont(duration_ms, 0.95) as p95_ms FROM app_requests GROUP BY ts, route ORDER BY ts",
              "vrlFunctionQuery": "",
              "customQuery": true,
              "fields": {
                "stream": "app_requests",
                "stream_type": "logs",
                "x": [
                  {
                    "label": "ts",
                    "alias": "ts",
                    "column": "ts",
                    "color": null,
                    "sortBy": "ASC"
                  }
                ],
                "y": [
                  {
                    "label": "p95_ms",
                    "alias": "p95_ms",
                    "column": "p95_ms",
                    "color": null
                  }
                ],
                "z": [],
                "breakdown": [
                  {
                    "label": "route",
                    "alias": "route",
                    "column": "route",
                    "color": null
                  }
                ],
                "filter": {
                  "filterType": "group",
                  "logicalOperator": "AND",
                  "conditions": []
                }
              },
              "config": {
                "promql_legend": "",
                "layer_type": "scatter",
                "weight_fixed": 1.0
              }
            }
          ],
          "layout": {
            "x": 24,
            "y": 0,
            "w": 24,
            "h": 9,
            "i": 2
          }
        },
        {
          "id": "panel_pctl",
          "type": "table",
          "title": "各接口 耗时分位 P50/P95/P99 (ms)",
          "description": "",
          "config": {
            "show_legends": true,
            "legends_position": null,
            "decimals": 2.0,
            "axis_border_show": false,
            "base_map": null,
            "map_view": null
          },
          "queryType": "sql",
          "queries": [
            {
              "query": "SELECT route, approx_percentile_cont(duration_ms,0.5) as p50, approx_percentile_cont(duration_ms,0.95) as p95, approx_percentile_cont(duration_ms,0.99) as p99, count(*) as cnt FROM app_requests GROUP BY route ORDER BY p95 DESC",
              "vrlFunctionQuery": "",
              "customQuery": true,
              "fields": {
                "stream": "app_requests",
                "stream_type": "logs",
                "x": [
                  {
                    "label": "route",
                    "alias": "route",
                    "column": "route",
                    "color": null
                  }
                ],
                "y": [
                  {
                    "label": "p50",
                    "alias": "p50",
                    "column": "p50",
                    "color": null
                  },
                  {
                    "label": "p95",
                    "alias": "p95",
                    "column": "p95",
                    "color": null
                  },
                  {
                    "label": "p99",
                    "alias": "p99",
                    "column": "p99",
                    "color": null
                  },
                  {
                    "label": "cnt",
                    "alias": "cnt",
                    "column": "cnt",
                    "color": null
                  }
                ],
                "z": [],
                "breakdown": [],
                "filter": {
                  "filterType": "group",
                  "logicalOperator": "AND",
                  "conditions": []
                }
              },
              "config": {
                "promql_legend": "",
                "layer_type": "scatter",
                "weight_fixed": 1.0
              }
            }
          ],
          "layout": {
            "x": 0,
            "y": 9,
            "w": 24,
            "h": 9,
            "i": 3
          }
        },
        {
          "id": "panel_err",
          "type": "table",
          "title": "各接口 错误率 (5xx %)",
          "description": "",
          "config": {
            "show_legends": true,
            "legends_position": null,
            "decimals": 2.0,
            "axis_border_show": false,
            "base_map": null,
            "map_view": null
          },
          "queryType": "sql",
          "queries": [
            {
              "query": "SELECT route, count(*) FILTER (WHERE status >= 500) * 100.0 / count(*) as err_pct, count(*) as cnt FROM app_requests GROUP BY route ORDER BY err_pct DESC",
              "vrlFunctionQuery": "",
              "customQuery": true,
              "fields": {
                "stream": "app_requests",
                "stream_type": "logs",
                "x": [
                  {
                    "label": "route",
                    "alias": "route",
                    "column": "route",
                    "color": null
                  }
                ],
                "y": [
                  {
                    "label": "err_pct",
                    "alias": "err_pct",
                    "column": "err_pct",
                    "color": null
                  },
                  {
                    "label": "cnt",
                    "alias": "cnt",
                    "column": "cnt",
                    "color": null
                  }
                ],
                "z": [],
                "breakdown": [],
                "filter": {
                  "filterType": "group",
                  "logicalOperator": "AND",
                  "conditions": []
                }
              },
              "config": {
                "promql_legend": "",
                "layer_type": "scatter",
                "weight_fixed": 1.0
              }
            }
          ],
          "layout": {
            "x": 24,
            "y": 9,
            "w": 24,
            "h": 9,
            "i": 4
          }
        }
      ]
    }
  ],
  "variables": {
    "list": []
  }
}