Skip to content

A basic monitoring based on the Pokkadot log level='info'

Notifications You must be signed in to change notification settings

ksmnetwork/kusama-promtail

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 

Repository files navigation

KUSAMA Validator Simple Monitoring

Simple logging for KUSAMA and POLKADOT Validator based on the level="info" logs by the application.

KUSAMA GRAFANA LOKI PROMTAIL

  • KUSAMA is WILD!
  • Grafana is a feature-rich metrics dashboard and graph editor
  • Loki is the logging engine.
  • Promtail sends logs to Loki

Distributor ID: Debian Description: Debian GNU/Linux 10 (buster) Release: 10 Codename: buster

Installation

If you already running Grafana just add Loki as a Data Source and install the Promtail agent on the KUSAMA/PolkaDOT Host 'Step 3'.

Grafana dashboard can be installed from https://grafana.com/grafana/dashboards/14899

Dashboard Preview

KSMNETWORK

  • Logs are obtained by the scrapping job "journal" from the systemd-journal,
  • The relabel_configs will provide you with a simple "unit" & "hostname" labels where you can separate multi-nodes by hostname
  • as a unique value. Most of the logs are dropped since this monitoring is focused only on the PolkaDOT default logs level="info"
  • but you can always drop more if you detect some.. by adding a match stage to the pipeline with a selector unit
  • '{job="systemd-journal", unit="<UNIT.NAME>"}'
  - match:
      selector: '{job="systemd-journal", unit="init.scope"}'
      action: drop
      drop_counter_reason: promtail_logs
  • Logging... well regex ".*", shall explain everything.
  • Grafana Dashboard is quite simple as it looks, more like the host terminal with some extra visual statistics,
  • don't forget the "{{hostname}}" the label is quite helpful on multi-node setups.
  • Query limit configuration in the setting by default is 1000 if you want to adjust it, go do it!
  • Labels set at the queries and then they are transformed to fields, filtered by names to suite the graphs needs.

Simple query for Unit Service Logs

=: exactly equal
!=: not equal
=~: regex matches
!~: regex does not match
Regex log stream examples:
  • Example
{unit="polkadot.service"} |= " Idle "

Grafana

sudo apt-get install -y apt-transport-https \
&& sudo apt-get install -y software-properties-common wget \
&& wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add - \
&& echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list \
&& sudo apt-get update \
&& sudo apt-get install grafana \
&& sudo systemctl daemon-reload \
&& sudo systemctl start grafana-server \
&& sudo systemctl status grafana-server \
&& sudo systemctl enable grafana-server.service

Loki

apt install unzip \
&& mkdir /opt/loki \
&& cd /opt/loki
wget https://github.com/grafana/loki/releases/download/v2.2.1/loki-linux-amd64.zip \
&& sudo unzip loki-linux-amd64.zipsudo unzip loki-linux-amd64.zip
cat <<EOF >/etc/systemd/system/loki.service
[Unit] 
Description=Loki service 
After=network.target 
 
[Service] 
Type=simple 
#User=loki 

ExecStart=/opt/loki/loki-linux-amd64 -config.file /opt/loki/loki-local-config.yaml 
Restart=always 
 
[Install] 
WantedBy=multi-user.target
EOF
cat <<EOF>/opt/loki/loki-local-config.yaml
auth_enabled: false

server:
  http_listen_port: 0
  grpc_listen_port: 0

ingester:
  wal:
    enabled: true
    dir: /tmp/wal
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_sleep: 0s
  chunk_idle_period: 1h       
  max_chunk_age: 1h           
  chunk_target_size: 1048576  
  chunk_retain_period: 30s    
  max_transfer_retries: 0
schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /tmp/loki/boltdb-shipper-active
    cache_location: /tmp/loki/boltdb-shipper-cache
    cache_ttl: 24h
    shared_store: filesystem
  filesystem:
    directory: /tmp/loki/chunks

compactor:
  working_directory: /tmp/loki/boltdb-shipper-compactor
  shared_store: filesystem

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h

chunk_store_config:
  max_look_back_period: 0s

table_manager:
  retention_deletes_enabled: false
  retention_period: 0s

ruler:
  storage:
    type: local
    local:
      directory: /tmp/loki/rules
  rule_path: /tmp/loki/rules-temp
  alertmanager_url: http://localhost:9093
  ring:
    kvstore:
      store: inmemory
  enable_api: true
EOF
sudo systemctl enable loki.service \
&& sudo systemctl start loki.service \
&& sudo systemctl status loki.service 

Promtail

apt install unzip \
&& sudo mkdir /opt/promtail \
&& cd /opt/promtail \
&& wget https://github.com/grafana/loki/releases/download/v2.2.1/promtail-linux-amd64.zip \
&& sudo unzip promtail-linux-amd64.zip
cat <<EOF>/opt/promtail/polkadot-config.yaml
server:
  http_listen_port: 0
  grpc_listen_port: 0
clients:
  - url: http://<HOST>:3100/loki/api/v1/push
    tenant_id: 'v1'
positions:
  filename: /tmp/positions.yaml
scrape_configs:
- job_name: journal
  journal:
    max_age: 60s
    labels:
      job: systemd-journal
  relabel_configs:
    - source_labels: ['__journal__systemd_unit']
      target_label: 'unit'
    - source_labels: ['__journal__hostname']
      target_label: 'hostname'
  pipeline_stages:
  # Drop this logs
  - match:
      selector: '{job="systemd-journal", unit="ifup@eth0.service"}'
      action: drop
      drop_counter_reason: ifup_logs
  - match:
      selector: '{job="systemd-journal", unit="init.scope"}'
      action: drop
      drop_counter_reason: promtail_logs
  - match:
      selector: '{job="systemd-journal", unit="cron.service"}'
      action: drop
      drop_counter_reason: cron_logs
  - match:
      selector: '{job="systemd-journal", unit="ssh.service"}'
      action: drop
      drop_counter_reason: ssh_logs
  - match:
      selector: '{job="systemd-journal", unit="systemd-logind.service"}'
      action: drop
      drop_counter_reason: systemd_logs
  # Get this logs
  - match:
      selector: '{job="systemd-journal", unit="polkadot.service"}'
      stages:
      - regex:
          expression: '.*(<output>)'
      - labels:
          level:

      - output:
          source: output
EOF
cat <<EOF >/etc/systemd/system/promtail.service
[Unit] 
Description=Promtail service 
After=network.target 
 
[Service] 
Type=simple 
#User=promtail 

ExecStart=/opt/loki/promtail-linux-amd64 -config.file /opt/promtail/polkadot-config.yaml 
Restart=always 
 
[Install] 
WantedBy=multi-user.target
EOF
systemctl enable promtail.service \
&& systemctl start promtail.service \
&& systemctl status promtail.service

Grafana Dashboard Template

{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": "-- Grafana --",
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "target": {
          "limit": 100,
          "matchAny": false,
          "tags": [],
          "type": "dashboard"
        },
        "type": "dashboard"
      },
      {
        "datasource": null,
        "enable": true,
        "expr": "{job=\"systemd-journal\", unit=\"polkadot.service\", hostname=~\".*\"}",
        "iconColor": "#00b781",
        "name": "Hostname",
        "tagKeys": "{{hostname}}",
        "target": {},
        "textFormat": "{{hostname}}",
        "titleFormat": "Name"
      }
    ]
  },
  "description": "A basic monitoring based on the Polkadot log level='info' ",
  "editable": true,
  "gnetId": null,
  "graphTooltip": 0,
  "id": 4,
  "links": [
    {
      "asDropdown": false,
      "icon": "external link",
      "includeVars": false,
      "keepTime": false,
      "tags": [],
      "targetBlank": true,
      "title": "For support & nomination please use the following KUSAMA (KSM) Crypto Address: H1bSKJxoxzxYRCdGQutVqFGeW7xU3AcN6vyEdZBU7Qb1rsZ",
      "tooltip": "KSM",
      "type": "link",
      "url": "https://ksm.network"
    }
  ],
  "panels": [
    {
      "datasource": null,
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "No Blocks W#@% Dude? ",
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "dark-red",
                "value": null
              },
              {
                "color": "red",
                "value": 0
              },
              {
                "color": "#EAB839",
                "value": 1
              },
              {
                "color": "#6ED0E0",
                "value": 2
              },
              {
                "color": "#EF843C",
                "value": 3
              },
              {
                "color": "#E24D42",
                "value": 4
              },
              {
                "color": "#1F78C1",
                "value": 5
              },
              {
                "color": "#BA43A9",
                "value": 10
              }
            ]
          }
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 3,
        "x": 0,
        "y": 0
      },
      "id": 12,
      "options": {
        "colorMode": "background",
        "graphMode": "area",
        "justifyMode": "center",
        "orientation": "horizontal",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "/^imported$/",
          "values": false
        },
        "text": {},
        "textMode": "value_and_name"
      },
      "pluginVersion": "8.1.1",
      "targets": [
        {
          "expr": "count_over_time( {unit=\"polkadot.service\", hostname=~\".*\"} |= \"Imported\" | regexp \"(?P<time>\\\\d+-\\\\d+-\\\\d+\\\\s+\\\\d+:\\\\d+:\\\\d+)\\\\W+\\\\w+\\\\W+(?P<imported>[0-9]+)\"[6s])",
          "hide": false,
          "legendFormat": "",
          "refId": "C"
        }
      ],
      "timeFrom": null,
      "timeShift": null,
      "title": "Imported Blocks Per/s",
      "transformations": [
        {
          "id": "labelsToFields",
          "options": {}
        },
        {
          "id": "organize",
          "options": {
            "excludeByName": {
              "id": true,
              "job": true,
              "line": true,
              "ts": true,
              "tsNs": true,
              "unit": true
            },
            "indexByName": {},
            "renameByName": {
              "Time": "time",
              "Value": "imported",
              "id": "Id",
              "imported": "Imported",
              "job": "Job",
              "line": "Line",
              "time": "time",
              "ts": "TS",
              "tsNs": "tsNs",
              "unit": "Unit"
            }
          }
        }
      ],
      "type": "stat"
    },
    {
      "datasource": null,
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "fixedColor": "#27b27e",
            "mode": "fixed"
          },
          "mappings": [],
          "noValue": "W$@#?",
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "#580000",
                "value": null
              }
            ]
          }
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 18,
        "x": 3,
        "y": 0
      },
      "id": 10,
      "options": {
        "colorMode": "value",
        "graphMode": "area",
        "justifyMode": "center",
        "orientation": "vertical",
        "reduceOptions": {
          "calcs": [
            "last"
          ],
          "fields": "/.*/",
          "limit": 1,
          "values": false
        },
        "text": {},
        "textMode": "value_and_name"
      },
      "pluginVersion": "8.1.1",
      "repeat": null,
      "targets": [
        {
          "expr": "{unit=\"polkadot.service\", hostname=~\".*\"} |= \" Idle \" | regexp \"^(?s)(?P<time>\\\\S+\\\\d+\\\\s+\\\\d+:\\\\d+:\\\\d+) \\\\W+\\\\s? Idle\\\\W+(?P<peers>\\\\d+) peers\\\\)\\\\, best\\\\:\\\\s+\\\\W(?P<best>\\\\d+)\\\\s+\\\\W(?P<hash>[a-zA-Z0-9]+\\\\W[a-zA-Z0-9]+)\\\\W\\\\, finalized\\\\s\\\\W(?P<finalized>[0-9]+)\\\\s+\\\\W(?P<fhash>[a-zA-Z0-9]+\\\\W[a-zA-Z0-9]+)\\\\W+(?P<download>[0-9]+\\\\W[0-9]+[a-zA-Z]+\\\\Ws\\\\s+)\\\\W+(?P<upload>[0-9]+\\\\W[0-9]+[a-zA-Z]+\\\\Ws)\"",
          "instant": false,
          "legendFormat": "{{hostname}}",
          "range": true,
          "refId": "A"
        }
      ],
      "timeFrom": null,
      "timeShift": null,
      "title": "Statistics",
      "transformations": [
        {
          "id": "labelsToFields",
          "options": {}
        },
        {
          "id": "filterFieldsByName",
          "options": {
            "include": {
              "names": [
                "upload",
                "download",
                "best",
                "finalized"
              ]
            }
          }
        },
        {
          "id": "calculateField",
          "options": {
            "alias": "Count",
            "mode": "reduceRow",
            "reduce": {
              "include": [
                "best"
              ],
              "reducer": "sum"
            },
            "replaceFields": false
          }
        },
        {
          "id": "organize",
          "options": {
            "excludeByName": {},
            "indexByName": {
              "Count": 5,
              "best": 1,
              "download": 4,
              "finalized": 2,
              "peers": 0,
              "upload": 3
            },
            "renameByName": {
              "Count": "Blocks Counter",
              "best": "Best Block",
              "download": "Download",
              "finalized": "Finalized Block",
              "peers": "Peers",
              "upload": "Upload"
            }
          }
        }
      ],
      "type": "stat"
    },
    {
      "datasource": null,
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "No Peers",
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "#dd051b",
                "value": null
              },
              {
                "color": "semi-dark-red",
                "value": 5
              },
              {
                "color": "dark-orange",
                "value": 10
              },
              {
                "color": "light-yellow",
                "value": 15
              },
              {
                "color": "yellow",
                "value": 25
              },
              {
                "color": "dark-yellow",
                "value": 35
              },
              {
                "color": "dark-green",
                "value": 50
              },
              {
                "color": "semi-dark-green",
                "value": 65
              },
              {
                "color": "green",
                "value": 80
              },
              {
                "color": "purple",
                "value": 100
              },
              {
                "color": "dark-purple",
                "value": 200
              }
            ]
          }
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 3,
        "x": 21,
        "y": 0
      },
      "id": 14,
      "options": {
        "orientation": "auto",
        "reduceOptions": {
          "calcs": [
            "last"
          ],
          "fields": "/^peers$/",
          "limit": 3,
          "values": false
        },
        "showThresholdLabels": true,
        "showThresholdMarkers": true,
        "text": {}
      },
      "pluginVersion": "8.1.1",
      "targets": [
        {
          "expr": "{unit=\"polkadot.service\", hostname=~\".*\"} |= \" Idle \" | regexp \"^(?s)(?P<time>\\\\S+\\\\d+\\\\s+\\\\d+:\\\\d+:\\\\d+) \\\\W+\\\\s? Idle\\\\W+(?P<peers>\\\\d+) peers\\\\)\\\\, best\\\\:\\\\s+\\\\W(?P<best>\\\\d+)\\\\s+\\\\W(?P<hash>[a-zA-Z0-9]+\\\\W[a-zA-Z0-9]+)\\\\W\\\\, finalized\\\\s\\\\W(?P<finalized>[0-9]+)\\\\s+\\\\W(?P<fhash>[a-zA-Z0-9]+\\\\W[a-zA-Z0-9]+)\\\\W+(?P<download>[0-9]+\\\\W[0-9]+[a-zA-Z]+\\\\Ws\\\\s+)\\\\W+(?P<upload>[0-9]+\\\\W[0-9]+[a-zA-Z]+\\\\Ws)\"",
          "refId": "A"
        }
      ],
      "title": "Peers",
      "transformations": [
        {
          "id": "labelsToFields",
          "options": {}
        },
        {
          "id": "organize",
          "options": {
            "excludeByName": {
              "best": true,
              "download": true,
              "fhash": true,
              "finalized": true,
              "hash": true,
              "id": true,
              "job": true,
              "line": true,
              "ts": true,
              "tsNs": true,
              "unit": true,
              "upload": true
            },
            "indexByName": {
              "best": 3,
              "download": 4,
              "fhash": 8,
              "finalized": 2,
              "hash": 10,
              "id": 7,
              "job": 12,
              "line": 6,
              "peers": 1,
              "time": 0,
              "ts": 11,
              "tsNs": 13,
              "unit": 9,
              "upload": 5
            },
            "renameByName": {}
          }
        }
      ],
      "type": "gauge"
    },
    {
      "datasource": null,
      "gridPos": {
        "h": 26,
        "w": 13,
        "x": 0,
        "y": 10
      },
      "id": 8,
      "options": {
        "dedupStrategy": "none",
        "enableLogDetails": true,
        "prettifyLogMessage": false,
        "showCommonLabels": true,
        "showLabels": true,
        "showTime": false,
        "sortOrder": "Descending",
        "wrapLogMessage": false
      },
      "pluginVersion": "8.1.1",
      "targets": [
        {
          "expr": "{unit=\"polkadot.service\"} != \" Dispute \" != \" Mismatch \" != \"error=\"",
          "maxLines": null,
          "refId": "A"
        }
      ],
      "title": "LOGS",
      "type": "logs"
    },
    {
      "datasource": null,
      "gridPos": {
        "h": 26,
        "w": 11,
        "x": 13,
        "y": 10
      },
      "id": 17,
      "options": {
        "dedupStrategy": "none",
        "enableLogDetails": true,
        "prettifyLogMessage": false,
        "showCommonLabels": true,
        "showLabels": true,
        "showTime": false,
        "sortOrder": "Descending",
        "wrapLogMessage": false
      },
      "pluginVersion": "8.1.1",
      "targets": [
        {
          "expr": "{unit=\"polkadot.service\"}  != \" Idle \" != \"Dispute coordinator confirmation lost\" != \"Imported\" != \"Discovered new external address for our node\"",
          "maxLines": null,
          "refId": "A"
        }
      ],
      "title": "Unknown logs ",
      "type": "logs"
    }
  ],
  "refresh": "",
  "schemaVersion": 30,
  "style": "dark",
  "tags": [],
  "templating": {
    "list": []
  },
  "time": {
    "from": "now-5m",
    "to": "now"
  },
  "timepicker": {
    "nowDelay": "1m"
  },
  "timezone": "",
  "title": "Kusama Validator Monitoring With Grafana Loki & Promtail",
  "uid": "skglLKzRz",
  "version": 130
}

Stress less project


For Support && Nominations

  • Display name. KSMNETWORK && KSMNETWORK-WEST

  • Email w3f@ksm.network

  • Riot @gtoocool:matrix.org

  • KUSAMA (KSM) Address

  • H1bSKJxoxzxYRCdGQutVqFGeW7xU3AcN6vyEdZBU7Qb1rsZ

  • PolkaDOT (DOT) Address:

  • 15FxvBFDd3X7H9qcMGqsiuvFYEg4D3mBoTA2LQufreysTHKA

  • https://ksm.network

About

A basic monitoring based on the Pokkadot log level='info'

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published