Like Prometheus, but for logs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
loki/clients/pkg/promtail/promtail.go

126 lines
3.3 KiB

package promtail
import (
"sync"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/grafana/loki/clients/pkg/logentry/stages"
"github.com/grafana/loki/clients/pkg/promtail/client"
"github.com/grafana/loki/clients/pkg/promtail/config"
"github.com/grafana/loki/clients/pkg/promtail/server"
"github.com/grafana/loki/clients/pkg/promtail/targets"
util_log "github.com/grafana/loki/pkg/util/log"
)
// Option is a function that can be passed to the New method of Promtail and
// customize the Promtail that is created.
type Option func(p *Promtail)
// WithLogger overrides the default logger for Promtail.
func WithLogger(log log.Logger) Option {
return func(p *Promtail) {
p.logger = log
}
}
// WithRegisterer overrides the default registerer for Promtail.
func WithRegisterer(reg prometheus.Registerer) Option {
return func(p *Promtail) {
p.reg = reg
}
}
// Promtail is the root struct for Promtail.
type Promtail struct {
client client.Client
targetManagers *targets.TargetManagers
server server.Server
logger log.Logger
reg prometheus.Registerer
stopped bool
mtx sync.Mutex
}
// New makes a new Promtail.
func New(cfg config.Config, metrics *client.Metrics, dryRun bool, opts ...Option) (*Promtail, error) {
// Initialize promtail with some defaults and allow the options to override
// them.
promtail := &Promtail{
logger: util_log.Logger,
reg: prometheus.DefaultRegisterer,
}
for _, o := range opts {
// todo (callum) I don't understand why I needed to add this check
if o == nil {
continue
}
o(promtail)
}
cfg.Setup()
if cfg.LimitConfig.ReadlineRateEnabled {
stages.SetReadLineRateLimiter(cfg.LimitConfig.ReadlineRate, cfg.LimitConfig.ReadlineBurst, cfg.LimitConfig.ReadlineRateDrop)
}
var err error
if dryRun {
promtail.client, err = client.NewLogger(metrics, cfg.Options.StreamLagLabels, promtail.logger, cfg.ClientConfigs...)
if err != nil {
return nil, err
}
cfg.PositionsConfig.ReadOnly = true
} else {
promtail.client, err = client.NewMulti(metrics, cfg.Options.StreamLagLabels, promtail.logger, cfg.ClientConfigs...)
if err != nil {
return nil, err
}
}
tms, err := targets.NewTargetManagers(promtail, promtail.reg, promtail.logger, cfg.PositionsConfig, promtail.client, cfg.ScrapeConfig, &cfg.TargetConfig)
if err != nil {
return nil, err
}
promtail.targetManagers = tms
server, err := server.New(cfg.ServerConfig, promtail.logger, tms, cfg.String())
if err != nil {
return nil, err
}
promtail.server = server
return promtail, nil
}
// Run the promtail; will block until a signal is received.
func (p *Promtail) Run() error {
p.mtx.Lock()
// if we stopped promtail before the server even started we can return without starting.
if p.stopped {
p.mtx.Unlock()
return nil
}
p.mtx.Unlock() // unlock before blocking
return p.server.Run()
}
// Client returns the underlying client Promtail uses to write to Loki.
func (p *Promtail) Client() client.Client {
return p.client
}
// Shutdown the promtail.
func (p *Promtail) Shutdown() {
p.mtx.Lock()
defer p.mtx.Unlock()
p.stopped = true
if p.server != nil {
p.server.Shutdown()
}
if p.targetManagers != nil {
p.targetManagers.Stop()
}
// todo work out the stop.
p.client.Stop()
}