LCOV - code coverage report
Current view: top level - pebble/internal/base - logger.go (source / functions) Hit Total Coverage
Test: 2024-12-21 08:16Z 78d53457 - tests only.lcov Lines: 30 51 58.8 %
Date: 2024-12-21 08:17:21 Functions: 0 0 -

          Line data    Source code
       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 base
       6             : 
       7             : import (
       8             :         "bytes"
       9             :         "context"
      10             :         "fmt"
      11             :         "log"
      12             :         "os"
      13             :         "sync"
      14             : 
      15             :         "github.com/cockroachdb/pebble/internal/invariants"
      16             : )
      17             : 
      18             : // Logger defines an interface for writing log messages.
      19             : type Logger interface {
      20             :         Infof(format string, args ...interface{})
      21             :         Errorf(format string, args ...interface{})
      22             :         Fatalf(format string, args ...interface{})
      23             : }
      24             : type defaultLogger struct{}
      25             : 
      26             : // DefaultLogger logs to the Go stdlib logs.
      27             : var DefaultLogger defaultLogger
      28             : 
      29             : var _ Logger = DefaultLogger
      30             : 
      31             : // Infof implements the Logger.Infof interface.
      32           1 : func (defaultLogger) Infof(format string, args ...interface{}) {
      33           1 :         _ = log.Output(2, fmt.Sprintf(format, args...))
      34           1 : }
      35             : 
      36             : // Errorf implements the Logger.Errorf interface.
      37           0 : func (defaultLogger) Errorf(format string, args ...interface{}) {
      38           0 :         _ = log.Output(2, fmt.Sprintf(format, args...))
      39           0 : }
      40             : 
      41             : // Fatalf implements the Logger.Fatalf interface.
      42           0 : func (defaultLogger) Fatalf(format string, args ...interface{}) {
      43           0 :         _ = log.Output(2, fmt.Sprintf(format, args...))
      44           0 :         os.Exit(1)
      45           0 : }
      46             : 
      47             : // InMemLogger implements Logger using an in-memory buffer (used for testing).
      48             : // The buffer can be read via String() and cleared via Reset().
      49             : type InMemLogger struct {
      50             :         mu struct {
      51             :                 sync.Mutex
      52             :                 buf bytes.Buffer
      53             :         }
      54             : }
      55             : 
      56             : var _ Logger = (*InMemLogger)(nil)
      57             : 
      58             : // Reset clears the internal buffer.
      59           1 : func (b *InMemLogger) Reset() {
      60           1 :         b.mu.Lock()
      61           1 :         defer b.mu.Unlock()
      62           1 :         b.mu.buf.Reset()
      63           1 : }
      64             : 
      65             : // String returns the current internal buffer.
      66           1 : func (b *InMemLogger) String() string {
      67           1 :         b.mu.Lock()
      68           1 :         defer b.mu.Unlock()
      69           1 :         return b.mu.buf.String()
      70           1 : }
      71             : 
      72             : // Infof is part of the Logger interface.
      73           1 : func (b *InMemLogger) Infof(format string, args ...interface{}) {
      74           1 :         s := fmt.Sprintf(format, args...)
      75           1 :         b.mu.Lock()
      76           1 :         defer b.mu.Unlock()
      77           1 :         b.mu.buf.Write([]byte(s))
      78           1 :         if n := len(s); n == 0 || s[n-1] != '\n' {
      79           1 :                 b.mu.buf.Write([]byte("\n"))
      80           1 :         }
      81             : }
      82             : 
      83             : // Errorf is part of the Logger interface.
      84           0 : func (b *InMemLogger) Errorf(format string, args ...interface{}) {
      85           0 :         b.Infof(format, args...)
      86           0 : }
      87             : 
      88             : // Fatalf is part of the Logger interface.
      89           1 : func (b *InMemLogger) Fatalf(format string, args ...interface{}) {
      90           1 :         b.Infof("FATAL: "+format, args...)
      91           1 : }
      92             : 
      93             : // LoggerAndTracer defines an interface for logging and tracing.
      94             : type LoggerAndTracer interface {
      95             :         Logger
      96             :         // Eventf formats and emits a tracing log, if tracing is enabled in the
      97             :         // current context. It can also emit to a regular log, if expensive
      98             :         // logging is enabled.
      99             :         Eventf(ctx context.Context, format string, args ...interface{})
     100             :         // IsTracingEnabled returns true if tracing is enabled for this context,
     101             :         // or expensive logging is enabled. It can be used as an optimization to
     102             :         // avoid calling Eventf (which will be a noop when tracing or expensive
     103             :         // logging is not enabled) to avoid the overhead of boxing the args.
     104             :         IsTracingEnabled(ctx context.Context) bool
     105             : }
     106             : 
     107             : // LoggerWithNoopTracer wraps a logger and does no tracing.
     108             : type LoggerWithNoopTracer struct {
     109             :         Logger
     110             : }
     111             : 
     112             : var _ LoggerAndTracer = &LoggerWithNoopTracer{}
     113             : 
     114             : // Eventf implements LoggerAndTracer.
     115           0 : func (*LoggerWithNoopTracer) Eventf(ctx context.Context, format string, args ...interface{}) {
     116           0 :         if invariants.Enabled && ctx == nil {
     117           0 :                 panic("Eventf context is nil")
     118             :         }
     119             : }
     120             : 
     121             : // IsTracingEnabled implements LoggerAndTracer.
     122           1 : func (*LoggerWithNoopTracer) IsTracingEnabled(ctx context.Context) bool {
     123           1 :         if invariants.Enabled && ctx == nil {
     124           0 :                 panic("IsTracingEnabled ctx is nil")
     125             :         }
     126           1 :         return false
     127             : }
     128             : 
     129             : // NoopLoggerAndTracer does no logging and tracing. Remember that struct{} is
     130             : // special cased in Go and does not incur an allocation when it backs the
     131             : // interface LoggerAndTracer.
     132             : type NoopLoggerAndTracer struct{}
     133             : 
     134             : var _ LoggerAndTracer = NoopLoggerAndTracer{}
     135             : 
     136             : // Infof implements LoggerAndTracer.
     137           0 : func (l NoopLoggerAndTracer) Infof(format string, args ...interface{}) {}
     138             : 
     139             : // Errorf implements LoggerAndTracer.
     140           0 : func (l NoopLoggerAndTracer) Errorf(format string, args ...interface{}) {}
     141             : 
     142             : // Fatalf implements LoggerAndTracer.
     143           0 : func (l NoopLoggerAndTracer) Fatalf(format string, args ...interface{}) {}
     144             : 
     145             : // Eventf implements LoggerAndTracer.
     146           0 : func (l NoopLoggerAndTracer) Eventf(ctx context.Context, format string, args ...interface{}) {
     147           0 :         if invariants.Enabled && ctx == nil {
     148           0 :                 panic("Eventf context is nil")
     149             :         }
     150             : }
     151             : 
     152             : // IsTracingEnabled implements LoggerAndTracer.
     153           1 : func (l NoopLoggerAndTracer) IsTracingEnabled(ctx context.Context) bool {
     154           1 :         if invariants.Enabled && ctx == nil {
     155           0 :                 panic("IsTracingEnabled ctx is nil")
     156             :         }
     157           1 :         return false
     158             : }

Generated by: LCOV version 1.14