Commit 2eeed141 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

endpoint-monitor: deprecate (#10667)

`endpoint-monitor` is not maintained anymore and is
deprecated, so this commit removes it from the monorepo
parent b1338fe5
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
/indexer @ethereum-optimism/devxpod /indexer @ethereum-optimism/devxpod
/infra @ethereum-optimism/infra-reviewers /infra @ethereum-optimism/infra-reviewers
/specs @ethereum-optimism/contract-reviewers @ethereum-optimism/go-reviewers /specs @ethereum-optimism/contract-reviewers @ethereum-optimism/go-reviewers
/endpoint-monitor @ethereum-optimism/infra-reviewers
# Don't add owners if only package.json is updated # Don't add owners if only package.json is updated
/packages/*/package.json /packages/*/package.json
......
...@@ -22,7 +22,6 @@ jobs: ...@@ -22,7 +22,6 @@ jobs:
replica-mon: ${{ steps.packages.outputs.replica-mon }} replica-mon: ${{ steps.packages.outputs.replica-mon }}
wd-mon: ${{ steps.packages.outputs.wd-mon }} wd-mon: ${{ steps.packages.outputs.wd-mon }}
canary-docker-tag: ${{ steps.docker-image-name.outputs.canary-docker-tag }} canary-docker-tag: ${{ steps.docker-image-name.outputs.canary-docker-tag }}
endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }}
steps: steps:
- name: Check out source code - name: Check out source code
...@@ -204,41 +203,3 @@ jobs: ...@@ -204,41 +203,3 @@ jobs:
target: replica-mon target: replica-mon
push: true push: true
tags: ethereumoptimism/replica-mon:${{ needs.canary-publish.outputs.canary-docker-tag }} tags: ethereumoptimism/replica-mon:${{ needs.canary-publish.outputs.canary-docker-tag }}
endpoint-monitor:
name: Publish endpoint-monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish
if: needs.canary-publish.outputs.endpoint-monitor != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set build args
id: build_args
run: |
echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)"
echo ::set-output name=GITVERSION::$(jq -r .version ./endpoint-monitor/package.json)
echo ::set-output name=GITCOMMIT::"$GITHUB_SHA"
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./endpoint-monitor/Dockerfile
push: true
tags: ethereumoptimism/endpoint-monitor:${{ needs.canary-publish.outputs.endpoint-monitor }}
build-args: |
GITDATE=${{ steps.build_args.outputs.GITDATE }}
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
...@@ -22,7 +22,6 @@ jobs: ...@@ -22,7 +22,6 @@ jobs:
multisig-mon: ${{ steps.packages.outputs.multisig-mon }} multisig-mon: ${{ steps.packages.outputs.multisig-mon }}
replica-mon: ${{ steps.packages.outputs.replica-mon }} replica-mon: ${{ steps.packages.outputs.replica-mon }}
wd-mon: ${{ steps.packages.outputs.wd-mon }} wd-mon: ${{ steps.packages.outputs.wd-mon }}
endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }}
# Permissions necessary for Changesets to push a new branch and open PRs # Permissions necessary for Changesets to push a new branch and open PRs
# (for automated Version Packages PRs), and request the JWT for provenance. # (for automated Version Packages PRs), and request the JWT for provenance.
# More info: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings # More info: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings
...@@ -241,40 +240,3 @@ jobs: ...@@ -241,40 +240,3 @@ jobs:
target: replica-mon target: replica-mon
push: true push: true
tags: ethereumoptimism/replica-mon:${{ needs.release.outputs.replica-mon }},ethereumoptimism/replica-mon:latest tags: ethereumoptimism/replica-mon:${{ needs.release.outputs.replica-mon }},ethereumoptimism/replica-mon:latest
endpoint-monitor:
name: Publish endpoint-monitor Version ${{ needs.release.outputs.endpoint-monitor}}
needs: release
if: needs.release.outputs.endpoint-monitor != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set build args
id: build_args
run: |
echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)"
echo ::set-output name=GITVERSION::$(jq -r .version ./endpoint-monitor/package.json)
echo ::set-output name=GITCOMMIT::"$GITHUB_SHA"
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./endpoint-monitor/Dockerfile
push: true
tags: ethereumoptimism/endpoint-monitor:${{ needs.release.outputs.endpoint-monitor }},ethereumoptimism/endpoint-monitor:latest
build-args: |
GITDATE=${{ steps.build_args.outputs.GITDATE }}
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
export ENDPOINT_MONITOR_LOG_LEVEL=debug
export ENDPOINT_MONITOR_PROVIDERS=goerli,mainnet
export ENDPOINT_MONITOR_GOERLI_URL=wss://ws-goerli.optimism.io
export ENDPOINT_MONITOR_MAINNET_URL=wss://ws-mainnet.optimism.io
# @eth-optimism/endpoint-monitor
## 1.0.4
### Patch Changes
- [#9964](https://github.com/ethereum-optimism/optimism/pull/9964) [`8241220898128e1f61064f22dcb6fdd0a5f043c3`](https://github.com/ethereum-optimism/optimism/commit/8241220898128e1f61064f22dcb6fdd0a5f043c3) Thanks [@roninjin10](https://github.com/roninjin10)! - Removed only-allow command from package.json
## 1.0.3
### Patch Changes
- [#7450](https://github.com/ethereum-optimism/optimism/pull/7450) [`ac90e16a7`](https://github.com/ethereum-optimism/optimism/commit/ac90e16a7f85c4f73661ae6023135c3d00421c1e) Thanks [@roninjin10](https://github.com/roninjin10)! - Updated dev dependencies related to testing that is causing audit tooling to report failures
## 1.0.2
### Patch Changes
- [#6164](https://github.com/ethereum-optimism/optimism/pull/6164) [`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a) Thanks [@pengin7384](https://github.com/pengin7384)! - fix typo
## 1.0.1
### Patch Changes
- f505078be: Update go-ethereum to v1.10.26
## 1.0.0
### Major Changes
- a10c2b49: Initial release of endpoint monitor
FROM golang:1.21.1-alpine3.18 as builder
RUN apk --no-cache add make jq bash git alpine-sdk
COPY ./go.mod /app/go.mod
COPY ./go.sum /app/go.sum
WORKDIR /app
RUN go mod download
COPY ./endpoint-monitor /app/endpoint-monitor
COPY ./op-service /app/op-service
COPY ./op-node /app/op-node
COPY ./.git /app/.git
WORKDIR /app/endpoint-monitor
RUN make build
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
RUN addgroup -S app && adduser -S app -G app
USER app
WORKDIR /app
COPY --from=builder /app/endpoint-monitor/bin/endpoint-monitor /app
ENTRYPOINT ["/app/endpoint-monitor"]
GITCOMMIT ?= $(shell git rev-parse HEAD)
GITDATE ?= $(shell git show -s --format='%ct')
VERSION := v0.0.0
LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.Version=$(VERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"
all: build
build:
env GO111MODULE=on go build -v $(LDFLAGS) -o ./bin/endpoint-monitor ./cmd
clean:
rm ./bin/endpoint-monitor
test:
go test -v ./...
lint:
golangci-lint run ./...
.PHONY: \
build \
clean \
test \
lint
# @eth-optimism/endpoint-monitor
The endpoint-monitor runs websocket checks on edge-proxyd endpoints and downstream infra provider endpoints.
## Setup
Install go1.19
```bash
make build
source .env.example # (or copy to .envrc if using direnv)
./bin/endpoint-monitor
```
package main
import (
"os"
opservice "github.com/ethereum-optimism/optimism/op-service"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
endpointMonitor "github.com/ethereum-optimism/optimism/endpoint-monitor"
)
var (
Version = ""
GitCommit = ""
GitDate = ""
)
func main() {
oplog.SetupDefaults()
app := cli.NewApp()
app.Flags = endpointMonitor.CLIFlags("ENDPOINT_MONITOR")
app.Version = opservice.FormatVersion(Version, GitCommit, GitDate, "")
app.Name = "endpoint-monitor"
app.Usage = "Endpoint Monitoring Service"
app.Description = ""
app.Action = endpointMonitor.Main(Version)
err := app.Run(os.Args)
if err != nil {
log.Crit("Application failed", "message", err)
}
}
package app
import (
"fmt"
"os"
"strings"
"time"
opservice "github.com/ethereum-optimism/optimism/op-service"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/urfave/cli/v2"
)
type ProviderConfig struct {
Name string
Url string
}
const (
ProvidersFlagName = "providers"
CheckIntervalFlagName = "check-interval"
CheckDurationFlagName = "check-duration"
)
func CLIFlags(envPrefix string) []cli.Flag {
prefixEnvVars := func(name string) []string {
return opservice.PrefixEnvVar(envPrefix, name)
}
flags := []cli.Flag{
&cli.StringSliceFlag{
Name: ProvidersFlagName,
Usage: "List of providers",
Required: true,
EnvVars: prefixEnvVars("PROVIDERS"),
},
&cli.DurationFlag{
Name: CheckIntervalFlagName,
Usage: "Check interval duration",
Value: 5 * time.Minute,
EnvVars: prefixEnvVars("CHECK_INTERVAL"),
},
&cli.DurationFlag{
Name: CheckDurationFlagName,
Usage: "Check duration",
Value: 4 * time.Minute,
EnvVars: prefixEnvVars("CHECK_DURATION"),
},
}
flags = append(flags, opmetrics.CLIFlags(envPrefix)...)
flags = append(flags, oplog.CLIFlags(envPrefix)...)
return flags
}
type Config struct {
Providers []string
CheckInterval time.Duration
CheckDuration time.Duration
LogConfig oplog.CLIConfig
MetricsConfig opmetrics.CLIConfig
}
func (c Config) Check() error {
if c.CheckDuration >= c.CheckInterval {
return fmt.Errorf("%s must be less than %s", CheckDurationFlagName, CheckIntervalFlagName)
}
if err := c.MetricsConfig.Check(); err != nil {
return err
}
return nil
}
func NewConfig(ctx *cli.Context) Config {
return Config{
Providers: ctx.StringSlice(ProvidersFlagName),
CheckInterval: ctx.Duration(CheckIntervalFlagName),
CheckDuration: ctx.Duration(CheckDurationFlagName),
LogConfig: oplog.ReadCLIConfig(ctx),
MetricsConfig: opmetrics.ReadCLIConfig(ctx),
}
}
// GetProviderConfigs fetches endpoint provider configurations from the environment
// Each provider should have a corresponding env var with the url, ex: PROVIDER1_URL=<provider-url>
func (c Config) GetProviderConfigs() []ProviderConfig {
result := make([]ProviderConfig, 0)
for _, provider := range c.Providers {
envKey := fmt.Sprintf("ENDPOINT_MONITOR_%s_URL", strings.ToUpper(provider))
url := os.Getenv(envKey)
if url == "" {
panic(fmt.Sprintf("%s is not set", envKey))
}
result = append(result, ProviderConfig{Name: provider, Url: url})
}
return result
}
package app
import (
"context"
"fmt"
"strings"
"time"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum-optimism/optimism/op-service/opio"
)
var (
MetricWsSubscribeStatus = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "ws_subscribe_status",
Help: "eth_subscribe over websocket check status"},
[]string{"status", "provider", "error"},
)
)
func Main(version string) func(cliCtx *cli.Context) error {
return func(cliCtx *cli.Context) error {
cfg := NewConfig(cliCtx)
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid CLI flags: %w", err)
}
l := oplog.NewLogger(oplog.AppOut(cliCtx), cfg.LogConfig)
oplog.SetGlobalLogHandler(l.Handler())
endpointMonitor := NewEndpointMonitor(cfg, l)
l.Info(fmt.Sprintf("starting endpoint monitor with checkInterval=%s checkDuration=%s", cfg.CheckInterval, cfg.CheckDuration))
endpointMonitor.Start()
registry := opmetrics.NewRegistry()
registry.MustRegister(MetricWsSubscribeStatus)
metricsCfg := cfg.MetricsConfig
l.Info("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort)
srv, err := opmetrics.StartServer(registry, metricsCfg.ListenAddr, metricsCfg.ListenPort)
if err != nil {
l.Error("error starting metrics server", err)
return err
}
defer func() {
if err := srv.Stop(cliCtx.Context); err != nil {
l.Error("failed to stop metrics server", "err", err)
}
}()
opio.BlockOnInterrupts()
return nil
}
}
type EndpointMonitor struct {
cfg Config
logger log.Logger
}
func NewEndpointMonitor(cfg Config, l log.Logger) EndpointMonitor {
return EndpointMonitor{cfg: cfg, logger: l}
}
func (e EndpointMonitor) Start() {
for _, providerConfig := range e.cfg.GetProviderConfigs() {
go e.runWebsocketCheckLoop(providerConfig, e.cfg.CheckInterval, e.cfg.CheckDuration)
}
}
// getWrappingErrorMsg returns the most recently wrapped error message
// it's used in this case to get the error type reported by runSubscribeCallCheck
func getWrappingErrorMsg(err error) string {
cause := errors.Cause(err)
return strings.TrimSuffix(err.Error(), fmt.Sprintf(": %s", cause.Error()))
}
// runWebsocketCheckLoop runs subscribe call checks every checkInterval and reports status metrics to prometheus
func (e EndpointMonitor) runWebsocketCheckLoop(p ProviderConfig, checkInterval, checkDuration time.Duration) {
ticker := time.NewTicker(checkInterval)
defer ticker.Stop()
for {
e.logger.Info("running websocket check", "provider", p.Name)
err := e.runWebsocketCheck(p, checkDuration)
if err != nil {
errType := getWrappingErrorMsg(err)
MetricWsSubscribeStatus.With(prometheus.Labels{"provider": p.Name, "status": "error", "error": errType}).Inc()
e.logger.Error("finished websocket check", "provider", p.Name, "error", errType)
} else {
MetricWsSubscribeStatus.With(prometheus.Labels{"provider": p.Name, "status": "success", "error": ""}).Inc()
e.logger.Info("finished websocket check", "provider", p.Name)
}
<-ticker.C
}
}
// runWebsocketCheck creates a client and subscribes to blockchain head notifications and returns any errors encountered for reporting
func (e EndpointMonitor) runWebsocketCheck(p ProviderConfig, duration time.Duration) error {
client, err := ethclient.Dial(p.Url)
if err != nil {
return errors.Wrap(err, "dial")
}
defer client.Close()
headers := make(chan *types.Header)
sub, err := client.SubscribeNewHead(context.Background(), headers)
if err != nil {
return errors.Wrap(err, "eth_subscribe_failed")
}
receivedData := false
ticker := time.NewTicker(duration)
defer ticker.Stop()
for {
select {
case <-ticker.C:
sub.Unsubscribe()
if !receivedData {
return errors.New("nodata")
}
return nil
case err := <-sub.Err():
return errors.Wrap(err, "read")
case header := <-headers:
e.logger.Debug(header.Hash().Hex(), "provider", p.Name)
receivedData = true
}
}
}
{
"name": "@eth-optimism/endpoint-monitor",
"version": "1.0.4",
"private": true,
"dependencies": {}
}
...@@ -114,8 +114,6 @@ importers: ...@@ -114,8 +114,6 @@ importers:
specifier: ^7.2.0 specifier: ^7.2.0
version: 7.2.0 version: 7.2.0
endpoint-monitor: {}
indexer/api-ts: indexer/api-ts:
devDependencies: devDependencies:
tsup: tsup:
......
packages: packages:
- 'packages/*' - 'packages/*'
- 'endpoint-monitor'
- 'indexer/api-ts' - 'indexer/api-ts'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment