github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/objstorage/remote/logging.go (about) 1 // Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package remote 6 7 import ( 8 "context" 9 "fmt" 10 "io" 11 "sort" 12 ) 13 14 // WithLogging wraps the given Storage implementation and emits logs for various 15 // operations. 16 func WithLogging(wrapped Storage, logf func(fmt string, args ...interface{})) Storage { 17 return &loggingStore{ 18 logf: logf, 19 wrapped: wrapped, 20 } 21 } 22 23 // loggingStore wraps a remote.Storage implementation and emits logs of the 24 // operations. 25 type loggingStore struct { 26 logf func(fmt string, args ...interface{}) 27 wrapped Storage 28 } 29 30 var _ Storage = (*loggingStore)(nil) 31 32 func (l *loggingStore) Close() error { 33 l.logf("close") 34 return l.wrapped.Close() 35 } 36 37 func (l *loggingStore) ReadObject( 38 ctx context.Context, objName string, 39 ) (_ ObjectReader, objSize int64, _ error) { 40 r, size, err := l.wrapped.ReadObject(ctx, objName) 41 l.logf("create reader for object %q: %s", objName, errOrPrintf(err, "%d bytes", size)) 42 if err != nil { 43 return nil, 0, err 44 } 45 return &loggingReader{ 46 l: l, 47 name: objName, 48 wrapped: r, 49 }, size, nil 50 } 51 52 type loggingReader struct { 53 l *loggingStore 54 name string 55 wrapped ObjectReader 56 } 57 58 var _ ObjectReader = (*loggingReader)(nil) 59 60 func (l *loggingReader) ReadAt(ctx context.Context, p []byte, offset int64) error { 61 if err := l.wrapped.ReadAt(ctx, p, offset); err != nil { 62 l.l.logf("read object %q at %d (length %d): error %v", l.name, offset, len(p), err) 63 return err 64 } 65 l.l.logf("read object %q at %d (length %d)", l.name, offset, len(p)) 66 return nil 67 } 68 69 func (l *loggingReader) Close() error { 70 l.l.logf("close reader for %q", l.name) 71 return l.wrapped.Close() 72 } 73 74 func (l *loggingStore) CreateObject(objName string) (io.WriteCloser, error) { 75 l.logf("create object %q", objName) 76 writer, err := l.wrapped.CreateObject(objName) 77 if err != nil { 78 return nil, err 79 } 80 return &loggingWriter{ 81 l: l, 82 name: objName, 83 WriteCloser: writer, 84 }, nil 85 } 86 87 type loggingWriter struct { 88 l *loggingStore 89 name string 90 bytesWritten int64 91 io.WriteCloser 92 } 93 94 func (l *loggingWriter) Write(p []byte) (n int, err error) { 95 n, err = l.WriteCloser.Write(p) 96 l.bytesWritten += int64(n) 97 return n, err 98 } 99 100 func (l *loggingWriter) Close() error { 101 l.l.logf("close writer for %q after %d bytes", l.name, l.bytesWritten) 102 return l.WriteCloser.Close() 103 } 104 105 func (l *loggingStore) List(prefix, delimiter string) ([]string, error) { 106 l.logf("list (prefix=%q, delimiter=%q)", prefix, delimiter) 107 res, err := l.wrapped.List(prefix, delimiter) 108 if err != nil { 109 return nil, err 110 } 111 sorted := append([]string(nil), res...) 112 sort.Strings(sorted) 113 for _, s := range sorted { 114 l.logf(" - %s", s) 115 } 116 return res, nil 117 } 118 119 func (l *loggingStore) Delete(objName string) error { 120 l.logf("delete object %q", objName) 121 return l.wrapped.Delete(objName) 122 } 123 124 func (l *loggingStore) Size(objName string) (int64, error) { 125 size, err := l.wrapped.Size(objName) 126 l.logf("size of object %q: %s", objName, errOrPrintf(err, "%d", size)) 127 return size, err 128 } 129 130 func errOrPrintf(err error, format string, args ...interface{}) string { 131 if err != nil { 132 return fmt.Sprintf("error: %v", err) 133 } 134 return fmt.Sprintf(format, args...) 135 } 136 137 func (l *loggingStore) IsNotExistError(err error) bool { 138 return l.wrapped.IsNotExistError(err) 139 }