Skip to content

Commit

Permalink
refresh template
Browse files Browse the repository at this point in the history
  • Loading branch information
dvush committed Sep 25, 2024
1 parent ef41d7f commit e7cdc74
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 60 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: ^1.21
go-version: ^1.22
id: go

- name: Check out code into the Go module directory
Expand All @@ -30,7 +30,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: ^1.21
go-version: ^1.22
id: go

- name: Check out code into the Go module directory
Expand All @@ -40,7 +40,7 @@ jobs:
run: go install mvdan.cc/[email protected]

- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@v0.4.2
run: go install honnef.co/go/tools/cmd/staticcheck@2024.1.1

- name: Install golangci-lint
run: go install github.com/golangci/golangci-lint/cmd/[email protected]
Expand Down
13 changes: 3 additions & 10 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,30 @@ linters:
- nlreturn
- noctx
- nonamedreturns
- nosnakecase
- paralleltest
- revive
- testpackage
- unparam
- varnamelen
- wrapcheck
- wsl
- deadcode
- varcheck
- exhaustruct
- depguard
- err113

#
# Disabled because of generics:
#
- contextcheck
- rowserrcheck
- sqlclosecheck
- structcheck
- wastedassign

#
# Disabled because deprecated:
#
- exhaustivestruct
- golint
- ifshort
- interfacer
- maligned
- scopelint
- execinquery
- exportloopref

linters-settings:
#
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ lint: ## Run linters
go vet ./...
staticcheck ./...
golangci-lint run
nilaway ./...
# nilaway ./...

.PHONY: fmt
fmt: ## Format the code
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# go-template

[![Goreport status](https://goreportcard.com/badge/github.com/flashbots/go-template)](https://goreportcard.com/report/github.com/flashbots/go-template)
[![Test status](https://github.com/flashbots/go-template/workflows/Checks/badge.svg?branch=main)](https://github.com/flashbots/go-template/actions?query=workflow%3A%22Checks%22)
[![Test status](https://github.com/flashbots/go-template/actions/workflows/checks.yml/badge.svg?branch=main)](https://github.com/flashbots/go-template/actions?query=workflow%3A%22Checks%22)

Toolbox and building blocks for new Go projects, to get started quickly and right-footed!

Expand Down
2 changes: 1 addition & 1 deletion cli.dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM golang:1.21 AS builder
FROM golang:1.23 AS builder
ARG VERSION
WORKDIR /build
ADD go.mod /build/
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/flashbots/go-template

go 1.21
go 1.22

require (
github.com/flashbots/go-utils v0.6.1-0.20240610084140-4461ab748667
Expand Down
2 changes: 1 addition & 1 deletion httpserver.dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM golang:1.21 AS builder
FROM golang:1.23 AS builder
ARG VERSION
WORKDIR /build
ADD go.mod /build/
Expand Down
24 changes: 12 additions & 12 deletions httpserver/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/flashbots/go-template/metrics"
)

func (s *Server) handleAPI(w http.ResponseWriter, r *http.Request) {
m := s.metricsSrv.Float64Histogram(
func (srv *Server) handleAPI(w http.ResponseWriter, r *http.Request) {
m := srv.metricsSrv.Float64Histogram(
"request_duration_api",
"API request handling duration",
metrics.UomMicroseconds,
Expand All @@ -23,32 +23,32 @@ func (s *Server) handleAPI(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}

func (s *Server) handleLivenessCheck(w http.ResponseWriter, r *http.Request) {
func (srv *Server) handleLivenessCheck(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}

func (s *Server) handleReadinessCheck(w http.ResponseWriter, r *http.Request) {
if !s.isReady.Load() {
func (srv *Server) handleReadinessCheck(w http.ResponseWriter, r *http.Request) {
if !srv.isReady.Load() {
w.WriteHeader(http.StatusServiceUnavailable)
return
}

w.WriteHeader(http.StatusOK)
}

func (s *Server) handleDrain(w http.ResponseWriter, r *http.Request) {
if wasReady := s.isReady.Swap(false); !wasReady {
func (srv *Server) handleDrain(w http.ResponseWriter, r *http.Request) {
if wasReady := srv.isReady.Swap(false); !wasReady {
return
}
// l := logutils.ZapFromRequest(r)
s.log.Info("Server marked as not ready")
time.Sleep(s.cfg.DrainDuration) // Give LB enough time to detect us not ready
srv.log.Info("Server marked as not ready")
time.Sleep(srv.cfg.DrainDuration) // Give LB enough time to detect us not ready
}

func (s *Server) handleUndrain(w http.ResponseWriter, r *http.Request) {
if wasReady := s.isReady.Swap(true); wasReady {
func (srv *Server) handleUndrain(w http.ResponseWriter, r *http.Request) {
if wasReady := srv.isReady.Swap(true); wasReady {
return
}
// l := logutils.ZapFromRequest(r)
s.log.Info("Server marked as ready")
srv.log.Info("Server marked as ready")
}
18 changes: 18 additions & 0 deletions httpserver/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,21 @@ func Test_Handlers_Healthcheck_Drain_Undrain(t *testing.T) {
require.Equal(t, http.StatusOK, resp.StatusCode, "Healthcheck must return `Ok` after undraining")
}
}

func Test_Handlers_Simple(t *testing.T) {
// This test doesn't need the server to actually start and serve. Instead it just tests the handlers.
//nolint: exhaustruct
srv, err := New(&HTTPServerConfig{
Log: getTestLogger(),
})
require.NoError(t, err)

{ // Check health
req, err := http.NewRequest(http.MethodGet, "/readyz", nil) //nolint:goconst,nolintlint
require.NoError(t, err)

rr := httptest.NewRecorder()
srv.getRouter().ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code)
}
}
63 changes: 33 additions & 30 deletions httpserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,72 +50,75 @@ func New(cfg *HTTPServerConfig) (srv *Server, err error) {
}
srv.isReady.Swap(true)

srv.srv = &http.Server{
Addr: cfg.ListenAddr,
Handler: srv.getRouter(),
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
}

return srv, nil
}

func (srv *Server) getRouter() http.Handler {
mux := chi.NewRouter()
mux.With(srv.httpLogger).Get("/api", srv.handleAPI) // Never serve at `/` (root) path
mux.With(srv.httpLogger).Get("/livez", srv.handleLivenessCheck)
mux.With(srv.httpLogger).Get("/readyz", srv.handleReadinessCheck)
mux.With(srv.httpLogger).Get("/drain", srv.handleDrain)
mux.With(srv.httpLogger).Get("/undrain", srv.handleUndrain)

if cfg.EnablePprof {
if srv.cfg.EnablePprof {
srv.log.Info("pprof API enabled")
mux.Mount("/debug", middleware.Profiler())
}

srv.srv = &http.Server{
Addr: cfg.ListenAddr,
Handler: mux,
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
}

return srv, nil
return mux
}

func (s *Server) httpLogger(next http.Handler) http.Handler {
return httplogger.LoggingMiddlewareSlog(s.log, next)
func (srv *Server) httpLogger(next http.Handler) http.Handler {
return httplogger.LoggingMiddlewareSlog(srv.log, next)
}

func (s *Server) RunInBackground() {
func (srv *Server) RunInBackground() {
// metrics
if s.cfg.MetricsAddr != "" {
if srv.cfg.MetricsAddr != "" {
go func() {
s.log.With("metricsAddress", s.cfg.MetricsAddr).Info("Starting metrics server")
err := s.metricsSrv.ListenAndServe()
srv.log.With("metricsAddress", srv.cfg.MetricsAddr).Info("Starting metrics server")
err := srv.metricsSrv.ListenAndServe()
if err != nil && !errors.Is(err, http.ErrServerClosed) {
s.log.Error("HTTP server failed", "err", err)
srv.log.Error("HTTP server failed", "err", err)
}
}()
}

// api
go func() {
s.log.Info("Starting HTTP server", "listenAddress", s.cfg.ListenAddr)
if err := s.srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
s.log.Error("HTTP server failed", "err", err)
srv.log.Info("Starting HTTP server", "listenAddress", srv.cfg.ListenAddr)
if err := srv.srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
srv.log.Error("HTTP server failed", "err", err)
}
}()
}

func (s *Server) Shutdown() {
func (srv *Server) Shutdown() {
// api
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.GracefulShutdownDuration)
ctx, cancel := context.WithTimeout(context.Background(), srv.cfg.GracefulShutdownDuration)
defer cancel()
if err := s.srv.Shutdown(ctx); err != nil {
s.log.Error("Graceful HTTP server shutdown failed", "err", err)
if err := srv.srv.Shutdown(ctx); err != nil {
srv.log.Error("Graceful HTTP server shutdown failed", "err", err)
} else {
s.log.Info("HTTP server gracefully stopped")
srv.log.Info("HTTP server gracefully stopped")
}

// metrics
if len(s.cfg.MetricsAddr) != 0 {
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.GracefulShutdownDuration)
if len(srv.cfg.MetricsAddr) != 0 {
ctx, cancel := context.WithTimeout(context.Background(), srv.cfg.GracefulShutdownDuration)
defer cancel()

if err := s.metricsSrv.Shutdown(ctx); err != nil {
s.log.Error("Graceful metrics server shutdown failed", "err", err)
if err := srv.metricsSrv.Shutdown(ctx); err != nil {
srv.log.Error("Graceful metrics server shutdown failed", "err", err)
} else {
s.log.Info("Metrics server gracefully stopped")
srv.log.Info("Metrics server gracefully stopped")
}
}
}
7 changes: 7 additions & 0 deletions metrics/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# metrics

This example metrics module uses the OpenTelemetry package.

A solid alternative is [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics), see an example
implementation here: https://github.com/flashbots/mev-share-node/blob/main/metrics/metrics.go

---

Introduction:
- https://opentelemetry.io/docs/languages/go/instrumentation/

Expand Down

0 comments on commit e7cdc74

Please sign in to comment.