github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekalog/entry_private.go (about)

     1  // Copyright © 2020-2021. All rights reserved.
     2  // Author: Ilya Stroy.
     3  // Contacts: iyuryevich@pm.me, https://github.com/qioalice
     4  // License: https://opensource.org/licenses/MIT
     5  
     6  package ekalog
     7  
     8  import (
     9  	"runtime"
    10  
    11  	"github.com/qioalice/ekago/v3/ekasys"
    12  	"github.com/qioalice/ekago/v3/internal/ekaletter"
    13  )
    14  
    15  // prepare prepares current Entry for being used assuming that Entry has been
    16  // obtained from the Entry's pool. Returns prepared Entry.
    17  func (e *Entry) prepare() *Entry {
    18  
    19  	// Because we can't detect when work with Entry is done while user chains
    20  	// Logger's method (with Entry cloning), we must use runtime.SetFinalizer()
    21  	// to return Entry to the its pool.
    22  	if e.needSetFinalizer {
    23  		runtime.SetFinalizer(e, releaseEntryForFinalizer)
    24  		e.needSetFinalizer = false
    25  	}
    26  
    27  	return e
    28  }
    29  
    30  // cleanup frees all allocated resources (RAM in 99% cases) by Entry, preparing
    31  // it for being returned to the pool and being reused in the future.
    32  func (e *Entry) cleanup() (this *Entry) {
    33  
    34  	e.l = nil
    35  	e.LogLetter.StackTrace = nil
    36  	e.ErrLetter = nil
    37  
    38  	ekaletter.LReset(e.LogLetter)
    39  	return e
    40  }
    41  
    42  // clone clones the current Entry and returns it copy. It takes a new Entry
    43  // object from its pool to avoid unnecessary RAM allocations.
    44  func (e *Entry) clone() *Entry {
    45  
    46  	clonedEntry := acquireEntry()
    47  
    48  	// Clone Fields using most efficient way.
    49  	// Do not allocate RAM if it's already allocated (but nulled).
    50  	if lFrom := len(e.LogLetter.Fields); lFrom > 0 {
    51  		if cTo := cap(clonedEntry.LogLetter.Fields); cTo < lFrom {
    52  			clonedEntry.LogLetter.Fields = make([]ekaletter.LetterField, lFrom)
    53  		} else {
    54  			// lFrom <= cTo, it's ok to do that
    55  			clonedEntry.LogLetter.Fields =
    56  				clonedEntry.LogLetter.Fields[:lFrom]
    57  		}
    58  		for i := 0; i < lFrom; i++ {
    59  			clonedEntry.LogLetter.Fields[i] = e.LogLetter.Fields[i]
    60  		}
    61  	}
    62  
    63  	// There is no need to zero Time, Level, LetterMessage fields
    64  	// because they used only in one place and will be overwritten anyway.
    65  
    66  	return clonedEntry
    67  }
    68  
    69  // addStacktraceIfNotPresented generates and adds stacktrace
    70  // (if it's not presented by ErrLetter's field).
    71  func (e *Entry) addStacktraceIfNotPresented() (this *Entry) {
    72  	if e.ErrLetter == nil {
    73  		e.LogLetter.StackTrace = ekasys.GetStackTrace(3, -1).ExcludeInternal()
    74  	}
    75  	return e
    76  }