vegaprotocol / vega-monitoring

MVP to store more data for metrics
MIT License
2 stars 1 forks source link

Vega Network Monitoring

To properly monitor Vega Network you need to know what is happening in the network itself, e.g. deposits, transfers, new market proposals, etc. 90% of this information is already gathered by the Data Node and stored in TimescaleDB, which is time series database extension to the PostgreSQL. You can use various tools, like Grafana or Metabase, to process and filter that data.

Vega Network Monitoring is a separate application that provides the other 10% of data. It extends the Data Node database with new tables, filled with data scraped from other services.

Extra data

1. Block Signers

Information about validators signing and proposing blocks. table

2. Network History Segments

Network History is a way of storing Data Node state in segments created every X blocks, and sharing them through IPFS. Here we store segment hashes available from a specified list of Data Nodes. table

3. CometBFT Txs

Subest of CometBFT Txs that otherwise can't be found in Data Node DB.

4. Network Balances

Keeps track of four types of balances:

table

5. Asset Prices

Prices in USD of all assets traded on Vega Network. table

Setup

Setup Service

Compile

go build -o bin/vega-monitoring .

Init

Create config file

First, generate config.toml in the root directory.

./vega-monitoring service init

Now edit the config.toml and provide the necessary information.

Validate config

./vega-monitoring service validate-config

Initialize Database

Before, you need to start Data Node, which will set up a Database. Then run this to create all extra tables for Vega Network Monitoring

./vega-monitoring service init-db

Start service

./vega-monitoring service start

Other tools

Backup Grafana config

Pull Alerts, Dashboards and Data Sources config from Grafana API and store in ./grafana directory.

go run main.go grafana download-config --url [grafana base url] --api-token [service account token]

Configuration

Monitoring.EthereumChain

Example for Monitoring.EthereumChain:

[[Monitoring.EthereumChain]]
NodeName = "Some-unique-node-name"
Period = "1m15s"
ChainId = 100
NetworkId = 100
RPCEndpoint = "https://rpc.ankr.com/gnosis/XXXXXXX"

Accounts = [
    "0x6063a8de125d0982fcd7b41754262d94cac8ff14",
]

[[Monitoring.EthereumChain.Calls]]
    Name = "BTC/USD"
    Address = "0x719abd606155442c21b7d561426d42bd0e40a776"
    Abi = "[{\"inputs\": [{\"internalType\": \"bytes32\",\"name\": \"id\",\"type\": \"bytes32\"}],\"name\": \"getPrice\",\"outputs\": [{\"internalType\": \"int256\",\"name\": \"\",\"type\": \"int256\"}],\"stateMutability\": \"view\",\"type\": \"function\"}]"
    Method = "getPrice"
    Args = [
    "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
    ]
    OutputTransform = "float_price:18"

[[Monitoring.EthereumChain.Calls]]
    Name = "SOL/USD"
    Address = "0x719abd606155442c21b7d561426d42bd0e40a776"
    Abi = "[{\"inputs\": [{\"internalType\": \"bytes32\",\"name\": \"id\",\"type\": \"bytes32\"}],\"name\": \"getPrice\",\"outputs\": [{\"internalType\": \"int256\",\"name\": \"\",\"type\": \"int256\"}],\"stateMutability\": \"view\",\"type\": \"function\"}]"
    Method = "getPrice"
    Args = [
    "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
    ]
    OutputTransform = "float_price:18"

[[Monitoring.EthereumChain]]
NodeName = "Some-unique-node-name"
Period = "1m15s"
ChainId = 5
NetworkId = 5
RPCEndpoint = "https://goerli.infura.io/v3/XXXXXXX" # infura daniel@vega.xyz

[[Monitoring.EthereumChain.Events]]
    Name = "UMA Settlement on Goerli"
    ContractAddress = "0xB49281A7F7878Cdf5B6378d8c7dC211Ffc1b5B60"
    ABI = "[{\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Disputed\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": false, \"internalType\": \"bool\", \"name\": \"result\", \"type\": \"bool\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, { \"indexed\": true,\"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Resolved\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Submitted\", \"type\": \"event\"}]"
    InitialBlocksToScan = 40 # ~half hour
    MaxBlocksToFilter   = 1000

[[Monitoring.EthereumChain.Events]]
    Name = "UMA Termination on Goerli"
    ContractAddress = "0x8744F73A5b404ef843A76A927dF89FE20ab071CB"
    ABI = "[{\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Disputed\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": false, \"internalType\": \"bool\", \"name\": \"result\", \"type\": \"bool\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, { \"indexed\": true,\"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Resolved\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Submitted\", \"type\": \"event\"}]"
    InitialBlocksToScan = 40 # ~half hour
    MaxBlocksToFilter   = 1000

Accounts

List of account We want to get ETH balances for list(string)

Example:

Accounts = [
    "0x6063a8de125d0982fcd7b41754262d94cac8ff14",
]

Result:

vega_monitoring_ethereum_balance{address="0x6063a8de125d0982fcd7b41754262d94cac8ff14",chain_id="100",network_id="100"} 40.46573 1710281507676

Monitoring.EthereumChain.Calls

Defines ethereum call to smart contract

Example:

[[Monitoring.EthereumChain.Calls]]
    Name = "BTC/USD"
    Address = "0x719abd606155442c21b7d561426d42bd0e40a776"
    Abi = "[{\"inputs\": [{\"internalType\": \"bytes32\",\"name\": \"id\",\"type\": \"bytes32\"}],\"name\": \"getPrice\",\"outputs\": [{\"internalType\": \"int256\",\"name\": \"\",\"type\": \"int256\"}],\"stateMutability\": \"view\",\"type\": \"function\"}]"
    Method = "getPrice"
    Args = [
    "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
    ]
    OutputTransform = "float_price:18"

[[Monitoring.EthereumChain.Calls]]
    Name = "SOL/USD"
    Address = "0x719abd606155442c21b7d561426d42bd0e40a776"
    Abi = "[{\"inputs\": [{\"internalType\": \"bytes32\",\"name\": \"id\",\"type\": \"bytes32\"}],\"name\": \"getPrice\",\"outputs\": [{\"internalType\": \"int256\",\"name\": \"\",\"type\": \"int256\"}],\"stateMutability\": \"view\",\"type\": \"function\"}]"
    Method = "getPrice"
    Args = [
    "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
    ]
    OutputTransform = "float_price:18"

[[Monitoring.EthereumChain.Calls]]
    Name = "PEPE/USDx1000000"
    Address = "0x719abd606155442c21b7d561426d42bd0e40a776"
    Abi = "[{\"inputs\": [{\"internalType\": \"bytes32\",\"name\": \"id\",\"type\": \"bytes32\"}],\"name\": \"getPrice\",\"outputs\": [{\"internalType\": \"int256\",\"name\": \"\",\"type\": \"int256\"}],\"stateMutability\": \"view\",\"type\": \"function\"}]"
    Method = "getPrice"
    Args = [
    "d69731a2e74ac1ce884fc3890f7ee324b6deb66147055249568869ed700882e4"
    ]
    OutputTransform = "float_price:12"

Result:

vega_monitoring_contract_call_response{address="0x719AbD606155442c21b7d561426D42bD0E40a776",id="BTC/USD",method="getPrice"} 70989.75012348244 1710281507676
vega_monitoring_contract_call_response{address="0x719AbD606155442c21b7d561426D42bD0E40a776",id="PEPE/USDx1000000",method="getPrice"} 8.143887868795 1710281507676
vega_monitoring_contract_call_response{address="0x719AbD606155442c21b7d561426D42bD0E40a776",id="SOL/USD",method="getPrice"} 147.51017038752528 1710281507676

Monitoring.EthereumChain.Events

Example:

[[Monitoring.EthereumChain.Events]]
    Name = "UMA Settlement on Goerli"
    ContractAddress = "0xB49281A7F7878Cdf5B6378d8c7dC211Ffc1b5B60"
    ABI = "[{\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Disputed\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": false, \"internalType\": \"bool\", \"name\": \"result\", \"type\": \"bool\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, { \"indexed\": true,\"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Resolved\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Submitted\", \"type\": \"event\"}]"
    InitialBlocksToScan = 40 # ~half hour
    MaxBlocksToFilter   = 1000

[[Monitoring.EthereumChain.Events]]
    Name = "UMA Termination on Goerli"
    ContractAddress = "0x8744F73A5b404ef843A76A927dF89FE20ab071CB"
    ABI = "[{\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Disputed\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": false, \"internalType\": \"bool\", \"name\": \"result\", \"type\": \"bool\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, { \"indexed\": true,\"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Resolved\", \"type\": \"event\"}, {\"anonymous\": false, \"inputs\": [{\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"claimId\", \"type\": \"bytes32\"}, {\"indexed\": true, \"internalType\": \"bytes32\", \"name\": \"assertionId\", \"type\": \"bytes32\"}], \"name\": \"Submitted\", \"type\": \"event\"}]"
    InitialBlocksToScan = 40 # ~half hour
    MaxBlocksToFilter   = 1000

Result:

vega_monitoring_contract_events{address="0x8744F73A5b404ef843A76A927dF89FE20ab071CB",event_name="*",id="UMA Termination on Goerli"} 0 1710281507676
vega_monitoring_contract_events{address="0xB49281A7F7878Cdf5B6378d8c7dC211Ffc1b5B60",event_name="*",id="UMA Settlement on Goerli"} 7 1710281507676
vega_monitoring_contract_events{address="0xB49281A7F7878Cdf5B6378d8c7dC211Ffc1b5B60",event_name="Submitted",id="UMA Settlement on Goerli"} 7 1710281507676