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  }