github.com/cloudwego/hertz@v0.9.3/pkg/common/tracer/stats/event.go (about) 1 /* 2 * Copyright 2022 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package stats 18 19 import ( 20 "sync" 21 "sync/atomic" 22 23 "github.com/cloudwego/hertz/pkg/common/errors" 24 ) 25 26 // EventIndex indicates a unique event. 27 type EventIndex int 28 29 // Level sets the record level. 30 type Level int 31 32 // Event levels. 33 const ( 34 LevelDisabled Level = iota 35 LevelBase 36 LevelDetailed 37 ) 38 39 // Event is used to indicate a specific event. 40 type Event interface { 41 Index() EventIndex 42 Level() Level 43 } 44 45 type event struct { 46 idx EventIndex 47 level Level 48 } 49 50 // Index implements the Event interface. 51 func (e event) Index() EventIndex { 52 return e.idx 53 } 54 55 // Level implements the Event interface. 56 func (e event) Level() Level { 57 return e.level 58 } 59 60 const ( 61 _ EventIndex = iota 62 serverHandleStart 63 serverHandleFinish 64 httpStart 65 httpFinish 66 readHeaderStart 67 readHeaderFinish 68 readBodyStart 69 readBodyFinish 70 writeStart 71 writeFinish 72 predefinedEventNum 73 ) 74 75 // Predefined events. 76 var ( 77 HTTPStart = newEvent(httpStart, LevelBase) 78 HTTPFinish = newEvent(httpFinish, LevelBase) 79 80 ServerHandleStart = newEvent(serverHandleStart, LevelDetailed) 81 ServerHandleFinish = newEvent(serverHandleFinish, LevelDetailed) 82 ReadHeaderStart = newEvent(readHeaderStart, LevelDetailed) 83 ReadHeaderFinish = newEvent(readHeaderFinish, LevelDetailed) 84 ReadBodyStart = newEvent(readBodyStart, LevelDetailed) 85 ReadBodyFinish = newEvent(readBodyFinish, LevelDetailed) 86 WriteStart = newEvent(writeStart, LevelDetailed) 87 WriteFinish = newEvent(writeFinish, LevelDetailed) 88 ) 89 90 // errors 91 var ( 92 ErrNotAllowed = errors.NewPublic("event definition is not allowed after initialization") 93 ErrDuplicated = errors.NewPublic("event name is already defined") 94 ) 95 96 var ( 97 lock sync.RWMutex 98 inited int32 99 userDefined = make(map[string]Event) 100 maxEventNum = int(predefinedEventNum) 101 ) 102 103 // FinishInitialization freezes all events defined and prevents further definitions to be added. 104 func FinishInitialization() { 105 atomic.StoreInt32(&inited, 1) 106 } 107 108 // DefineNewEvent allows user to add event definitions during program initialization. 109 func DefineNewEvent(name string, level Level) (Event, error) { 110 if atomic.LoadInt32(&inited) == 1 { 111 return nil, ErrNotAllowed 112 } 113 lock.Lock() 114 defer lock.Unlock() 115 evt, exist := userDefined[name] 116 if exist { 117 return evt, ErrDuplicated 118 } 119 userDefined[name] = newEvent(EventIndex(maxEventNum), level) 120 maxEventNum++ 121 return userDefined[name], nil 122 } 123 124 // MaxEventNum returns the number of event defined. 125 func MaxEventNum() int { 126 lock.RLock() 127 defer lock.RUnlock() 128 return maxEventNum 129 } 130 131 func newEvent(idx EventIndex, level Level) Event { 132 return event{ 133 idx: idx, 134 level: level, 135 } 136 }