github.com/lusis/distribution@v2.0.1+incompatible/notifications/endpoint.go (about) 1 package notifications 2 3 import ( 4 "net/http" 5 "time" 6 ) 7 8 // EndpointConfig covers the optional configuration parameters for an active 9 // endpoint. 10 type EndpointConfig struct { 11 Headers http.Header 12 Timeout time.Duration 13 Threshold int 14 Backoff time.Duration 15 } 16 17 // defaults set any zero-valued fields to a reasonable default. 18 func (ec *EndpointConfig) defaults() { 19 if ec.Timeout <= 0 { 20 ec.Timeout = time.Second 21 } 22 23 if ec.Threshold <= 0 { 24 ec.Threshold = 10 25 } 26 27 if ec.Backoff <= 0 { 28 ec.Backoff = time.Second 29 } 30 } 31 32 // Endpoint is a reliable, queued, thread-safe sink that notify external http 33 // services when events are written. Writes are non-blocking and always 34 // succeed for callers but events may be queued internally. 35 type Endpoint struct { 36 Sink 37 url string 38 name string 39 40 EndpointConfig 41 42 metrics *safeMetrics 43 } 44 45 // NewEndpoint returns a running endpoint, ready to receive events. 46 func NewEndpoint(name, url string, config EndpointConfig) *Endpoint { 47 var endpoint Endpoint 48 endpoint.name = name 49 endpoint.url = url 50 endpoint.EndpointConfig = config 51 endpoint.defaults() 52 endpoint.metrics = newSafeMetrics() 53 54 // Configures the inmemory queue, retry, http pipeline. 55 endpoint.Sink = newHTTPSink( 56 endpoint.url, endpoint.Timeout, endpoint.Headers, 57 endpoint.metrics.httpStatusListener()) 58 endpoint.Sink = newRetryingSink(endpoint.Sink, endpoint.Threshold, endpoint.Backoff) 59 endpoint.Sink = newEventQueue(endpoint.Sink, endpoint.metrics.eventQueueListener()) 60 61 register(&endpoint) 62 return &endpoint 63 } 64 65 // Name returns the name of the endpoint, generally used for debugging. 66 func (e *Endpoint) Name() string { 67 return e.name 68 } 69 70 // URL returns the url of the endpoint. 71 func (e *Endpoint) URL() string { 72 return e.url 73 } 74 75 // ReadMetrics populates em with metrics from the endpoint. 76 func (e *Endpoint) ReadMetrics(em *EndpointMetrics) { 77 e.metrics.Lock() 78 defer e.metrics.Unlock() 79 80 *em = e.metrics.EndpointMetrics 81 // Map still need to copied in a threadsafe manner. 82 em.Statuses = make(map[string]int) 83 for k, v := range e.metrics.Statuses { 84 em.Statuses[k] = v 85 } 86 }