|
5 | 5 | package main |
6 | 6 |
|
7 | 7 | import ( |
8 | | - "errors" |
9 | | - "fmt" |
10 | | - "net/http" |
11 | | - "path" |
12 | | - "time" |
13 | | - |
14 | | - "cloud.google.com/go/compute/metadata" |
15 | | - "contrib.go.opencensus.io/exporter/prometheus" |
16 | | - "contrib.go.opencensus.io/exporter/stackdriver" |
17 | 8 | "go.opencensus.io/plugin/ochttp" |
18 | 9 | "go.opencensus.io/stats" |
19 | 10 | "go.opencensus.io/stats/view" |
20 | 11 | "go.opencensus.io/tag" |
21 | | - mrpb "google.golang.org/genproto/googleapis/api/monitoredres" |
22 | 12 | ) |
23 | 13 |
|
24 | 14 | var ( |
@@ -112,148 +102,18 @@ var ( |
112 | 102 | } |
113 | 103 | ) |
114 | 104 |
|
115 | | -// newMetricService initializes a *metricService. |
116 | | -// |
117 | | -// The metricService returned is configured to send metric data to StackDriver. |
118 | | -// When the sandbox is not running on GCE, it will host metrics through a prometheus HTTP handler. |
119 | | -func newMetricService() (*metricService, error) { |
120 | | - err := view.Register( |
121 | | - containerCount, |
122 | | - unwantedContainerCount, |
123 | | - maxContainerCount, |
124 | | - containerCreateCount, |
125 | | - containerCreationLatency, |
126 | | - ServerRequestCountView, |
127 | | - ServerRequestBytesView, |
128 | | - ServerResponseBytesView, |
129 | | - ServerLatencyView, |
130 | | - ServerRequestCountByMethod, |
131 | | - ServerResponseCountByStatusCode) |
132 | | - if err != nil { |
133 | | - return nil, err |
134 | | - } |
135 | | - |
136 | | - if !metadata.OnGCE() { |
137 | | - view.SetReportingPeriod(5 * time.Second) |
138 | | - pe, err := prometheus.NewExporter(prometheus.Options{}) |
139 | | - if err != nil { |
140 | | - return nil, fmt.Errorf("newMetricsService(): prometheus.NewExporter: %w", err) |
141 | | - } |
142 | | - view.RegisterExporter(pe) |
143 | | - return &metricService{pExporter: pe}, nil |
144 | | - } |
145 | | - |
146 | | - projID, err := metadata.ProjectID() |
147 | | - if err != nil { |
148 | | - return nil, err |
149 | | - } |
150 | | - gr, err := gceResource("go-playground-sandbox") |
151 | | - if err != nil { |
152 | | - return nil, err |
153 | | - } |
154 | | - |
155 | | - sd, err := stackdriver.NewExporter(stackdriver.Options{ |
156 | | - ProjectID: projID, |
157 | | - MonitoredResource: gr, |
158 | | - ReportingInterval: time.Minute, // Minimum interval for stackdriver is 1 minute. |
159 | | - }) |
160 | | - if err != nil { |
161 | | - return nil, err |
162 | | - } |
163 | | - |
164 | | - // Minimum interval for stackdriver is 1 minute. |
165 | | - view.SetReportingPeriod(time.Minute) |
166 | | - // Start the metrics exporter. |
167 | | - if err := sd.StartMetricsExporter(); err != nil { |
168 | | - return nil, err |
169 | | - } |
170 | | - |
171 | | - return &metricService{sdExporter: sd}, nil |
172 | | -} |
173 | | - |
174 | | -// metricService controls metric exporters. |
175 | | -type metricService struct { |
176 | | - sdExporter *stackdriver.Exporter |
177 | | - pExporter *prometheus.Exporter |
178 | | -} |
179 | | - |
180 | | -func (m *metricService) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
181 | | - if m.pExporter != nil { |
182 | | - m.pExporter.ServeHTTP(w, r) |
183 | | - return |
184 | | - } |
185 | | - http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) |
186 | | -} |
187 | | - |
188 | | -// Stop flushes metrics and stops exporting. Stop should be called before exiting. |
189 | | -func (m *metricService) Stop() { |
190 | | - if sde := m.sdExporter; sde != nil { |
191 | | - // Flush any unsent data before exiting. |
192 | | - sde.Flush() |
193 | | - |
194 | | - sde.StopMetricsExporter() |
195 | | - } |
196 | | -} |
197 | | - |
198 | | -// monitoredResource wraps a *mrpb.MonitoredResource to implement the |
199 | | -// monitoredresource.MonitoredResource interface. |
200 | | -type monitoredResource mrpb.MonitoredResource |
201 | | - |
202 | | -func (r *monitoredResource) MonitoredResource() (resType string, labels map[string]string) { |
203 | | - return r.Type, r.Labels |
204 | | -} |
205 | | - |
206 | | -// gceResource populates a monitoredResource with GCE Metadata. |
207 | | -// |
208 | | -// The returned monitoredResource will have the type set to "generic_task". |
209 | | -func gceResource(jobName string) (*monitoredResource, error) { |
210 | | - projID, err := metadata.ProjectID() |
211 | | - if err != nil { |
212 | | - return nil, err |
213 | | - } |
214 | | - zone, err := metadata.Zone() |
215 | | - if err != nil { |
216 | | - return nil, err |
217 | | - } |
218 | | - iname, err := metadata.InstanceName() |
219 | | - if err != nil { |
220 | | - return nil, err |
221 | | - } |
222 | | - igName, err := instanceGroupName() |
223 | | - if err != nil { |
224 | | - return nil, err |
225 | | - } else if igName == "" { |
226 | | - igName = projID |
227 | | - } |
228 | | - |
229 | | - return (*monitoredResource)(&mrpb.MonitoredResource{ |
230 | | - Type: "generic_task", // See: https://cloud.google.com/monitoring/api/resources#tag_generic_task |
231 | | - Labels: map[string]string{ |
232 | | - "project_id": projID, |
233 | | - "location": zone, |
234 | | - "namespace": igName, |
235 | | - "job": jobName, |
236 | | - "task_id": iname, |
237 | | - }, |
238 | | - }), nil |
239 | | -} |
240 | | - |
241 | | -// instanceGroupName fetches the instanceGroupName from the instance metadata. |
242 | | -// |
243 | | -// The instance group manager applies a custom "created-by" attribute to the instance, which is not part of the |
244 | | -// metadata package API, and must be queried separately. |
245 | | -// |
246 | | -// An empty string will be returned if a metadata.NotDefinedError is returned when fetching metadata. |
247 | | -// An error will be returned if other errors occur when fetching metadata. |
248 | | -func instanceGroupName() (string, error) { |
249 | | - ig, err := metadata.InstanceAttributeValue("created-by") |
250 | | - if nde := metadata.NotDefinedError(""); err != nil && !errors.As(err, &nde) { |
251 | | - return "", err |
252 | | - } |
253 | | - if ig == "" { |
254 | | - return "", nil |
255 | | - } |
256 | | - // "created-by" format: "projects/{{InstanceID}}/zones/{{Zone}}/instanceGroupManagers/{{Instance Group Name}} |
257 | | - ig = path.Base(ig) |
258 | | - return ig, err |
| 105 | +// views should contain all measurements. All *view.View added to this |
| 106 | +// slice will be registered and exported to the metric service. |
| 107 | +var views = []*view.View{ |
| 108 | + containerCount, |
| 109 | + unwantedContainerCount, |
| 110 | + maxContainerCount, |
| 111 | + containerCreateCount, |
| 112 | + containerCreationLatency, |
| 113 | + ServerRequestCountView, |
| 114 | + ServerRequestBytesView, |
| 115 | + ServerResponseBytesView, |
| 116 | + ServerLatencyView, |
| 117 | + ServerRequestCountByMethod, |
| 118 | + ServerResponseCountByStatusCode, |
259 | 119 | } |
0 commit comments