github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/metric/emit.go (about) 1 package metric 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "code.cloudfoundry.org/lager" 9 10 "github.com/pf-qiu/concourse/v6/atc/db" 11 flags "github.com/jessevdk/go-flags" 12 ) 13 14 type Event struct { 15 Name string 16 Value float64 17 Attributes map[string]string 18 Host string 19 Time time.Time 20 } 21 22 //go:generate counterfeiter . Emitter 23 type Emitter interface { 24 Emit(lager.Logger, Event) 25 } 26 27 //go:generate counterfeiter . EmitterFactory 28 type EmitterFactory interface { 29 Description() string 30 IsConfigured() bool 31 NewEmitter() (Emitter, error) 32 } 33 34 type Monitor struct { 35 emitter Emitter 36 eventHost string 37 eventAttributes map[string]string 38 emissions chan eventEmission 39 emitterFactories []EmitterFactory 40 41 Databases []db.Conn 42 DatabaseQueries Counter 43 44 ContainersCreated Counter 45 VolumesCreated Counter 46 47 FailedContainers Counter 48 FailedVolumes Counter 49 50 ContainersDeleted Counter 51 VolumesDeleted Counter 52 ChecksDeleted Counter 53 54 JobsScheduled Counter 55 JobsScheduling Gauge 56 57 BuildsStarted Counter 58 BuildsRunning Gauge 59 60 TasksWaiting map[TasksWaitingLabels]*Gauge 61 62 ChecksFinishedWithError Counter 63 ChecksFinishedWithSuccess Counter 64 ChecksStarted Counter 65 ChecksEnqueued Counter 66 67 ConcurrentRequests map[string]*Gauge 68 ConcurrentRequestsLimitHit map[string]*Counter 69 70 VolumesStreamed Counter 71 } 72 73 var Metrics = NewMonitor() 74 75 func NewMonitor() *Monitor { 76 return &Monitor{ 77 TasksWaiting: map[TasksWaitingLabels]*Gauge{}, 78 ConcurrentRequests: map[string]*Gauge{}, 79 ConcurrentRequestsLimitHit: map[string]*Counter{}, 80 } 81 } 82 83 func (m *Monitor) RegisterEmitter(factory EmitterFactory) { 84 m.emitterFactories = append(m.emitterFactories, factory) 85 } 86 87 func (m *Monitor) WireEmitters(group *flags.Group) { 88 for _, factory := range m.emitterFactories { 89 _, err := group.AddGroup(fmt.Sprintf("Metric Emitter (%s)", factory.Description()), "", factory) 90 if err != nil { 91 panic(err) 92 } 93 } 94 } 95 96 type eventEmission struct { 97 event Event 98 logger lager.Logger 99 } 100 101 func (m *Monitor) Initialize(logger lager.Logger, host string, attributes map[string]string, bufferSize uint32) error { 102 logger.Debug("metric-initialize", lager.Data{ 103 "host": host, 104 "attributes": attributes, 105 "buffer-size": bufferSize, 106 }) 107 108 var ( 109 emitterDescriptions []string 110 err error 111 ) 112 113 for _, factory := range m.emitterFactories { 114 if factory.IsConfigured() { 115 emitterDescriptions = append(emitterDescriptions, factory.Description()) 116 } 117 } 118 if len(emitterDescriptions) > 1 { 119 return fmt.Errorf("Multiple emitters configured: %s", strings.Join(emitterDescriptions, ", ")) 120 } 121 122 var emitter Emitter 123 124 for _, factory := range m.emitterFactories { 125 if factory.IsConfigured() { 126 emitter, err = factory.NewEmitter() 127 if err != nil { 128 return err 129 } 130 } 131 } 132 133 if emitter == nil { 134 return nil 135 } 136 137 m.emitter = emitter 138 m.eventHost = host 139 m.eventAttributes = attributes 140 m.emissions = make(chan eventEmission, int(bufferSize)) 141 142 go m.emitLoop() 143 144 return nil 145 } 146 147 func (m *Monitor) emit(logger lager.Logger, event Event) { 148 if m.emitter == nil { 149 return 150 } 151 152 event.Host = m.eventHost 153 event.Time = time.Now() 154 155 mergedAttributes := map[string]string{} 156 for k, v := range m.eventAttributes { 157 mergedAttributes[k] = v 158 } 159 160 if event.Attributes != nil { 161 for k, v := range event.Attributes { 162 mergedAttributes[k] = v 163 } 164 } 165 166 event.Attributes = mergedAttributes 167 168 select { 169 case m.emissions <- eventEmission{logger: logger, event: event}: 170 default: 171 logger.Error("queue-full", nil) 172 } 173 } 174 175 func (m *Monitor) emitLoop() { 176 for emission := range m.emissions { 177 m.emitter.Emit(emission.logger.Session("emit"), emission.event) 178 } 179 }