Grafana dashboard: 4 - APM Downstream Dependencies
Description: This map shows all services sending traces and the interactions between them. Each arrow represents a service calling a specific operation in another service. The legend in the arrows includes the requests per second for that interaction.  If you are downsampling your traces before sending them to Promscale, then the number of requests per second will not be accurate but you'll be able to see how it compares to other operations.

APM Overview dashboard offered by Promscale on top of traces by leveraging SQL and TimescaleDB capabilities.

This dashboard contains:

1. **Map of Downstream Dependencies**  representing nodes and edges here nodes are services and edges are connections between services. This panel represents all downstream dependencies for the selected service and operation. 

{
  "__inputs": [
    {
      "name": "DS_PROMSCALE-SQL",
      "label": "Promscale-SQL",
      "description": "TimescaleDB as PostgreSQL data source",
      "type": "datasource",
      "pluginId": "postgres",
      "pluginName": "PostgreSQL"
    }
  ],
  "__elements": [],
  "__requires": [
    {
      "type": "grafana",
      "id": "grafana",
      "name": "Grafana",
      "version": "8.5.2"
    },
    {
      "type": "panel",
      "id": "nodeGraph",
      "name": "Node Graph",
      "version": ""
    },
    {
      "type": "datasource",
      "id": "postgres",
      "name": "PostgreSQL",
      "version": "1.0.0"
    }
  ],
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": {
          "type": "datasource",
          "uid": "grafana"
        },
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "target": {
          "limit": 100,
          "matchAny": false,
          "tags": [],
          "type": "dashboard"
        },
        "type": "dashboard"
      }
    ]
  },
  "editable": true,
  "fiscalYearStartMonth": 0,
  "graphTooltip": 0,
  "id": null,
  "iteration": 1652003329264,
  "links": [
    {
      "asDropdown": false,
      "icon": "external link",
      "includeVars": true,
      "keepTime": true,
      "tags": [
        "promscale",
        "apm"
      ],
      "targetBlank": false,
      "title": "Menu",
      "tooltip": "",
      "type": "dashboards",
      "url": ""
    }
  ],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "postgres",
        "uid": "${DS_PROMSCALE-SQL}"
      },
      "description": "A.K.A. \"Who do I call?\"",
      "gridPos": {
        "h": 20,
        "w": 24,
        "x": 0,
        "y": 0
      },
      "id": 2,
      "targets": [
        {
          "datasource": {
            "type": "postgres",
            "uid": "${DS_PROMSCALE-SQL}"
          },
          "format": "table",
          "group": [],
          "metricColumn": "none",
          "rawQuery": true,
          "rawSql": "WITH RECURSIVE x AS\n(\n    SELECT\n        trace_id,\n        span_id,\n        parent_span_id,\n        service_name,\n        span_name\n    FROM ps_trace.span\n    WHERE start_time > NOW() - INTERVAL '10 minutes'\n    AND service_name = '${service}'\n    AND span_name = '${operation}'\n    UNION ALL\n    SELECT\n        s.trace_id,\n        s.span_id,\n        s.parent_span_id,\n        s.service_name,\n        s.span_name\n    FROM x\n    INNER JOIN ps_trace.span s\n    ON (x.trace_id = s.trace_id\n    AND x.span_id = s.parent_span_id)\n    AND s.start_time > NOW() - INTERVAL '10 minutes'\n)\nSELECT\n    md5(service_name || '-' || span_name) as id,\n    span_name as title,\n    service_name as \"subTitle\",\n    count(*) as \"mainStat\"\nFROM x\nGROUP BY service_name, span_name",
          "refId": "A",
          "select": [
            [
              {
                "params": [
                  "span_duration_ms"
                ],
                "type": "column"
              }
            ]
          ],
          "table": "event",
          "timeColumn": "\"time\"",
          "timeColumnType": "timestamp",
          "where": [
            {
              "name": "$__timeFilter",
              "params": [],
              "type": "macro"
            }
          ]
        },
        {
          "datasource": {
            "type": "postgres",
            "uid": "${DS_PROMSCALE-SQL}"
          },
          "format": "table",
          "group": [],
          "hide": false,
          "metricColumn": "none",
          "rawQuery": true,
          "rawSql": "WITH RECURSIVE x AS\n(\n    SELECT\n        trace_id,\n        span_id,\n        parent_span_id,\n        service_name,\n        span_name,\n        null::text as id,\n        null::text as source,\n        null::text as target\n    FROM ps_trace.span\n    WHERE start_time > NOW() - INTERVAL '10 minutes'\n    AND service_name = '${service}'\n    AND span_name = '${operation}'\n    UNION ALL\n    SELECT\n        s.trace_id,\n        s.span_id,\n        s.parent_span_id,\n        s.service_name,\n        s.span_name,\n        md5(s.service_name || '-' || s.span_name || '-' || x.service_name || '-' || x.span_name) as id,\n        md5(x.service_name || '-' || x.span_name) as source,\n        md5(s.service_name || '-' || s.span_name) as target\n    FROM x\n    INNER JOIN ps_trace.span s\n    ON (x.trace_id = s.trace_id\n    AND x.span_id = s.parent_span_id)\n    AND s.start_time > NOW() - INTERVAL '10 minutes'\n)\nSELECT DISTINCT\n    x.id,\n    x.source,\n    x.target \nFROM x\nWHERE id is not null",
          "refId": "B",
          "select": [
            [
              {
                "params": [
                  "span_duration_ms"
                ],
                "type": "column"
              }
            ]
          ],
          "table": "event",
          "timeColumn": "\"time\"",
          "timeColumnType": "timestamp",
          "where": [
            {
              "name": "$__timeFilter",
              "params": [],
              "type": "macro"
            }
          ]
        }
      ],
      "title": "Map of Downstream Dependencies (last 10 minutes)",
      "transformations": [],
      "type": "nodeGraph"
    }
  ],
  "schemaVersion": 36,
  "style": "dark",
  "tags": [
    "promscale",
    "apm"
  ],
  "templating": {
    "list": [
      {
        "allValue": "ALL",
        "current": {},
        "datasource": {
          "type": "postgres",
          "uid": "${DS_PROMSCALE-SQL}"
        },
        "definition": "SELECT DISTINCT service_name FROM ps_trace.span WHERE start_time > NOW() - INTERVAL '10 minutes'\n",
        "hide": 0,
        "includeAll": false,
        "label": "Service",
        "multi": false,
        "name": "service",
        "options": [],
        "query": "SELECT DISTINCT service_name FROM ps_trace.span WHERE start_time > NOW() - INTERVAL '10 minutes'\n",
        "refresh": 1,
        "regex": "",
        "skipUrlSync": false,
        "sort": 1,
        "type": "query"
      },
      {
        "allValue": "ALL",
        "current": {},
        "datasource": {
          "type": "postgres",
          "uid": "${DS_PROMSCALE-SQL}"
        },
        "definition": "SELECT DISTINCT span_name FROM ps_trace.span WHERE service_name = ${service:sqlstring} AND start_time > NOW() - INTERVAL '10 minutes'\n)",
        "hide": 0,
        "includeAll": false,
        "label": "Operation",
        "multi": false,
        "name": "operation",
        "options": [],
        "query": "SELECT DISTINCT span_name FROM ps_trace.span WHERE service_name = ${service:sqlstring} AND start_time > NOW() - INTERVAL '10 minutes'\n",
        "refresh": 2,
        "regex": "",
        "skipUrlSync": false,
        "sort": 1,
        "type": "query"
      }
    ]
  },
  "time": {
    "from": "now-6h",
    "to": "now"
  },
  "timepicker": {
    "hidden": true
  },
  "timezone": "",
  "title": "4 - APM Downstream Dependencies",
  "uid": "SDJmJvPnz",
  "version": 1,
  "weekStart": "",
  "gnetId": 16245,
  "description": "This map shows all services sending traces and the interactions between them. Each arrow represents a service calling a specific operation in another service. The legend in the arrows includes the requests per second for that interaction.  If you are downsampling your traces before sending them to Promscale, then the number of requests per second will not be accurate but you'll be able to see how it compares to other operations."
}