Add simple debug logging.
This commit is contained in:
parent
935d5d8109
commit
95c8181d2a
@ -12,6 +12,7 @@ import (
|
||||
"go.dev.pztrn.name/metricator/internal/common"
|
||||
"go.dev.pztrn.name/metricator/internal/configuration"
|
||||
"go.dev.pztrn.name/metricator/internal/httpserver"
|
||||
"go.dev.pztrn.name/metricator/internal/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -25,8 +26,6 @@ func main() {
|
||||
mainCtx, cancelFunc := context.WithCancel(context.Background())
|
||||
config := configuration.NewConfig()
|
||||
|
||||
httpSrv, httpStopped := httpserver.NewHTTPServer(mainCtx, config)
|
||||
|
||||
// Parse configuration.
|
||||
flag.Parse()
|
||||
|
||||
@ -40,8 +39,11 @@ func main() {
|
||||
// Create applications.
|
||||
apps := make([]*application.Application, 0, len(config.Applications))
|
||||
|
||||
logger := logger.NewLogger(config.Logger)
|
||||
httpSrv, httpStopped := httpserver.NewHTTPServer(mainCtx, config, logger)
|
||||
|
||||
for appName, appConfig := range config.Applications {
|
||||
app := application.NewApplication(mainCtx, appName, appConfig)
|
||||
app := application.NewApplication(mainCtx, appName, appConfig, logger)
|
||||
app.Start()
|
||||
|
||||
httpSrv.RegisterHandlerForApplication(appName, app.GetHandler())
|
||||
|
@ -2,11 +2,11 @@ package application
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"go.dev.pztrn.name/metricator/internal/common"
|
||||
"go.dev.pztrn.name/metricator/internal/logger"
|
||||
"go.dev.pztrn.name/metricator/internal/storage"
|
||||
"go.dev.pztrn.name/metricator/internal/storage/memory"
|
||||
)
|
||||
@ -17,6 +17,7 @@ type Application struct {
|
||||
config *Config
|
||||
ctx context.Context
|
||||
doneChan chan struct{}
|
||||
logger *logger.Logger
|
||||
name string
|
||||
|
||||
storage storage.Metrics
|
||||
@ -29,11 +30,12 @@ type Application struct {
|
||||
}
|
||||
|
||||
// NewApplication creates new application.
|
||||
func NewApplication(ctx context.Context, name string, config *Config) *Application {
|
||||
func NewApplication(ctx context.Context, name string, config *Config, logger *logger.Logger) *Application {
|
||||
a := &Application{
|
||||
config: config,
|
||||
ctx: ctx,
|
||||
doneChan: make(chan struct{}),
|
||||
logger: logger,
|
||||
name: name,
|
||||
}
|
||||
a.initialize()
|
||||
@ -54,9 +56,9 @@ func (a *Application) GetHandler() common.HTTPHandlerFunc {
|
||||
|
||||
// Initializes internal things like storage, HTTP client, etc.
|
||||
func (a *Application) initialize() {
|
||||
a.storage, a.storageDone = memory.NewStorage(a.ctx, a.name+" storage")
|
||||
a.storage, a.storageDone = memory.NewStorage(a.ctx, a.name+" storage", a.logger)
|
||||
|
||||
log.Printf("Application '%s' initialized with configuration: %+v\n", a.name, a.config)
|
||||
a.logger.Debugf("Application '%s' initialized with configuration: %+v\n", a.name, a.config)
|
||||
}
|
||||
|
||||
// Start starts asynchronous things like data fetching, storage cleanup, etc.
|
||||
@ -71,7 +73,7 @@ func (a *Application) Start() {
|
||||
// We should wait until storage routines are also stopped.
|
||||
<-a.storage.GetDoneChan()
|
||||
|
||||
log.Println("Application", a.name, "stopped")
|
||||
a.logger.Infoln("Application", a.name, "stopped")
|
||||
|
||||
a.doneChan <- struct{}{}
|
||||
}()
|
||||
|
@ -2,7 +2,6 @@ package application
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@ -23,11 +22,11 @@ func (a *Application) fetch() {
|
||||
a.fetchIsRunning = true
|
||||
a.fetchIsRunningMutex.Unlock()
|
||||
|
||||
log.Println("Fetching data for", a.name)
|
||||
a.logger.Infoln("Fetching data for", a.name)
|
||||
|
||||
req, err := http.NewRequestWithContext(a.ctx, "GET", a.config.Endpoint, nil)
|
||||
if err != nil {
|
||||
log.Println("Failed to create request for", a.name, "metrics:", err.Error())
|
||||
a.logger.Infoln("Failed to create request for", a.name, "metrics:", err.Error())
|
||||
|
||||
return
|
||||
}
|
||||
@ -38,7 +37,7 @@ func (a *Application) fetch() {
|
||||
|
||||
resp, err := a.httpClient.Do(req)
|
||||
if err != nil {
|
||||
log.Println("Failed to execute request for", a.name, "metrics:", err.Error())
|
||||
a.logger.Infoln("Failed to execute request for", a.name, "metrics:", err.Error())
|
||||
|
||||
return
|
||||
}
|
||||
@ -47,7 +46,7 @@ func (a *Application) fetch() {
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println("Failed to read response body for", a.name, "metrics:", err.Error())
|
||||
a.logger.Infoln("Failed to read response body for", a.name, "metrics:", err.Error())
|
||||
|
||||
return
|
||||
}
|
||||
@ -70,7 +69,7 @@ func (a *Application) startFetcher() {
|
||||
Timeout: time.Second * 5,
|
||||
}
|
||||
|
||||
defer log.Println("Fetcher for", a.name, "completed")
|
||||
defer a.logger.Debugln("Fetcher for", a.name, "completed")
|
||||
|
||||
// First fetch should be executed ASAP.
|
||||
a.fetch()
|
||||
|
@ -26,7 +26,7 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
||||
continue
|
||||
}
|
||||
|
||||
// log.Println("Analyzing line:", line)
|
||||
a.logger.Debugln("Analyzing line:", line)
|
||||
|
||||
name = a.getMetricName(line)
|
||||
metric, found := data[name]
|
||||
@ -76,12 +76,12 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
||||
|
||||
metric.Value = a.getMetricValue(line)
|
||||
|
||||
// log.Printf("Got metric: %+v\n", metric)
|
||||
a.logger.Debugln("Got metric: %+v\n", metric)
|
||||
|
||||
data[name] = metric
|
||||
}
|
||||
|
||||
// log.Printf("Data parsed: %+v\n", data)
|
||||
a.logger.Debugln("Data parsed: %+v\n", data)
|
||||
|
||||
return data
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"go.dev.pztrn.name/metricator/internal/application"
|
||||
"go.dev.pztrn.name/metricator/internal/logger"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@ -24,6 +25,8 @@ type Config struct {
|
||||
// Applications describes configuration for remote application's endpoints.
|
||||
// Key is an application's name.
|
||||
Applications map[string]*application.Config `yaml:"applications"`
|
||||
// Logger is a logging configuration.
|
||||
Logger *logger.Config `yaml:"logger"`
|
||||
}
|
||||
|
||||
// NewConfig returns new configuration.
|
||||
|
@ -2,7 +2,6 @@ package httpserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
@ -10,6 +9,7 @@ import (
|
||||
|
||||
"go.dev.pztrn.name/metricator/internal/common"
|
||||
"go.dev.pztrn.name/metricator/internal/configuration"
|
||||
"go.dev.pztrn.name/metricator/internal/logger"
|
||||
)
|
||||
|
||||
// HTTPServer is a controlling structure for HTTP server.
|
||||
@ -17,15 +17,17 @@ type HTTPServer struct {
|
||||
config *configuration.Config
|
||||
ctx context.Context
|
||||
doneChan chan struct{}
|
||||
logger *logger.Logger
|
||||
handler *handler
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
func NewHTTPServer(ctx context.Context, cfg *configuration.Config) (*HTTPServer, chan struct{}) {
|
||||
func NewHTTPServer(ctx context.Context, cfg *configuration.Config, logger *logger.Logger) (*HTTPServer, chan struct{}) {
|
||||
h := &HTTPServer{
|
||||
config: cfg,
|
||||
ctx: ctx,
|
||||
doneChan: make(chan struct{}),
|
||||
logger: logger,
|
||||
}
|
||||
h.initialize()
|
||||
|
||||
@ -40,6 +42,8 @@ func (h *HTTPServer) getRequestContext(_ net.Listener) context.Context {
|
||||
|
||||
// Initializes handler and HTTP server structure.
|
||||
func (h *HTTPServer) initialize() {
|
||||
h.logger.Debugln("Initializing HTTP server...")
|
||||
|
||||
h.handler = &handler{
|
||||
handlers: make(map[string]common.HTTPHandlerFunc),
|
||||
}
|
||||
@ -58,6 +62,7 @@ func (h *HTTPServer) initialize() {
|
||||
|
||||
// RegisterHandlerForApplication registers HTTP handler for application.
|
||||
func (h *HTTPServer) RegisterHandlerForApplication(name string, handler common.HTTPHandlerFunc) {
|
||||
h.logger.Debugln("Registering handler for application", name)
|
||||
h.handler.register(name, handler)
|
||||
}
|
||||
|
||||
@ -68,21 +73,21 @@ func (h *HTTPServer) Start() {
|
||||
err := h.server.ListenAndServe()
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "Server closed") {
|
||||
log.Println("HTTP server failed to listen:", err.Error())
|
||||
h.logger.Infoln("HTTP server failed to listen:", err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
<-h.ctx.Done()
|
||||
log.Println("Shutting down HTTP server")
|
||||
h.logger.Infoln("Shutting down HTTP server")
|
||||
|
||||
err := h.server.Shutdown(h.ctx)
|
||||
if err != nil && !strings.Contains(err.Error(), "context canceled") {
|
||||
log.Println("Failed to stop HTTP server:", err.Error())
|
||||
h.logger.Infoln("Failed to stop HTTP server:", err.Error())
|
||||
}
|
||||
|
||||
log.Println("HTTP server stopped")
|
||||
h.logger.Infoln("HTTP server stopped")
|
||||
|
||||
h.doneChan <- struct{}{}
|
||||
}()
|
||||
|
6
internal/logger/config.go
Normal file
6
internal/logger/config.go
Normal file
@ -0,0 +1,6 @@
|
||||
package logger
|
||||
|
||||
// Config represents logging configuration.
|
||||
type Config struct {
|
||||
Debug bool `yaml:"debug"`
|
||||
}
|
41
internal/logger/logger.go
Normal file
41
internal/logger/logger.go
Normal file
@ -0,0 +1,41 @@
|
||||
package logger
|
||||
|
||||
import "log"
|
||||
|
||||
// Logger responsible for all logging actions.
|
||||
type Logger struct {
|
||||
config *Config
|
||||
}
|
||||
|
||||
// NewLogger creates new logging wrapper and returns it to caller.
|
||||
func NewLogger(config *Config) *Logger {
|
||||
l := &Logger{config: config}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// Debugf is a wrapper around log.Printf which will work only when debug mode
|
||||
// is enabled.
|
||||
func (l *Logger) Debugf(template string, params ...interface{}) {
|
||||
if l.config.Debug {
|
||||
log.Printf(template, params...)
|
||||
}
|
||||
}
|
||||
|
||||
// Debugln is a wrapper around log.Println which will work only when debug mode
|
||||
// is enabled.
|
||||
func (l *Logger) Debugln(params ...interface{}) {
|
||||
if l.config.Debug {
|
||||
log.Println(params...)
|
||||
}
|
||||
}
|
||||
|
||||
// Infof is a wrapper around log.Printf.
|
||||
func (l *Logger) Infof(template string, params ...interface{}) {
|
||||
log.Printf(template, params...)
|
||||
}
|
||||
|
||||
// Infoln is a wrapper around log.Println.
|
||||
func (l *Logger) Infoln(params ...interface{}) {
|
||||
log.Println(params...)
|
||||
}
|
@ -3,9 +3,9 @@ package memory
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"go.dev.pztrn.name/metricator/internal/logger"
|
||||
"go.dev.pztrn.name/metricator/internal/models"
|
||||
)
|
||||
|
||||
@ -15,6 +15,7 @@ var ErrMetricNotFound = errors.New("metric not found")
|
||||
type Storage struct {
|
||||
ctx context.Context
|
||||
doneChan chan struct{}
|
||||
logger *logger.Logger
|
||||
name string
|
||||
|
||||
data map[string]models.Metric
|
||||
@ -22,10 +23,11 @@ type Storage struct {
|
||||
}
|
||||
|
||||
// NewStorage creates new in-memory storage to use.
|
||||
func NewStorage(ctx context.Context, name string) (*Storage, chan struct{}) {
|
||||
func NewStorage(ctx context.Context, name string, logger *logger.Logger) (*Storage, chan struct{}) {
|
||||
s := &Storage{
|
||||
ctx: ctx,
|
||||
doneChan: make(chan struct{}),
|
||||
logger: logger,
|
||||
name: name,
|
||||
}
|
||||
s.initialize()
|
||||
@ -35,19 +37,27 @@ func NewStorage(ctx context.Context, name string) (*Storage, chan struct{}) {
|
||||
|
||||
// Get returns data from storage by key.
|
||||
func (s *Storage) Get(key string) (models.Metric, error) {
|
||||
s.logger.Debugln("Retrieving data for", key, "key from storage...")
|
||||
|
||||
s.dataMutex.RLock()
|
||||
defer s.dataMutex.RUnlock()
|
||||
|
||||
data, found := s.data[key]
|
||||
if !found {
|
||||
s.logger.Infoln("Key", key, "not found in storage!")
|
||||
|
||||
return models.NewMetric("", "", "", nil), ErrMetricNotFound
|
||||
}
|
||||
|
||||
s.logger.Debugf("Key %s found: %+v\n", key, data)
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// GetAsSlice returns all data from storage as slice.
|
||||
func (s *Storage) GetAsSlice() []models.Metric {
|
||||
s.logger.Debugln("Returning all stored metrics as slice...")
|
||||
|
||||
metrics := make([]models.Metric, 0, len(s.data))
|
||||
|
||||
for _, metric := range s.data {
|
||||
@ -80,7 +90,7 @@ func (s *Storage) Put(data map[string]models.Metric) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Put", len(data), "items in", s.name)
|
||||
s.logger.Debugln("Put", len(data), "items in", s.name)
|
||||
}
|
||||
|
||||
// Start starts asynchronous things if needed.
|
||||
@ -89,7 +99,7 @@ func (s *Storage) Start() {
|
||||
go func() {
|
||||
<-s.ctx.Done()
|
||||
|
||||
log.Println("In-memory storage", s.name, "done")
|
||||
s.logger.Infoln("In-memory storage", s.name, "done")
|
||||
|
||||
s.doneChan <- struct{}{}
|
||||
}()
|
||||
|
@ -10,3 +10,8 @@ applications:
|
||||
# Timeout between requests. Not neccessarily be exact and requests might
|
||||
# be sent in 60 or more seconds (in this example).
|
||||
time_between_requests: 60s
|
||||
|
||||
# Logger's configuration.
|
||||
logger:
|
||||
# Print debug output or not?
|
||||
debug: false
|
||||
|
Loading…
Reference in New Issue
Block a user