Skip to content

Commit

Permalink
feat: implement basic functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
0x416e746f6e committed May 27, 2024
1 parent a3eb402 commit b0104da
Show file tree
Hide file tree
Showing 30 changed files with 1,723 additions and 0 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: release

on:
workflow_dispatch:
push:
tags:
- "v*"

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4

- name: setup go dependencies
uses: actions/setup-go@v5
with:
go-version: "1.22"

- name: setup quemu
uses: docker/setup-qemu-action@v3

- name: setup docker buildx
uses: docker/setup-buildx-action@v3

- name: login to docker hub
uses: docker/login-action@v2
with:
username: ${{ secrets.FLASHBOTS_DOCKERHUB_USERNAME }}
password: ${{ secrets.FLASHBOTS_DOCKERHUB_TOKEN }}

- name: login to ghcr
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: build and publish backend release
uses: goreleaser/goreleaser-action@v5
with:
args: release --clean
distribution: goreleaser
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56 changes: 56 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
env:
- CGO_ENABLED=0

builds:
- main: ./cmd
ldflags:
- -s
- -w
- -X main.version={{ .Version }}
targets:
- linux_amd64
- linux_arm64

archives:
- id: zip
format: zip
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"
files:
- none*

checksum:
name_template: 'checksums.txt'

release:
prerelease: auto

dockers:
- dockerfile: Dockerfile.goreleaser
goarch: amd64
goos: linux
use: buildx
build_flag_templates:
- --platform=linux/amd64
image_templates:
- "flashbots/latency-monitor:{{ .Tag }}-amd64"
- "ghcr.io/flashbots/latency-monitor:{{ .Tag }}-amd64"

- dockerfile: Dockerfile.goreleaser
goarch: arm64
goos: linux
use: buildx
build_flag_templates:
- --platform=linux/arm64
image_templates:
- "flashbots/latency-monitor:{{ .Tag }}-arm64"
- "ghcr.io/flashbots/latency-monitor:{{ .Tag }}-arm64"

docker_manifests:
- name_template: "flashbots/latency-monitor:{{ .Tag }}"
image_templates:
- "flashbots/latency-monitor:{{ .Tag }}-amd64"
- "flashbots/latency-monitor:{{ .Tag }}-arm64"
- name_template: "ghcr.io/flashbots/latency-monitor:{{ .Tag }}"
image_templates:
- "ghcr.io/flashbots/latency-monitor:{{ .Tag }}-amd64"
- "ghcr.io/flashbots/latency-monitor:{{ .Tag }}-arm64"
26 changes: 26 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# stage: build ---------------------------------------------------------

FROM golang:1.22-alpine as build

RUN apk add --no-cache gcc musl-dev linux-headers

WORKDIR /go/src/github.com/flashbots/latency-monitor

COPY go.* ./
RUN go mod download

COPY . .

RUN go build -o bin/latency-monitor -ldflags "-s -w" github.com/flashbots/latency-monitor/cmd

# stage: run -----------------------------------------------------------

FROM alpine

RUN apk add --no-cache ca-certificates

WORKDIR /app

COPY --from=build /go/src/github.com/flashbots/latency-monitor/bin/latency-monitor ./latency-monitor

ENTRYPOINT ["/app/latency-monitor"]
9 changes: 9 additions & 0 deletions Dockerfile.goreleaser
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# stage: run

FROM gcr.io/distroless/static-debian12 as runner

WORKDIR /app

COPY latency-monitor ./

ENTRYPOINT [ "./latency-monitor" ]
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
VERSION := $(shell git describe --tags --always --dirty="-dev" --match "v*.*.*" || echo "development" )
VERSION := $(VERSION:v%=%)

.PHONY: build
build:
@CGO_ENABLED=0 go build \
-ldflags "-X main.version=${VERSION}" \
-o ./bin/latency-monitor \
github.com/flashbots/latency-monitor/cmd

.PHONY: snapshot
snapshot:
@goreleaser release --snapshot --clean
Empty file added bin/.gitkeep
Empty file.
81 changes: 81 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package main

import (
"fmt"
"os"

"github.com/flashbots/latency-monitor/config"
"github.com/flashbots/latency-monitor/logutils"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
)

var (
version = "development"
)

const (
envPrefix = "LATENCY_MONITOR_"
)

func main() {
cfg := &config.Config{}

flags := []cli.Flag{
&cli.StringFlag{
Destination: &cfg.Log.Level,
EnvVars: []string{envPrefix + "LOG_LEVEL"},
Name: "log-level",
Usage: "logging level",
Value: "info",
},

&cli.StringFlag{
Destination: &cfg.Log.Mode,
EnvVars: []string{envPrefix + "LOG_MODE"},
Name: "log-mode",
Usage: "logging mode",
Value: "prod",
},
}

commands := []*cli.Command{
CommandServe(cfg),
}

app := &cli.App{
Name: "latency-monitor",
Usage: "Monitors latency between the nodes",
Version: version,

Flags: flags,
Commands: commands,
DefaultCommand: commands[0].Name,

Before: func(_ *cli.Context) error {
// setup logger
l, err := logutils.NewLogger(&cfg.Log)
if err != nil {
return err
}
zap.ReplaceGlobals(l)

// inject version
cfg.Metrics.MetricsVersion = version

return nil
},

Action: func(clictx *cli.Context) error {
return cli.ShowAppHelp(clictx)
},
}

defer func() {
zap.L().Sync() //nolint:errcheck
}()
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "\nFailed with error:\n\n%s\n\n", err.Error())
os.Exit(1)
}
}
124 changes: 124 additions & 0 deletions cmd/serve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import (
"slices"
"time"

"github.com/flashbots/latency-monitor/config"
"github.com/flashbots/latency-monitor/server"
"github.com/flashbots/latency-monitor/types"
"github.com/urfave/cli/v2"
)

const (
categoryMetrics = "METRICS:"
categoryServer = "SERVER:"
categoryTransponder = "TRANSPONDER:"
)

func CommandServe(cfg *config.Config) *cli.Command {
transponderPeers := &cli.StringSlice{}

metricsFlags := []cli.Flag{
&cli.StringFlag{
Category: categoryMetrics,
Destination: &cfg.Metrics.ListenAddress,
EnvVars: []string{envPrefix + "METRICS_LISTEN_ADDRESS"},
Name: "metrics-listen-address",
Usage: "`host:port` for the metrics-server to listen on",
Value: "0.0.0.0:8080",
},

&cli.IntFlag{
Category: categoryMetrics,
Destination: &cfg.Metrics.LatencyBucketsCount,
EnvVars: []string{envPrefix + "METRICS_LATENCY_BUCKETS_COUNT"},
Name: "metrics-latency-buckets-count",
Usage: "`count` of latency histogram buckets",
Value: 33,
},

&cli.IntFlag{
Category: categoryMetrics,
Destination: &cfg.Metrics.MaxLatencyUs,
EnvVars: []string{envPrefix + "METRICS_MAX_LATENCY"},
Name: "metrics-max-latency",
Usage: "`microseconds` value for the largest histogram latency bucket",
Value: 1000000,
},
}

transponderFlags := []cli.Flag{
&cli.DurationFlag{
Category: categoryTransponder,
Destination: &cfg.Transponder.Interval,
EnvVars: []string{envPrefix + "TRANSPONDER_INTERVAL"},
Name: "transponder-interval",
Usage: "`interval` at which the transponder should send its probes",
Value: time.Minute,
},

&cli.StringFlag{
Category: categoryTransponder,
Destination: &cfg.Transponder.ListenAddress,
EnvVars: []string{envPrefix + "TRANSPONDER_LISTEN_ADDRESS"},
Name: "transponder-listen-port",
Usage: "`host:port` for the transponder to listen on",
Value: "0.0.0.0:32123",
},

&cli.StringSliceFlag{
Category: categoryTransponder,
Destination: transponderPeers,
EnvVars: []string{envPrefix + "TRANSPONDER_PEER"},
Name: "transponder-peer",
Usage: "`name=host:port` of the transponder peer to measure the latency against",
Value: cli.NewStringSlice("localhost=127.0.0.1:32123"),
},
}

serverFlags := []cli.Flag{
&cli.StringFlag{
Category: categoryServer,
Destination: &cfg.Server.Name,
EnvVars: []string{envPrefix + "SERVER_NAME"},
Name: "server-name",
Usage: "service `name` to report in prometheus metrics",
Value: "latency-monitor",
},
}

flags := slices.Concat(
serverFlags,
metricsFlags,
transponderFlags,
)

return &cli.Command{
Name: "serve",
Usage: "run the monitor server",
Flags: flags,

Before: func(ctx *cli.Context) error {
p := transponderPeers.Value()
peers := make([]types.Peer, 0, len(p))
for _, s := range p {
peer, err := types.NewPeer(s)
if err != nil {
return err
}
peers = append(peers, peer)
}
cfg.Transponder.Peers = peers
return nil
},

Action: func(_ *cli.Context) error {
s, err := server.New(cfg)
if err != nil {
return err
}
return s.Run()
},
}
}
8 changes: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package config

type Config struct {
Log Log `yaml:"log"`
Metrics Metrics `yaml:"metrics"`
Transponder Transponder `yaml:"transponder"`
Server Server `yaml:"server"`
}
6 changes: 6 additions & 0 deletions config/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package config

type Log struct {
Level string `yaml:"level"`
Mode string `yaml:"mode"`
}
10 changes: 10 additions & 0 deletions config/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package config

type Metrics struct {
ListenAddress string `yaml:"metrics_listen_address"`

LatencyBucketsCount int `yaml:"metrics_latency_buckets_count"`
MaxLatencyUs int `yaml:"metrics_max_latency_us"`

MetricsVersion string `yaml:"metrics_version"`
}
5 changes: 5 additions & 0 deletions config/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package config

type Server struct {
Name string `yaml:"name"`
}
Loading

0 comments on commit b0104da

Please sign in to comment.