diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a39e6c4 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +.PHONY: build test + +build: + go build -o build/ + +test: + go test -v ./... diff --git a/build/heartbeat-server b/build/heartbeat-server new file mode 100755 index 0000000..e606ec0 Binary files /dev/null and b/build/heartbeat-server differ diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..007a887 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module git.faercol.me/monitoring/heartbeat-server + +go 1.16 + +require github.com/sirupsen/logrus v1.9.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ed65537 --- /dev/null +++ b/go.sum @@ -0,0 +1,15 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..58b4f9f --- /dev/null +++ b/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "context" + + "git.faercol.me/monitoring/heartbeat-server/server" + "github.com/sirupsen/logrus" +) + +func main() { + addr := "localhost:9000" + logger := logrus.New() + + srv, err := server.New(addr, logger) + if err != nil { + logger.Fatalf("Failed to create HTTP server: %s", err.Error()) + } + + srv.Run(context.Background()) +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..48c6bc0 --- /dev/null +++ b/server/server.go @@ -0,0 +1,59 @@ +package server + +import ( + "context" + "fmt" + "net" + "net/http" + + "github.com/sirupsen/logrus" +) + +type Server struct { + ctx context.Context + cancel context.CancelFunc + httpSrv *http.Server + listener net.Listener + handler *http.ServeMux + logger *logrus.Logger +} + +func (s *Server) initMux() { + s.handler.HandleFunc("/", s.heartbeatHandler) +} + +func (s *Server) heartbeatHandler(w http.ResponseWriter, r *http.Request) { + remoteHost, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + s.logger.Warnf("Unexpected remote address %s: %q", r.RemoteAddr, err.Error()) + } else { + s.logger.Infof("Received a heartbeat query from %s", remoteHost) + } + w.WriteHeader(http.StatusNoContent) +} + +func (s *Server) Run(ctx context.Context) { + s.ctx, s.cancel = context.WithCancel(ctx) + s.initMux() + if err := s.httpSrv.Serve(s.listener); err != nil { + s.logger.Errorf("Failed to serve HTTP server: %s", err.Error()) + } +} + +func New(addr string, logger *logrus.Logger) (*Server, error) { + m := http.NewServeMux() + l, err := net.Listen("tcp", addr) + if err != nil { + return nil, fmt.Errorf("failed to setup listener on addr %q: %w", addr, err) + } + + return &Server{ + ctx: context.TODO(), + httpSrv: &http.Server{ + Handler: m, + }, + handler: m, + listener: l, + logger: logger, + }, nil +}