github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/vfs/logging_fs.go (about) 1 // Copyright 2021 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 vfs 6 7 import ( 8 "io" 9 "os" 10 ) 11 12 // WithLogging wraps an FS and logs filesystem modification operations to the 13 // given logFn. 14 func WithLogging(fs FS, logFn LogFn) FS { 15 return &loggingFS{ 16 FS: fs, 17 logFn: logFn, 18 } 19 } 20 21 // LogFn is a function that is used to capture a log when WithLogging is used. 22 type LogFn func(fmt string, args ...interface{}) 23 24 type loggingFS struct { 25 FS 26 logFn LogFn 27 } 28 29 var _ FS = (*loggingFS)(nil) 30 31 func (fs *loggingFS) Create(name string) (File, error) { 32 fs.logFn("create: %s", name) 33 f, err := fs.FS.Create(name) 34 if err != nil { 35 return nil, err 36 } 37 return newLoggingFile(f, name, fs.logFn), nil 38 } 39 40 func (fs *loggingFS) Open(name string, opts ...OpenOption) (File, error) { 41 fs.logFn("open: %s", name) 42 f, err := fs.FS.Open(name, opts...) 43 if err != nil { 44 return nil, err 45 } 46 return newLoggingFile(f, name, fs.logFn), nil 47 } 48 49 func (fs *loggingFS) OpenReadWrite(name string, opts ...OpenOption) (File, error) { 50 fs.logFn("open-read-write: %s", name) 51 f, err := fs.FS.OpenReadWrite(name, opts...) 52 if err != nil { 53 return nil, err 54 } 55 return newLoggingFile(f, name, fs.logFn), nil 56 } 57 58 func (fs *loggingFS) Link(oldname, newname string) error { 59 fs.logFn("link: %s -> %s", oldname, newname) 60 return fs.FS.Link(oldname, newname) 61 } 62 63 func (fs *loggingFS) OpenDir(name string) (File, error) { 64 fs.logFn("open-dir: %s", name) 65 f, err := fs.FS.OpenDir(name) 66 if err != nil { 67 return nil, err 68 } 69 return newLoggingFile(f, name, fs.logFn), nil 70 } 71 72 func (fs *loggingFS) Rename(oldname, newname string) error { 73 fs.logFn("rename: %s -> %s", oldname, newname) 74 return fs.FS.Rename(oldname, newname) 75 } 76 77 func (fs *loggingFS) ReuseForWrite(oldname, newname string) (File, error) { 78 fs.logFn("reuseForWrite: %s -> %s", oldname, newname) 79 f, err := fs.FS.ReuseForWrite(oldname, newname) 80 if err != nil { 81 return nil, err 82 } 83 return newLoggingFile(f, newname, fs.logFn), nil 84 } 85 86 func (fs *loggingFS) MkdirAll(dir string, perm os.FileMode) error { 87 fs.logFn("mkdir-all: %s %#o", dir, perm) 88 return fs.FS.MkdirAll(dir, perm) 89 } 90 91 func (fs *loggingFS) Lock(name string) (io.Closer, error) { 92 fs.logFn("lock: %s", name) 93 return fs.FS.Lock(name) 94 } 95 96 func (fs loggingFS) Remove(name string) error { 97 fs.logFn("remove: %s", name) 98 err := fs.FS.Remove(name) 99 return err 100 } 101 102 func (fs loggingFS) RemoveAll(name string) error { 103 fs.logFn("remove-all: %s", name) 104 err := fs.FS.RemoveAll(name) 105 return err 106 } 107 108 type loggingFile struct { 109 File 110 name string 111 logFn LogFn 112 } 113 114 var _ File = (*loggingFile)(nil) 115 116 func newLoggingFile(f File, name string, logFn LogFn) *loggingFile { 117 return &loggingFile{ 118 File: f, 119 name: name, 120 logFn: logFn, 121 } 122 } 123 124 func (f *loggingFile) Close() error { 125 f.logFn("close: %s", f.name) 126 return f.File.Close() 127 } 128 129 func (f *loggingFile) Sync() error { 130 f.logFn("sync: %s", f.name) 131 return f.File.Sync() 132 } 133 134 func (f *loggingFile) SyncData() error { 135 f.logFn("sync-data: %s", f.name) 136 return f.File.SyncData() 137 } 138 139 func (f *loggingFile) SyncTo(length int64) (fullSync bool, err error) { 140 f.logFn("sync-to(%d): %s", length, f.name) 141 return f.File.SyncTo(length) 142 } 143 144 func (f *loggingFile) ReadAt(p []byte, offset int64) (int, error) { 145 f.logFn("read-at(%d, %d): %s", offset, len(p), f.name) 146 return f.File.ReadAt(p, offset) 147 } 148 149 func (f *loggingFile) WriteAt(p []byte, offset int64) (int, error) { 150 f.logFn("write-at(%d, %d): %s", offset, len(p), f.name) 151 return f.File.WriteAt(p, offset) 152 } 153 154 func (f *loggingFile) Prefetch(offset int64, length int64) error { 155 f.logFn("prefetch(%d, %d): %s", offset, length, f.name) 156 return f.File.Prefetch(offset, length) 157 }