logentries.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Package logentries provides the log driver for forwarding server logs
  2. // to logentries endpoints.
  3. package logentries // import "github.com/docker/docker/daemon/logger/logentries"
  4. import (
  5. "context"
  6. "fmt"
  7. "strconv"
  8. "github.com/bsphere/le_go"
  9. "github.com/containerd/log"
  10. "github.com/docker/docker/daemon/logger"
  11. "github.com/pkg/errors"
  12. )
  13. type logentries struct {
  14. tag string
  15. containerID string
  16. containerName string
  17. writer *le_go.Logger
  18. extra map[string]string
  19. lineOnly bool
  20. }
  21. const (
  22. name = "logentries"
  23. token = "logentries-token"
  24. lineonly = "line-only"
  25. )
  26. func init() {
  27. if err := logger.RegisterLogDriver(name, New); err != nil {
  28. panic(err)
  29. }
  30. if err := logger.RegisterLogOptValidator(name, ValidateLogOpt); err != nil {
  31. panic(err)
  32. }
  33. }
  34. // New creates a logentries logger using the configuration passed in on
  35. // the context. The supported context configuration variable is
  36. // logentries-token.
  37. func New(info logger.Info) (logger.Logger, error) {
  38. log.G(context.TODO()).WithField("container", info.ContainerID).
  39. WithField("token", info.Config[token]).
  40. WithField("line-only", info.Config[lineonly]).
  41. Debug("logging driver logentries configured")
  42. log, err := le_go.Connect(info.Config[token])
  43. if err != nil {
  44. return nil, errors.Wrap(err, "error connecting to logentries")
  45. }
  46. var lineOnly bool
  47. if info.Config[lineonly] != "" {
  48. if lineOnly, err = strconv.ParseBool(info.Config[lineonly]); err != nil {
  49. return nil, errors.Wrap(err, "error parsing lineonly option")
  50. }
  51. }
  52. return &logentries{
  53. containerID: info.ContainerID,
  54. containerName: info.ContainerName,
  55. writer: log,
  56. lineOnly: lineOnly,
  57. }, nil
  58. }
  59. func (f *logentries) Log(msg *logger.Message) error {
  60. if !f.lineOnly {
  61. data := map[string]string{
  62. "container_id": f.containerID,
  63. "container_name": f.containerName,
  64. "source": msg.Source,
  65. "log": string(msg.Line),
  66. }
  67. for k, v := range f.extra {
  68. data[k] = v
  69. }
  70. ts := msg.Timestamp
  71. logger.PutMessage(msg)
  72. f.writer.Println(f.tag, ts, data)
  73. } else {
  74. line := string(msg.Line)
  75. logger.PutMessage(msg)
  76. f.writer.Println(line)
  77. }
  78. return nil
  79. }
  80. func (f *logentries) Close() error {
  81. return f.writer.Close()
  82. }
  83. func (f *logentries) Name() string {
  84. return name
  85. }
  86. // ValidateLogOpt looks for logentries specific log option logentries-address.
  87. func ValidateLogOpt(cfg map[string]string) error {
  88. for key := range cfg {
  89. switch key {
  90. case "env":
  91. case "env-regex":
  92. case "labels":
  93. case "labels-regex":
  94. case "tag":
  95. case key:
  96. default:
  97. return fmt.Errorf("unknown log opt '%s' for logentries log driver", key)
  98. }
  99. }
  100. if cfg[token] == "" {
  101. return fmt.Errorf("Missing logentries token")
  102. }
  103. return nil
  104. }