Skip to content

Commit

Permalink
refactor: switch to slog and upgrade deps
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-karan committed Feb 23, 2024
1 parent 0dd4b97 commit 7174e47
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.21
go-version: 1.22

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ bin/
data/
dist/
*.idea/
.cache/
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ build: ## Build binary.

.PHONY: run
run: ## Run binary.
./${APP-BIN}
./${APP-BIN} --config ./config.toml

.PHONY: clean
clean: ## Remove temporary files and the `bin` folder.
Expand All @@ -27,10 +27,10 @@ lint:
.PHONY: dev-docker
dev-docker: clean build ## Build and spawns docker containers for the entire suite (Alertmanager/Prometheus/calert).
cd dev; \
docker-compose build ; \
CURRENT_UID=$(id -u):$(id -g) docker-compose up
echo "Current UID: $(shell id -u):$(shell id -g)"; \
CURRENT_UID=$(shell id -u):$(shell id -g) docker compose up

.PHONY: rm-dev-docker
rm-dev-docker: clean build ## Delete the docker containers including volumes.
cd dev; \
docker-compose down -v ; \
docker compose down -v ; \
6 changes: 3 additions & 3 deletions cmd/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func handleDispatchNotif(w http.ResponseWriter, r *http.Request) {

// Unmarshall POST Body.
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
app.lo.WithError(err).Error("error decoding request body")
app.lo.Error("error decoding request body", "error", err)
app.metrics.Increment(`http_request_errors_total{handler="dispatch"}`)
sendErrorResponse(w, "Error decoding payload.", http.StatusBadRequest, nil)
return
Expand All @@ -99,14 +99,14 @@ func handleDispatchNotif(w http.ResponseWriter, r *http.Request) {
roomName = payload.Receiver
}

app.lo.WithField("receiver", roomName).Info("dispatching new alert")
app.lo.Info("dispatching new alert", "room", roomName, "count", len(payload.Alerts))

// Dispatch a list of alerts via Notifier.
// If there are a lot of alerts (>=10) to push, G-Chat API can be extremely slow to add messages
// to an existing thread. So it's better to enqueue it in background.
go func() {
if err := app.notifier.Dispatch(payload.Alerts, roomName); err != nil {
app.lo.WithError(err).Error("error dispatching alerts")
app.lo.Error("error dispatching alerts", "error", err)
app.metrics.Increment(`http_request_errors_total{handler="dispatch"}`)
}
app.metrics.Duration(`http_request_duration_seconds{handler="dispatch"}`, now)
Expand Down
44 changes: 23 additions & 21 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"fmt"
"log"
"log/slog"
"os"
"strings"

Expand All @@ -13,24 +15,24 @@ import (
"github.com/mr-karan/calert/internal/notifier"
prvs "github.com/mr-karan/calert/internal/providers"
"github.com/mr-karan/calert/internal/providers/google_chat"
"github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
)

// initLogger initializes logger instance.
func initLogger() *logrus.Logger {
logger := logrus.New()

logger.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
DisableLevelTruncation: true,
})
func initLogger(verbose bool) *slog.Logger {
lvl := slog.LevelInfo
if verbose {
lvl = slog.LevelDebug
}

return logger
return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: lvl,
AddSource: true,
}))
}

// initConfig loads config to `ko` object.
func initConfig(lo *logrus.Logger, cfgDefault string, envPrefix string) (*koanf.Koanf, error) {
func initConfig(cfgDefault string, envPrefix string) (*koanf.Koanf, error) {
var (
ko = koanf.New(".")
f = flag.NewFlagSet("front", flag.ContinueOnError)
Expand All @@ -52,19 +54,19 @@ func initConfig(lo *logrus.Logger, cfgDefault string, envPrefix string) (*koanf.
}

// Load the config files from the path provided.
lo.WithField("path", *cfgPath).Info("attempting to load config from file")
log.Printf("attempting to load config from file: %s\n", *cfgPath)

err = ko.Load(file.Provider(*cfgPath), toml.Parser())
if err != nil {
// If the default config is not present, print a warning and continue reading the values from env.
if *cfgPath == cfgDefault {
lo.WithError(err).Warn("unable to open sample config file")
log.Printf("unable to open config file: %w falling back to env vars\n", err.Error())
} else {
return nil, err
}
}

lo.Info("attempting to read config from env vars")
log.Println("attempting to read config from env vars")
// Load environment variables if the key is given
// and merge into the loaded config.
if envPrefix != "" {
Expand All @@ -81,7 +83,7 @@ func initConfig(lo *logrus.Logger, cfgDefault string, envPrefix string) (*koanf.
}

// initProviders loads all the providers specified in the config.
func initProviders(ko *koanf.Koanf, lo *logrus.Logger, metrics *metrics.Manager) []prvs.Provider {
func initProviders(ko *koanf.Koanf, lo *slog.Logger, metrics *metrics.Manager) ([]prvs.Provider, error) {
provs := make([]prvs.Provider, 0)

// Loop over all providers listed in config.
Expand All @@ -106,32 +108,32 @@ func initProviders(ko *koanf.Koanf, lo *logrus.Logger, metrics *metrics.Manager)
},
)
if err != nil {
lo.WithError(err).Fatal("error initialising google chat provider")
return nil, fmt.Errorf("error initialising google chat provider: %s", err)
}

lo.WithField("room", gchat.Room()).Info("initialised provider")
lo.Info("initialised provider", "room", gchat.Room())
provs = append(provs, gchat)
}
}

if len(provs) == 0 {
lo.Fatal("no providers listed in config")
return nil, fmt.Errorf("no providers listed in config")
}

return provs
return provs, nil
}

// initNotifier initializes a Notifier instance.
func initNotifier(ko *koanf.Koanf, lo *logrus.Logger, provs []prvs.Provider) notifier.Notifier {
func initNotifier(ko *koanf.Koanf, lo *slog.Logger, provs []prvs.Provider) (notifier.Notifier, error) {
n, err := notifier.Init(notifier.Opts{
Providers: provs,
Log: lo,
})
if err != nil {
lo.WithError(err).Fatal("error initialising notifier")
return notifier.Notifier{}, fmt.Errorf("error initialising notifier: %s", err)
}

return n
return n, err
}

// initMetrics initializes a Metrics manager.
Expand Down
50 changes: 33 additions & 17 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package main

import (
"net/http"
"os"

"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/mr-karan/calert/internal/metrics"
"github.com/mr-karan/calert/internal/notifier"

"github.com/sirupsen/logrus"
"log/slog"
)

var (
Expand All @@ -19,31 +20,41 @@ var (
// App is the global contains
// instances of various objects used in the lifecyle of program.
type App struct {
lo *logrus.Logger
lo *slog.Logger
metrics *metrics.Manager
notifier notifier.Notifier
}

func main() {
// Initialise logger.
lo := initLogger()

// Initialise and load the config.
ko, err := initConfig(lo, "config.sample.toml", "CALERT_")
ko, err := initConfig("config.sample.toml", "CALERT_")
if err != nil {
// Need to `panic` since logger can only be initialised once config is initialised.
panic(err.Error())
}

var (
metrics = initMetrics()
provs = initProviders(ko, lo, metrics)
notifier = initNotifier(ko, lo, provs)
metrics = initMetrics()
)

// Enable debug mode if specified.
// Initialise logger.
verbose := false
if ko.String("app.log") == "debug" {
lo.SetLevel(logrus.DebugLevel)
verbose = true
}
lo := initLogger(verbose)

// Initialise providers.
provs, err := initProviders(ko, lo, metrics)
if err != nil {
lo.Error("error initialising providers", "error", err)
exit()
}

// Initialise notifier.
notifier, err := initNotifier(ko, lo, provs)
if err != nil {
lo.Error("error initialising notifier", "error", err)
exit()
}

app := &App{
Expand All @@ -52,7 +63,7 @@ func main() {
metrics: metrics,
}

app.lo.WithField("version", buildString).Info("booting calert")
app.lo.Info("starting calert", "version", buildString, "verbose", verbose)

// Initialise HTTP Router.
r := chi.NewRouter()
Expand All @@ -70,14 +81,19 @@ func main() {
r.Post("/dispatch", wrap(app, handleDispatchNotif))

// Start HTTP Server.
app.lo.WithField("addr", ko.MustString("app.address")).Info("starting http server")
app.lo.Info("starting http server", "address", ko.MustString("app.address"))
srv := &http.Server{
Addr: ko.MustString("app.address"),
ReadTimeout: ko.MustDuration("app.server_timeout"),
WriteTimeout: ko.MustDuration("app.server_timeout"),
Handler: r,
}
if err := srv.ListenAndServe(); err != nil {
app.lo.WithError(err).Fatal("couldn't start server")
app.lo.Error("couldn't start server", "error", err)
exit()
}
}

func exit() {
os.Exit(1)
}
15 changes: 13 additions & 2 deletions dev/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
FROM golang:1.18 as builder
# Disable CGO
FROM golang:1.22 as builder

ENV CGO_ENABLED=0
WORKDIR /app

# Prepare cache directories and ensure correct permissions
RUN mkdir -p /app/.cache/go-build /app/.cache/go-mod && \
chown -R 1000:1000 /app/.cache

# Switch to non-root user
USER 1000:1000

# Set environment variables for caches
ENV GOCACHE=/app/.cache/go-build
ENV GOMODCACHE=/app/.cache/go-mod
12 changes: 7 additions & 5 deletions dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ networks:
driver: bridge

volumes:
prometheus_data: {}
prometheus_data: {}

services:

calert:
build:
context: ../
dockerfile: dev/Dockerfile.dev
command: ["make", "fresh"]
command: [ "make", "fresh" ]
ports:
- "6000:6000"
volumes:
- ../:/app
- $GOPATH/pkg/mod/cache:/go/pkg/mod/cache
networks:
- monitor-net
user: ${CURRENT_UID}
environment:
- GOCACHE=/app/.cache/go-build
- GOMODCACHE=/app/.cache/go-mod

alertmanager:
image: prom/alertmanager:v0.23.0
image: prom/alertmanager:v0.26.0
container_name: alertmanager
volumes:
- ./alertmanager:/etc/alertmanager
Expand All @@ -38,7 +40,7 @@ services:
- calert

prometheus:
image: prom/prometheus:v2.32.1
image: prom/prometheus:v2.50.0
container_name: prometheus
volumes:
- ./prometheus:/etc/prometheus
Expand Down
18 changes: 8 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
module github.com/mr-karan/calert

require (
github.com/VictoriaMetrics/metrics v1.24.0
github.com/go-chi/chi v1.5.5
github.com/VictoriaMetrics/metrics v1.32.0
github.com/go-chi/chi/v5 v5.0.12
github.com/gofrs/uuid v4.4.0+incompatible
github.com/knadh/koanf v1.5.0
github.com/prometheus/alertmanager v0.26.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
golang.org/x/text v0.14.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect
github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.47.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect
github.com/valyala/fastrand v1.1.0 // indirect
github.com/valyala/histogram v1.2.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
golang.org/x/sys v0.17.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

Expand Down
Loading

0 comments on commit 7174e47

Please sign in to comment.