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  }