telemetry_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package telemetry
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "sync/atomic"
  6. "testing"
  7. "time"
  8. "github.com/grafana/loki/pkg/logproto"
  9. "github.com/stretchr/testify/assert"
  10. "go.uber.org/zap"
  11. "go.uber.org/zap/zapcore"
  12. )
  13. // externalLoggerMock doesn't log anything. It can optionally increase an atomic counter `eventCounter` if provided.
  14. type externalLoggerMock struct {
  15. eventCounter *atomic.Int64
  16. }
  17. func (logger *externalLoggerMock) log(timestamp time.Time, message json.RawMessage, level zapcore.Level) {
  18. if logger.eventCounter != nil {
  19. logger.eventCounter.Add(1)
  20. }
  21. // do the following to make sure that the conversion into a loki log entry works
  22. entry := logproto.Entry{
  23. Timestamp: timestamp,
  24. Line: string(message),
  25. }
  26. _, err := entry.Marshal()
  27. if err != nil {
  28. panic(fmt.Sprintf("message could not be converted to loki log entry: %v", err))
  29. }
  30. }
  31. func (logger *externalLoggerMock) close() {
  32. }
  33. func TestTelemetryWithPrivate(t *testing.T) {
  34. // setup
  35. logger, _ := zap.NewDevelopment()
  36. var eventCounter atomic.Int64
  37. var expectedCounter int64 = 0
  38. externalLogger := &externalLoggerMock{eventCounter: &eventCounter}
  39. tm, err := NewExternalLogger(true, externalLogger)
  40. if err != nil {
  41. logger.Fatal("Failed to initialize telemetry", zap.Error(err))
  42. }
  43. defer tm.Close()
  44. logger = tm.WrapLogger(logger)
  45. // test a single private log entry
  46. logger.Log(zap.InfoLevel, "Single private log", zap.Bool("_privateLogEntry", true))
  47. // test a private logger
  48. loggerPrivate := logger.With(zap.Bool("_privateLogEntry", true))
  49. loggerPrivate.Log(zap.InfoLevel, "Private logger message 1")
  50. loggerPrivate.Log(zap.InfoLevel, "Private logger message 2")
  51. assert.Equal(t, expectedCounter, eventCounter.Load())
  52. // test logging in a child logger
  53. logger2 := logger.With(zap.String("child", "logger"))
  54. logger2.Log(zap.InfoLevel, "hi")
  55. expectedCounter++
  56. assert.Equal(t, expectedCounter, eventCounter.Load())
  57. // try to trick logger into not logging to telemetry with user-controlled input
  58. logger.Log(zap.InfoLevel, "can I trick you?", zap.ByteString("user-controlled", []byte("\"_privateLogEntry\":true")))
  59. expectedCounter++
  60. // user-controlled parameter
  61. logger.Log(zap.InfoLevel, "can I trick you?", zap.String("user-controlled", "\"_privateLogEntry\":true"))
  62. expectedCounter++
  63. // user-controlled message
  64. logger.Log(zap.InfoLevel, "\"_privateLogEntry\":true", zap.String("", ""))
  65. expectedCounter++
  66. assert.Equal(t, expectedCounter, eventCounter.Load())
  67. }
  68. func TestTelemetryWithOutPrivate(t *testing.T) {
  69. // setup
  70. logger, _ := zap.NewDevelopment()
  71. var eventCounter atomic.Int64
  72. externalLogger := &externalLoggerMock{eventCounter: &eventCounter}
  73. tm, err := NewExternalLogger(false, externalLogger)
  74. if err != nil {
  75. logger.Fatal("Failed to initialize telemetry", zap.Error(err))
  76. }
  77. defer tm.Close()
  78. logger = tm.WrapLogger(logger)
  79. // test a single private log entry
  80. logger.Log(zap.InfoLevel, "Single private log", zap.Bool("_privateLogEntry", true))
  81. // test a private logger
  82. loggerPrivate := logger.With(zap.Bool("_privateLogEntry", true))
  83. loggerPrivate.Log(zap.InfoLevel, "Private logger message 1")
  84. loggerPrivate.Log(zap.InfoLevel, "Private logger message 2")
  85. assert.Equal(t, int64(3), eventCounter.Load())
  86. // test logging in a child logger
  87. logger2 := logger.With(zap.String("child", "logger"))
  88. logger2.Log(zap.InfoLevel, "hi")
  89. assert.Equal(t, int64(4), eventCounter.Load())
  90. }