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