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