github.com/developest/gtm-core@v1.0.4-0.20220111132249-cc80a3372c3f/util/clogger.go (about)

     1  // Copyright 2016 Michael Schenk. All rights reserved.
     2  // Use of this source code is governed by a MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package util
     6  
     7  import (
     8  	"fmt"
     9  	"log"
    10  	"path/filepath"
    11  	"runtime"
    12  )
    13  
    14  // ContextLogger adds child and parent file location to logging
    15  type ContextLogger struct {
    16  	skip   int
    17  	logger *log.Logger
    18  }
    19  
    20  // NewContextLogger initializes a ContextLogger struct
    21  func NewContextLogger(x *log.Logger, skip int) *ContextLogger {
    22  	return &ContextLogger{logger: x, skip: skip}
    23  }
    24  
    25  // Printf prints log message with context and format
    26  func (c *ContextLogger) Printf(format string, v ...interface{}) {
    27  	s := c.stack()
    28  	v = append([]interface{}{s.String()}, v...)
    29  	c.logger.Printf(`%s`+format, v...)
    30  }
    31  
    32  // Print prints log message with context
    33  func (c *ContextLogger) Print(v ...interface{}) {
    34  	s := c.stack()
    35  	v = append([]interface{}{s.String()}, v...)
    36  	c.logger.Print(v...)
    37  }
    38  
    39  // Println prints log message with context
    40  func (c *ContextLogger) Println(v ...interface{}) {
    41  	s := c.stack()
    42  	v = append([]interface{}{s.String()}, v...)
    43  	c.logger.Println(v...)
    44  }
    45  
    46  func (c *ContextLogger) stack() FamilyCallStack {
    47  	pc := make([]uintptr, 15)
    48  	n := runtime.Callers(c.skip, pc)
    49  	fcs := NewFamilyCallStack(runtime.CallersFrames(pc[:n]))
    50  	return fcs
    51  }
    52  
    53  // NewFamilyCallStack initializes a FamilyCallStack struct
    54  func NewFamilyCallStack(f *runtime.Frames) FamilyCallStack {
    55  	child, _ := f.Next()
    56  	parent, _ := f.Next()
    57  
    58  	cframe := CallFrame{
    59  		File:     filepath.Base(child.File),
    60  		Line:     child.Line,
    61  		Function: filepath.Base(child.Function),
    62  	}
    63  
    64  	pframe := CallFrame{
    65  		File:     filepath.Base(parent.File),
    66  		Line:     parent.Line,
    67  		Function: filepath.Base(parent.Function),
    68  	}
    69  
    70  	return FamilyCallStack{Parent: pframe, Child: cframe}
    71  }
    72  
    73  // CallFrame contains the file, line number and function
    74  type CallFrame struct {
    75  	File     string
    76  	Line     int
    77  	Function string
    78  }
    79  
    80  // FamilyCallStack contains the child and parent call frames
    81  type FamilyCallStack struct {
    82  	Parent CallFrame
    83  	Child  CallFrame
    84  }
    85  
    86  // String returns a canonical representation of a FamilyCallStack
    87  func (f FamilyCallStack) String() string {
    88  	return fmt.Sprint(f.Parent, " > ", f.Child, " ")
    89  }
    90  
    91  // String returns a canonical representation of a CallFrame
    92  func (c CallFrame) String() string {
    93  	return fmt.Sprintf("%s:%d %s", c.File, c.Line, c.Function)
    94  }