Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove search engine indexing #73

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 1st stage, build app
FROM golang:1.19 as builder
FROM golang:1.20.6-bullseye as builder
RUN apt-get update && apt-get -y upgrade && apt-get install -y upx
COPY . /build/app
WORKDIR /build/app
Expand Down
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This is a tool for validators running tendermint nodes. It sends notifications w
- [Configuration File Settings](config.md)
- [Setting up PagerDuty](pagerduty.md)
- [Setting up Discord](discord.md)
- TODO: [Setting up Telegram](telegram.md)
- [Setting up Telegram](telegram.md)
- [Prometheus Exports](prometheus.md)
- [Remotely Configuring Tenderduty](remote.md)
- [Running on Akash](akash.md)
Expand Down Expand Up @@ -79,4 +79,4 @@ Notifications:
* There really isn't anything special about the notifications it sends. For Discord and Telegram it will only send an alert on a new alarm and when the alarm clears. Pagerduty has a little more nuance.
* Pagerduty:
* Pro-tip: the alarms sent to pagerduty all use a unique "key". Pagerduty will automatically de-deduplicate alerts based on this key. If you want redundant monitoring you can run multiple instances of tenderduty alerting to pagerduty and will not get duplicate alerts.
* Additional flapping detection is applied to pagerduty (not to discord or telegram). If a node is going up and down every few minutes it will only send an alert once in a five minute period.
* Additional flapping detection is applied to pagerduty (not to discord or telegram). If a node is going up and down every few minutes it will only send an alert once in a five minute period.
3 changes: 2 additions & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ services:
volumes:
- home:/var/lib/tenderduty
- ./config.yml:/var/lib/tenderduty/config.yml
- ./chains.d:/var/lib/tenderduty/chains.d/
logging:
driver: "json-file"
options:
Expand Down Expand Up @@ -159,4 +160,4 @@ sudo systemctl start tenderduty
# and to watch the logs, press CTRL-C to stop watching
sudo journalctl -fu tenderduty

```
```
2 changes: 1 addition & 1 deletion example-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ chains:
chain_id: osmosis-1
# Hooray, in v2 we derive the valcons from abci queries so you don't have to jump through hoops to figure out how
# to convert ed25519 keys to the appropriate bech32 address.
# Use valcons address if using ICS
# Use valcons address if using ICS or tendermint/PubKeyBn254
valoper_address: osmovaloper1xxxxxxx...
# Should the monitor revert to using public API endpoints if all supplied RCP nodes fail?
# This isn't always reliable, not all public nodes have websocket proxying setup correctly.
Expand Down
4 changes: 3 additions & 1 deletion example-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ volumes:

services:
tenderduty:
container_name: tenderduty
build: .
command: ""
expose:
Expand All @@ -30,7 +31,8 @@ services:
- monitor-net

caddy:
image: caddy:2.3.0
container_name: caddy
image: caddy:2.7.6
ports:
- "80:80"
- "443:443"
Expand Down
5 changes: 3 additions & 2 deletions td2/dashboard/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package dash
import (
"embed"
"encoding/json"
"github.com/gorilla/websocket"
"github.com/textileio/go-threads/broadcast"
"io/fs"
"log"
"net/http"
"regexp"
"sort"
"sync"
"time"

"github.com/gorilla/websocket"
"github.com/textileio/go-threads/broadcast"
)

var (
Expand Down
29 changes: 15 additions & 14 deletions td2/dashboard/types.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
package dash

type ChainStatus struct {
MsgType string `json:"msgType"`
Name string `json:"name"`
ChainId string `json:"chain_id"`
Moniker string `json:"moniker"`
Bonded bool `json:"bonded"`
Jailed bool `json:"jailed"`
Tombstoned bool `json:"tombstoned"`
Missed int64 `json:"missed"`
Window int64 `json:"window"`
Nodes int `json:"nodes"`
HealthyNodes int `json:"healthy_nodes"`
ActiveAlerts int `json:"active_alerts"`
Height int64 `json:"height"`
LastError string `json:"last_error"`
MsgType string `json:"msgType"`
Name string `json:"name"`
ChainId string `json:"chain_id"`
Moniker string `json:"moniker"`
Bonded bool `json:"bonded"`
Jailed bool `json:"jailed"`
Tombstoned bool `json:"tombstoned"`
Missed int64 `json:"missed"`
Window int64 `json:"window"`
MinSignedPerWindow float64 `json:"min_signed_per_window"`
Nodes int `json:"nodes"`
HealthyNodes int `json:"healthy_nodes"`
ActiveAlerts int `json:"active_alerts"`
Height int64 `json:"height"`
LastError string `json:"last_error"`

Blocks []int `json:"blocks"`
}
Expand Down
103 changes: 81 additions & 22 deletions td2/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tenderduty

import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
Expand All @@ -23,6 +24,7 @@ func (cc *ChainConfig) newRpc() error {
for _, endpoint := range cc.Nodes {
anyWorking = anyWorking || !endpoint.down
}

// grab the first working endpoint
tryUrl := func(u string) (msg string, down, syncing bool) {
_, err := url.Parse(u)
Expand All @@ -39,20 +41,28 @@ func (cc *ChainConfig) newRpc() error {
down = true
return
}
var network string
var catching_up bool
status, err := cc.client.Status(ctx)
if err != nil {
msg = fmt.Sprintf("❌ could not get status for %s: (%s) %s", cc.name, u, err)
down = true
l(msg)
return
n, c, err := getStatusWithEndpoint(ctx, u)
if err != nil {
msg = fmt.Sprintf("❌ could not get status for %s: (%s) %s", cc.name, u, err)
down = true
l(msg)
return
}
network, catching_up = n, c
} else {
network, catching_up = status.NodeInfo.Network, status.SyncInfo.CatchingUp
}
if status.NodeInfo.Network != cc.ChainId {
msg = fmt.Sprintf("chain id %s on %s does not match, expected %s, skipping", status.NodeInfo.Network, u, cc.ChainId)
if network != cc.ChainId {
msg = fmt.Sprintf("chain id %s on %s does not match, expected %s, skipping", network, u, cc.ChainId)
down = true
l(msg)
return
}
if status.SyncInfo.CatchingUp {
if catching_up {
msg = fmt.Sprint("🐢 node is not synced, skipping ", u)
syncing = true
down = true
Expand Down Expand Up @@ -97,21 +107,22 @@ func (cc *ChainConfig) newRpc() error {
cc.lastError = "no usable RPC endpoints available for " + cc.ChainId
if td.EnableDash {
td.updateChan <- &dash.ChainStatus{
MsgType: "status",
Name: cc.name,
ChainId: cc.ChainId,
Moniker: cc.valInfo.Moniker,
Bonded: cc.valInfo.Bonded,
Jailed: cc.valInfo.Jailed,
Tombstoned: cc.valInfo.Tombstoned,
Missed: cc.valInfo.Missed,
Window: cc.valInfo.Window,
Nodes: len(cc.Nodes),
HealthyNodes: 0,
ActiveAlerts: 1,
Height: 0,
LastError: cc.lastError,
Blocks: cc.blocksResults,
MsgType: "status",
Name: cc.name,
ChainId: cc.ChainId,
Moniker: cc.valInfo.Moniker,
Bonded: cc.valInfo.Bonded,
Jailed: cc.valInfo.Jailed,
Tombstoned: cc.valInfo.Tombstoned,
Missed: cc.valInfo.Missed,
Window: cc.valInfo.Window,
MinSignedPerWindow: cc.minSignedPerWindow,
Nodes: len(cc.Nodes),
HealthyNodes: 0,
ActiveAlerts: 1,
Height: 0,
LastError: cc.lastError,
Blocks: cc.blocksResults,
}
}
return errors.New("no usable endpoints available for " + cc.ChainId)
Expand Down Expand Up @@ -261,3 +272,51 @@ func guessPublicEndpoint(u string) string {
}
return proto + matches[1] + port
}

func getStatusWithEndpoint(ctx context.Context, u string) (string, bool, error) {
// Parse the URL
parsedURL, err := url.Parse(u)
if err != nil {
return "", false, err
}

// Check if the scheme is 'tcp' and modify to 'http'
if parsedURL.Scheme == "tcp" {
parsedURL.Scheme = "http"
}

queryPath := fmt.Sprintf("%s/status", parsedURL.String())
req, err := http.NewRequestWithContext(ctx, http.MethodGet, queryPath, nil)
if err != nil {
return "", false, err
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", false, err
}
defer resp.Body.Close()

b, err := io.ReadAll(resp.Body)
if err != nil {
return "", false, err
}

type tendermintStatus struct {
JsonRPC string `json:"jsonrpc"`
ID int `json:"id"`
Result struct {
NodeInfo struct {
Network string `json:"network"`
} `json:"node_info"`
SyncInfo struct {
CatchingUp bool `json:"catching_up"`
} `json:"sync_info"`
} `json:"result"`
}
var status tendermintStatus
if err := json.Unmarshal(b, &status); err != nil {
return "", false, err
}
return status.Result.NodeInfo.Network, status.Result.SyncInfo.CatchingUp, nil
}
6 changes: 6 additions & 0 deletions td2/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ func Run(configFile, stateFile, chainConfigDirectory string, password *string) e
time.Sleep(5 * time.Second)
continue
}

e = cc.GetMinSignedPerWindow()
if e != nil {
l("🛑", cc.ChainId, e)
}

e = cc.GetValInfo(true)
if e != nil {
l("🛑", cc.ChainId, e)
Expand Down
2 changes: 2 additions & 0 deletions td2/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</style>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<link rel="stylesheet" href="css/uikit.min.css" />
<title>Tenderduty Dashboard</title>
<script src="js/uikit.min.js"></script>
Expand Down Expand Up @@ -41,6 +42,7 @@
<th>Moniker</th>
<th style="text-align: center">Bonded</th>
<th class="uk-text-center">Uptime</th>
<th class="uk-text-center">Threshold</th>
<th class="uk-text-center">RPC Nodes</th>
</tr>
</thead>
Expand Down
6 changes: 5 additions & 1 deletion td2/static/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ function updateTable(status) {
window += `${(100 - (status.Status[i].missed / status.Status[i].window) * 100).toFixed(2)}%</div>`
}
window += `<div class="uk-width-1-2">${_.escape(status.Status[i].missed)} / ${_.escape(status.Status[i].window)}</div>`

let threshold = ""
threshold += `<span class="uk-width-1-2">${100 * status.Status[i].min_signed_per_window}%</span>`;

let nodes = `${_.escape(status.Status[i].healthy_nodes)} / ${_.escape(status.Status[i].nodes)}`
if (status.Status[i].healthy_nodes < status.Status[i].nodes) {
Expand All @@ -131,7 +134,8 @@ function updateTable(status) {
}
r.insertCell(4).innerHTML = `<div style="text-align: center">${bonded}</div>`
r.insertCell(5).innerHTML = `<div uk-grid>${window}</div>`
r.insertCell(6).innerHTML = `<div class="uk-text-center">${nodes}</div>`
r.insertCell(6).innerHTML = `<div class="uk-text-center">${threshold}</div>`
r.insertCell(7).innerHTML = `<div class="uk-text-center">${nodes}</div>`
}
}

Expand Down
52 changes: 27 additions & 25 deletions td2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,19 @@ type savedState struct {
// ChainConfig represents a validator to be monitored on a chain, it is somewhat of a misnomer since multiple
// validators can be monitored on a single chain.
type ChainConfig struct {
name string
wsclient *TmConn // custom websocket client to work around wss:// bugs in tendermint
client *rpchttp.HTTP // legit tendermint client
noNodes bool // tracks if all nodes are down
valInfo *ValInfo // recent validator state, only refreshed every few minutes
lastValInfo *ValInfo // use for detecting newly-jailed/tombstone
blocksResults []int
lastError string
lastBlockTime time.Time
lastBlockAlarm bool
lastBlockNum int64
activeAlerts int
name string
wsclient *TmConn // custom websocket client to work around wss:// bugs in tendermint
client *rpchttp.HTTP // legit tendermint client
noNodes bool // tracks if all nodes are down
valInfo *ValInfo // recent validator state, only refreshed every few minutes
lastValInfo *ValInfo // use for detecting newly-jailed/tombstone
minSignedPerWindow float64 // instantly see the validator risk level
blocksResults []int
lastError string
lastBlockTime time.Time
lastBlockAlarm bool
lastBlockNum int64
activeAlerts int

statTotalSigns float64
statTotalProps float64
Expand Down Expand Up @@ -326,19 +327,20 @@ func validateConfig(c *Config) (fatal bool, problems []string) {
}
if td.EnableDash {
td.updateChan <- &dash.ChainStatus{
MsgType: "status",
Name: v.name,
ChainId: v.ChainId,
Moniker: v.valInfo.Moniker,
Bonded: v.valInfo.Bonded,
Jailed: v.valInfo.Jailed,
Tombstoned: v.valInfo.Tombstoned,
Missed: v.valInfo.Missed,
Window: v.valInfo.Window,
Nodes: len(v.Nodes),
HealthyNodes: 0,
ActiveAlerts: 0,
Blocks: v.blocksResults,
MsgType: "status",
Name: v.name,
ChainId: v.ChainId,
Moniker: v.valInfo.Moniker,
Bonded: v.valInfo.Bonded,
Jailed: v.valInfo.Jailed,
Tombstoned: v.valInfo.Tombstoned,
Missed: v.valInfo.Missed,
MinSignedPerWindow: v.minSignedPerWindow,
Window: v.valInfo.Window,
Nodes: len(v.Nodes),
HealthyNodes: 0,
ActiveAlerts: 0,
Blocks: v.blocksResults,
}
}
}
Expand Down
Loading
Loading