forked from Cloud-Foundations/scotty
-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.go
211 lines (185 loc) · 6.09 KB
/
api.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Package scotty collects endpoint health metrics asynchronously.
package scotty
import (
"github.com/Symantec/scotty/hostid"
"github.com/Symantec/scotty/metrics"
"github.com/Symantec/scotty/sources"
"sync"
"time"
)
// Status represents the status of metric collection for a particular
// endpoint. Failure statuses are negative, success statuses are
// positive.
type Status int
const (
// failed to connect to endpoint
FailedToConnect Status = -1 - iota
// connected, but failed to collect metrics
FailedToPoll
)
const (
Unknown Status = iota
WaitingToConnect
Connecting
WaitingToPoll
Polling
Synced
)
func (s Status) String() string {
switch s {
case Unknown:
return ""
case WaitingToConnect:
return "waiting to connect"
case Connecting:
return "connecting"
case WaitingToPoll:
return "waiting to poll"
case Polling:
return "polling"
case Synced:
return "synced"
case FailedToConnect:
return "failed to connect"
case FailedToPoll:
return "failed to poll"
default:
return ""
}
}
// State represents the state of collecting metrics from a endpoint.
// State instances are immutable.
type State struct {
timestamp time.Time
sweepStartTime time.Time
waitToConnectDuration time.Duration
connectDuration time.Duration
waitToPollDuration time.Duration
pollDuration time.Duration
connectorName string
status Status
}
// ConnectorName returns the name of the connector
func (s *State) ConnectorName() string {
return s.connectorName
}
// Timestamp returns the timestamp of the last state change.
func (s *State) Timestamp() time.Time {
return s.timestamp
}
// SweepStartTime returns the start time of the sweep.
func (s *State) SweepStartTime() time.Time {
return s.sweepStartTime
}
// TimeSpentWaitingToConnect returns the time elapsed from the start of
// the sweep until establishing a connection first commences.
func (s *State) TimeSpentWaitingToConnect() time.Duration {
return s.waitToConnectDuration
}
// TimeSpentConnecting returns the time spent establishing a connection.
func (s *State) TimeSpentConnecting() time.Duration {
return s.connectDuration
}
// TimeSpentWaitingToPoll returns time elpased from when the connection
// was established to when downloading metrics first commences.
func (s *State) TimeSpentWaitingToPoll() time.Duration {
return s.waitToPollDuration
}
// TimeSpentPolling returns the time spent downloading the metrics.
func (s *State) TimeSpentPolling() time.Duration {
return s.pollDuration
}
// Status returns the status of the collection.
func (s *State) Status() Status {
return s.status
}
// Logger is the interface for instances that log metric collection events.
// Endpoint instances call Logger methods immediately after updating themselves.
// Logger instances must be safe to use among multiple goroutines.
type Logger interface {
// Called when new metrics come in from a given endpoint. If
// implementation returns a non-nil error, state goes to
// FailedtoPoll. Otherwise, state goes to Synced.
LogResponse(
e *Endpoint, response metrics.List, timestamp time.Time) error
// Called when error happens collecting metrics from a given
// endpoint.
// Also called when an error clears. In such a case both err and
// state are nil.
LogError(e *Endpoint, err error, state *State)
// Called when collection status changes on a given endpoint
LogStateChange(e *Endpoint, oldState, newState *State)
}
// Endpoint represents a particular endpoint with health metrics.
// Endpoint instances are safe to use with multiple goroutines.
type Endpoint struct {
// These fields are immutable
hostId *hostid.HostID
name string
conn sources.ResourceConnector
onePollAtATime chan bool
// These fields read and changed only by goroutine that has the
// onePollAtATime semaphore
state *State
errored bool
lock sync.Mutex
isTls bool
resourcePort uint
resource sources.Resource
}
// NewEndpointWithConnector creates a new endpoint for given host, port
// and connector.
func NewEndpointWithConnector(
hostId *hostid.HostID, appName string, connector sources.Connector) *Endpoint {
return newEndpoint(hostId, appName, connector)
}
// HostName returns the host name of the endpoint.
func (e *Endpoint) HostName() string {
return e.hostId.HostName
}
// IpAddress returns the IP Address if known or the empty string if not known.
func (e *Endpoint) IpAddress() string {
return e.hostId.IPAddress
}
// AppName returns the app name of the endpoint.
func (e *Endpoint) AppName() string {
return e.name
}
// ConnectorName returns the name of the underlying connector in this endpoint.
func (e *Endpoint) ConnectorName() string {
return e.conn.Name()
}
// Poll polls for metrics for this endpoint asynchronously.
// However, Poll may block while it waits to begin connecting if too many
// requests for metrics are in progress. Poll returns immediately if this
// instance is already in the process of collecting metrics.
// sweepStartTime is the start time of the current collection of metrics.
// isTls indicates whether or not TLS should be used
// port is the port to use to connect.
// logger logs collection events for this polling
func (e *Endpoint) Poll(
sweepStartTime time.Time, isTls bool, port uint, logger Logger) {
e.poll(sweepStartTime, isTls, port, logger)
}
// SetConcurrentPolls sets the maximum number of concurrent polls.
// Zero means no limit.
// Call SetConcurrentPolls at the beginning of the main() function before
// calling Endpoint.Poll
func SetConcurrentPolls(x uint) {
setConcurrentPolls(x)
}
// ConcurrentPolls returns the maximum number of concurrent polls.
// Default is 2 * number of CPUs. A return of 0 means no limit.
func ConcurrentPolls() uint {
return concurrentPolls
}
// SetConcurrentConnects sets the maximum number of concurrent connects.
// Call SetConcurrentConnects at the beginning of the main() function before
// calling Endpoint.Poll
func SetConcurrentConnects(x uint) {
setConcurrentConnects(x)
}
// ConcurrentConnects returns the maximum number of concurrent connects.
func ConcurrentConnects() uint {
return concurrentConnects
}