github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekalog/integrator_common_private.go (about) 1 // Copyright © 2020. 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 "io" 10 "os" 11 "unsafe" 12 13 "github.com/qioalice/ekago/v3/internal/ekaclike" 14 "github.com/qioalice/ekago/v3/internal/ekasys" 15 ) 16 17 //noinspection GoSnakeCaseUsage 18 type ( 19 // _CI_Output is a CommonIntegrator part that contains encoder 20 // and destination io.Writer set, encoded Entry will be written to. 21 // 22 // It used at the CommonIntegrator building procedure. 23 _CI_Output struct { 24 minLevel Level // minimum level log entry should have to be processed 25 stacktraceMinLevel Level // minimum level starting with stacktrace must be added to the entry 26 encoder CI_Encoder // func that encoders Entry object to []byte 27 writers []io.Writer // slice of io.Writer, log entry will be written to 28 preEncodedFields []byte // raw data of pre-encoded fields 29 } 30 ) 31 32 // assertNil panics if current CommonIntegrator is nil. 33 func (ci *CommonIntegrator) assertNil() { 34 if ci == nil { 35 panic("CommonIntegrator is nil object") 36 } 37 } 38 39 // assertWithLock calls assertNil(), locks then CommonIntegrator and checks, 40 // whether current CommonIntegrator is not registered before and has at least 1 41 // valid io.Writer. 42 // The caller must take a responsibility about unlocking CommonIntegrator. 43 func (ci *CommonIntegrator) assertWithLock() { 44 ci.assertNil() 45 ci.mu.Lock() 46 switch { 47 case ci.isRegistered: 48 panic("Failed to build CommonIntegrator. It has already registered.") 49 } 50 } 51 52 // build tries to prepare CommonIntegrator to be used with Logger: 53 // - Drops last not fully registered _CI_Output object, 54 // - Calculates lowest levels of all _CI_Output. 55 // 56 // Requirements: 57 // - Integrator must not be nil (even typed nil), panic otherwise; 58 // - If Integrator is CommonIntegrator 59 // it must not be registered with some Logger before, panic otherwise; 60 // - If Integrator is CommonIntegrator 61 // it must have at least 1 registered io.Writer, panic otherwise. 62 func (ci *CommonIntegrator) build() { 63 64 // build() cannot be called if CommonIntegrator is nil. 65 // So, another one nil check is redundant. 66 67 ci.assertWithLock() 68 defer ci.mu.Unlock() 69 70 if len(ci.output) == 0 { 71 panic("Failed to build CommonIntegrator. There is no valid io.Writer.") 72 } 73 74 // Use stdout (synced) as writer for last encoder if user forgot/omit 75 // to specify it explicitly AND if it has not been specified yet. 76 77 if len(ci.output[ci.idx].writers) == 0 { 78 79 // Try to find stdout in the previous writers. 80 81 stdoutNormal := unsafe.Pointer(os.Stdout) 82 stdoutSynced := unsafe.Pointer(ekasys.Stdout) 83 84 found := false 85 86 for i := 0; i < ci.idx && !found; i++ { 87 for j, n := 0, len(ci.output[i].writers); j < n && !found; j++ { 88 writerPtr := ekaclike.TakeRealAddr(ci.output[i].writers[j]) 89 found = writerPtr == stdoutNormal || writerPtr == stdoutSynced 90 } 91 } 92 93 if found { 94 // If stdout was used already, drop the last encoder. 95 ci.output = ci.output[:ci.idx] 96 } else { 97 ci.output[ci.idx].writers = append(ci.output[ci.idx].writers, ekasys.Stdout) 98 } 99 } 100 101 ci.oll = LEVEL_WARNING 102 ci.stll = LEVEL_WARNING 103 104 for _, output := range ci.output { 105 if output.minLevel > ci.oll { 106 ci.oll = output.minLevel 107 } 108 if output.stacktraceMinLevel > ci.stll { 109 ci.stll = output.stacktraceMinLevel 110 } 111 } 112 113 ci.isRegistered = true 114 }