github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/cmd/docker-driver/loki.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "sync" 6 7 "github.com/docker/docker/daemon/logger" 8 "github.com/go-kit/log" 9 "github.com/pkg/errors" 10 "github.com/prometheus/client_golang/prometheus" 11 "github.com/prometheus/common/model" 12 13 "github.com/grafana/loki/clients/pkg/logentry/stages" 14 "github.com/grafana/loki/clients/pkg/promtail/api" 15 "github.com/grafana/loki/clients/pkg/promtail/client" 16 17 "github.com/grafana/loki/pkg/logproto" 18 ) 19 20 var jobName = "docker" 21 22 type loki struct { 23 client client.Client 24 handler api.EntryHandler 25 labels model.LabelSet 26 logger log.Logger 27 28 closed bool 29 mutex sync.RWMutex 30 31 stop func() 32 } 33 34 // New create a new Loki logger that forward logs to Loki instance 35 func New(logCtx logger.Info, logger log.Logger) (logger.Logger, error) { 36 logger = log.With(logger, "container_id", logCtx.ContainerID) 37 cfg, err := parseConfig(logCtx) 38 if err != nil { 39 return nil, err 40 } 41 m := client.NewMetrics(prometheus.DefaultRegisterer, nil) 42 c, err := client.New(m, cfg.clientConfig, nil, logger) 43 if err != nil { 44 return nil, err 45 } 46 var handler api.EntryHandler = c 47 var stop = func() {} 48 if len(cfg.pipeline.PipelineStages) != 0 { 49 pipeline, err := stages.NewPipeline(logger, cfg.pipeline.PipelineStages, &jobName, prometheus.DefaultRegisterer) 50 if err != nil { 51 return nil, err 52 } 53 handler = pipeline.Wrap(c) 54 stop = handler.Stop 55 } 56 return &loki{ 57 client: c, 58 labels: cfg.labels, 59 logger: logger, 60 handler: handler, 61 stop: stop, 62 }, nil 63 } 64 65 // Log implements `logger.Logger` 66 func (l *loki) Log(m *logger.Message) error { 67 l.mutex.RLock() 68 defer l.mutex.RUnlock() 69 70 if l.closed { 71 return errors.New("client closed") 72 } 73 74 if len(bytes.Fields(m.Line)) == 0 { 75 return nil 76 } 77 lbs := l.labels.Clone() 78 if m.Source != "" { 79 lbs["source"] = model.LabelValue(m.Source) 80 } 81 l.handler.Chan() <- api.Entry{ 82 Labels: lbs, 83 Entry: logproto.Entry{ 84 Timestamp: m.Timestamp, 85 Line: string(m.Line), 86 }, 87 } 88 return nil 89 } 90 91 // Log implements `logger.Logger` 92 func (l *loki) Name() string { 93 return driverName 94 } 95 96 // Log implements `logger.Logger` 97 func (l *loki) Close() error { 98 l.mutex.Lock() 99 defer l.mutex.Unlock() 100 l.stop() 101 l.client.StopNow() 102 l.closed = true 103 return nil 104 }