github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/daemon/logger/local/local_test.go (about) 1 package local 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "io" 7 "os" 8 "path/filepath" 9 "strconv" 10 "testing" 11 "time" 12 13 "github.com/Prakhar-Agarwal-byte/moby/api/types/backend" 14 "github.com/Prakhar-Agarwal-byte/moby/api/types/plugins/logdriver" 15 "github.com/Prakhar-Agarwal-byte/moby/daemon/logger" 16 "github.com/Prakhar-Agarwal-byte/moby/daemon/logger/loggertest" 17 protoio "github.com/gogo/protobuf/io" 18 "gotest.tools/v3/assert" 19 is "gotest.tools/v3/assert/cmp" 20 ) 21 22 func TestWriteLog(t *testing.T) { 23 t.Parallel() 24 25 dir, err := os.MkdirTemp("", t.Name()) 26 assert.NilError(t, err) 27 defer os.RemoveAll(dir) 28 29 logPath := filepath.Join(dir, "test.log") 30 31 l, err := New(logger.Info{LogPath: logPath}) 32 assert.NilError(t, err) 33 defer l.Close() 34 35 m1 := logger.Message{Source: "stdout", Timestamp: time.Now().Add(-1 * 30 * time.Minute), Line: []byte("message 1")} 36 m2 := logger.Message{Source: "stdout", Timestamp: time.Now().Add(-1 * 20 * time.Minute), Line: []byte("message 2"), PLogMetaData: &backend.PartialLogMetaData{Last: true, ID: "0001", Ordinal: 1}} 37 m3 := logger.Message{Source: "stderr", Timestamp: time.Now().Add(-1 * 10 * time.Minute), Line: []byte("message 3")} 38 39 // copy the log message because the underying log writer resets the log message and returns it to a buffer pool 40 err = l.Log(copyLogMessage(&m1)) 41 assert.NilError(t, err) 42 err = l.Log(copyLogMessage(&m2)) 43 assert.NilError(t, err) 44 err = l.Log(copyLogMessage(&m3)) 45 assert.NilError(t, err) 46 47 f, err := os.Open(logPath) 48 assert.NilError(t, err) 49 defer f.Close() 50 dec := protoio.NewUint32DelimitedReader(f, binary.BigEndian, 1e6) 51 52 var ( 53 proto logdriver.LogEntry 54 testProto logdriver.LogEntry 55 partial logdriver.PartialLogEntryMetadata 56 ) 57 58 lenBuf := make([]byte, encodeBinaryLen) 59 seekMsgLen := func() { 60 io.ReadFull(f, lenBuf) 61 } 62 63 err = dec.ReadMsg(&proto) 64 assert.NilError(t, err) 65 messageToProto(&m1, &testProto, &partial) 66 assert.Check(t, is.DeepEqual(testProto, proto), "expected:\n%+v\ngot:\n%+v", testProto, proto) 67 seekMsgLen() 68 69 err = dec.ReadMsg(&proto) 70 assert.NilError(t, err) 71 messageToProto(&m2, &testProto, &partial) 72 assert.Check(t, is.DeepEqual(testProto, proto)) 73 seekMsgLen() 74 75 err = dec.ReadMsg(&proto) 76 assert.NilError(t, err) 77 messageToProto(&m3, &testProto, &partial) 78 assert.Check(t, is.DeepEqual(testProto, proto), "expected:\n%+v\ngot:\n%+v", testProto, proto) 79 } 80 81 func TestReadLog(t *testing.T) { 82 r := loggertest.Reader{ 83 Factory: func(t *testing.T, info logger.Info) func(*testing.T) logger.Logger { 84 dir := t.TempDir() 85 info.LogPath = filepath.Join(dir, info.ContainerID+".log") 86 return func(t *testing.T) logger.Logger { 87 l, err := New(info) 88 assert.NilError(t, err) 89 return l 90 } 91 }, 92 } 93 t.Run("Tail", r.TestTail) 94 t.Run("Follow", r.TestFollow) 95 } 96 97 func BenchmarkLogWrite(b *testing.B) { 98 f, err := os.CreateTemp("", b.Name()) 99 assert.Assert(b, err) 100 defer os.Remove(f.Name()) 101 f.Close() 102 103 local, err := New(logger.Info{LogPath: f.Name()}) 104 assert.Assert(b, err) 105 defer local.Close() 106 107 t := time.Now().UTC() 108 for _, data := range [][]byte{ 109 []byte(""), 110 []byte("a short string"), 111 bytes.Repeat([]byte("a long string"), 100), 112 bytes.Repeat([]byte("a really long string"), 10000), 113 } { 114 b.Run(strconv.Itoa(len(data)), func(b *testing.B) { 115 entry := &logdriver.LogEntry{Line: data, Source: "stdout", TimeNano: t.UnixNano()} 116 b.SetBytes(int64(entry.Size() + encodeBinaryLen + encodeBinaryLen)) 117 b.ResetTimer() 118 for i := 0; i < b.N; i++ { 119 msg := logger.NewMessage() 120 msg.Line = data 121 msg.Timestamp = t 122 msg.Source = "stdout" 123 if err := local.Log(msg); err != nil { 124 b.Fatal(err) 125 } 126 } 127 }) 128 } 129 } 130 131 func copyLogMessage(src *logger.Message) *logger.Message { 132 dst := logger.NewMessage() 133 dst.Source = src.Source 134 dst.Timestamp = src.Timestamp 135 dst.Attrs = src.Attrs 136 dst.Err = src.Err 137 dst.Line = append(dst.Line, src.Line...) 138 if src.PLogMetaData != nil { 139 lmd := *src.PLogMetaData 140 dst.PLogMetaData = &lmd 141 } 142 return dst 143 }