138 lines
4.9 KiB
Go
138 lines
4.9 KiB
Go
|
package pkg
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"github.com/getsentry/sentry-go"
|
||
|
"github.com/goccy/go-json"
|
||
|
"github.com/spf13/viper"
|
||
|
"math"
|
||
|
)
|
||
|
|
||
|
// Configuration holds all the application's configurable settings.
|
||
|
type Configuration struct {
|
||
|
// LoggingLevel is the logging level.
|
||
|
LoggingLevel string `json:"logging_level"`
|
||
|
// SentryDSN is the DSN used by Sentry, for reporting errors.
|
||
|
SentryDSN string `json:"sentry_dsn"`
|
||
|
// KafkaPollingGoroutines is the number of goroutines that will poll Kafka for new messages.
|
||
|
KafkaPollingGoroutines int `json:"kafka_polling_goroutines"`
|
||
|
// KafkaPollingTimeoutMs is the timeout in milliseconds for the message poll().
|
||
|
KafkaPollingTimeoutMs int `json:"kafka_polling_timeout_ms"`
|
||
|
// KafkaBoostrapServers is a string of comma separated boostrap servers.
|
||
|
KafkaBoostrapServers string `json:"kafka_boostrap_servers"`
|
||
|
// KafkaGroupId is the Kafka consumer group id.
|
||
|
KafkaGroupId string `json:"kafka_group_id"`
|
||
|
// SubscribeTopics is the list of topics or patterns to subscribe to.
|
||
|
SubscribeTopics []string `json:"subscribe_topics"`
|
||
|
// LokiPushUrl is the full URL of the Loki push API endpoint.
|
||
|
LokiPushUrl string `json:"loki_push_url"`
|
||
|
// LokiPushMode is the mode used to push data to Loki, http or proto.
|
||
|
LokiPushMode string `json:"loki_push_mode"`
|
||
|
// BufferMaxBatchSize is the batch size that will be sent to Loki.
|
||
|
BufferMaxBatchSize int `json:"buffer_max_batch_size"`
|
||
|
// BufferMaxBytesSize is max buffer size in bytes uncompressed and unserialized that will be sent to Loki.
|
||
|
BufferMaxBytesSize int `json:"buffer_max_bytes_size"`
|
||
|
// KafkaOffsetReset is analogous to https://kafka.apache.org/documentation/#consumerconfigs_auto.offset.reset
|
||
|
KafkaOffsetReset string `json:"kafka_offset_reset"`
|
||
|
}
|
||
|
|
||
|
// ToPrettyJson transforms the current configuration to a pretty json.
|
||
|
func (c Configuration) ToPrettyJson() string {
|
||
|
prettyJson, err := json.MarshalIndent(c, "", " ")
|
||
|
if err != nil {
|
||
|
SugaredLogger.Error("failed to convert config to pretty json")
|
||
|
return ""
|
||
|
}
|
||
|
return string(prettyJson)
|
||
|
}
|
||
|
|
||
|
// ViperConfigurator is a convenient wrapper over Viper.
|
||
|
type ViperConfigurator struct {
|
||
|
viper *viper.Viper
|
||
|
configuration Configuration
|
||
|
}
|
||
|
|
||
|
func NewViperConfigurator() (*ViperConfigurator, error) {
|
||
|
viperInstance := viper.New()
|
||
|
viperInstance.SetConfigName("config")
|
||
|
viperInstance.SetConfigType("json")
|
||
|
viperInstance.AddConfigPath("$HOME/.speedy")
|
||
|
viperInstance.AddConfigPath(".")
|
||
|
viperInstance.SetEnvPrefix("SG")
|
||
|
viperInstance.AutomaticEnv()
|
||
|
if err := viperInstance.ReadInConfig(); err != nil {
|
||
|
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||
|
SugaredLogger.Warn("Config file not found")
|
||
|
} else {
|
||
|
SugaredLogger.Error("Error loading config file.")
|
||
|
sentry.CaptureException(err)
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
viperConfigurator := ViperConfigurator{viperInstance, Configuration{}}
|
||
|
err := viperConfigurator.loadConfig()
|
||
|
if err != nil {
|
||
|
SugaredLogger.Error(err)
|
||
|
sentry.CaptureException(err)
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &viperConfigurator, nil
|
||
|
}
|
||
|
|
||
|
// GetConfig returns a copy of the Configuration data structure.
|
||
|
func (v *ViperConfigurator) GetConfig() Configuration {
|
||
|
return v.configuration
|
||
|
}
|
||
|
|
||
|
// loadConfig loads configuration from viper onto the internal data structures.
|
||
|
func (v *ViperConfigurator) loadConfig() error {
|
||
|
|
||
|
v.configuration.KafkaBoostrapServers = v.viper.GetString("kafka_bootstrap_servers")
|
||
|
if v.configuration.KafkaBoostrapServers == "" {
|
||
|
return errors.New("kafka_bootstrap_servers is empty")
|
||
|
}
|
||
|
|
||
|
v.configuration.KafkaGroupId = v.viper.GetString("kafka_group_id")
|
||
|
if v.configuration.KafkaGroupId == "" {
|
||
|
return errors.New("kafka_group_id is empty")
|
||
|
}
|
||
|
|
||
|
v.configuration.LokiPushUrl = v.viper.GetString("loki_push_url")
|
||
|
if v.configuration.LokiPushUrl == "" {
|
||
|
return errors.New("loki_push_url is empty")
|
||
|
}
|
||
|
|
||
|
v.configuration.SubscribeTopics = v.viper.GetStringSlice("subscribe_topics")
|
||
|
if len(v.configuration.SubscribeTopics) == 0 {
|
||
|
return errors.New("subscribe_topics is empty")
|
||
|
}
|
||
|
|
||
|
v.viper.SetDefault("buffer_max_batch_size", 10_000)
|
||
|
v.configuration.BufferMaxBatchSize = v.viper.GetInt("buffer_max_batch_size")
|
||
|
|
||
|
v.viper.SetDefault("buffer_max_bytes_size", math.MaxInt32)
|
||
|
v.configuration.BufferMaxBytesSize = v.viper.GetInt("buffer_max_bytes_size")
|
||
|
|
||
|
v.viper.SetDefault("loki_push_mode", "http")
|
||
|
v.configuration.LokiPushMode = v.viper.GetString("loki_push_mode")
|
||
|
|
||
|
v.viper.SetDefault("kafka_offset_reset", "earliest")
|
||
|
v.configuration.KafkaOffsetReset = v.viper.GetString("kafka_offset_reset")
|
||
|
|
||
|
v.viper.SetDefault("logging_level", "info")
|
||
|
v.configuration.LoggingLevel = v.viper.GetString("logging_level")
|
||
|
|
||
|
v.viper.SetDefault("kafka_polling_goroutines", 5)
|
||
|
v.configuration.KafkaPollingGoroutines = v.viper.GetInt("kafka_polling_goroutines")
|
||
|
|
||
|
v.viper.SetDefault("kafka_polling_timeout_ms", 30_000)
|
||
|
v.configuration.KafkaPollingTimeoutMs = v.viper.GetInt("kafka_polling_timeout_ms")
|
||
|
|
||
|
v.viper.SetDefault("sentry_dsn", "")
|
||
|
v.configuration.SentryDSN = v.viper.GetString("sentry_dsn")
|
||
|
|
||
|
return nil
|
||
|
}
|