-
Notifications
You must be signed in to change notification settings - Fork 1k
/
stackdriver_client.go
129 lines (108 loc) · 3.64 KB
/
stackdriver_client.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
package scalers
import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
"cloud.google.com/go/compute/metadata"
monitoring "cloud.google.com/go/monitoring/apiv3/v2"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
"google.golang.org/api/iterator"
option "google.golang.org/api/option"
monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)
// StackDriverClient is a generic client to fetch metrics from Stackdriver. Can be used
// for a stackdriver scaler in the future
type StackDriverClient struct {
metricsClient *monitoring.MetricClient
credentials GoogleApplicationCredentials
projectID string
}
// NewStackDriverClient creates a new stackdriver client with the credentials that are passed
func NewStackDriverClient(ctx context.Context, credentials string) (*StackDriverClient, error) {
var gcpCredentials GoogleApplicationCredentials
if err := json.Unmarshal([]byte(credentials), &gcpCredentials); err != nil {
return nil, err
}
clientOption := option.WithCredentialsJSON([]byte(credentials))
client, err := monitoring.NewMetricClient(ctx, clientOption)
if err != nil {
return nil, err
}
return &StackDriverClient{
metricsClient: client,
credentials: gcpCredentials,
}, nil
}
// NewStackDriverClient creates a new stackdriver client with the credentials underlying
func NewStackDriverClientPodIdentity(ctx context.Context) (*StackDriverClient, error) {
client, err := monitoring.NewMetricClient(ctx)
if err != nil {
return nil, err
}
c := metadata.NewClient(&http.Client{})
project, err := c.ProjectID()
if err != nil {
return nil, err
}
return &StackDriverClient{
metricsClient: client,
projectID: project,
}, nil
}
// GetMetrics fetches metrics from stackdriver for a specific filter for the last minute
func (s StackDriverClient) GetMetrics(ctx context.Context, filter string, projectID string) (int64, error) {
// Set the start time to 1 minute ago
startTime := time.Now().UTC().Add(time.Minute * -2)
// Set the end time to now
endTime := time.Now().UTC()
// Create a request with the filter and the GCP project ID
var req = &monitoringpb.ListTimeSeriesRequest{
Filter: filter,
Interval: &monitoringpb.TimeInterval{
StartTime: ×tamp.Timestamp{Seconds: startTime.Unix()},
EndTime: ×tamp.Timestamp{Seconds: endTime.Unix()},
},
}
switch projectID {
case "":
if len(s.projectID) > 0 {
req.Name = "projects/" + s.projectID
} else {
req.Name = "projects/" + s.credentials.ProjectID
}
default:
req.Name = "projects/" + projectID
}
// Get an iterator with the list of time series
it := s.metricsClient.ListTimeSeries(ctx, req)
var value int64 = -1
// Get the value from the first metric returned
resp, err := it.Next()
if err == iterator.Done {
return value, fmt.Errorf("could not find stackdriver metric with filter %s", filter)
}
if err != nil {
return value, err
}
if len(resp.GetPoints()) > 0 {
point := resp.GetPoints()[0]
value = point.GetValue().GetInt64Value()
}
return value, nil
}
// GoogleApplicationCredentials is a struct representing the format of a service account
// credentials file
type GoogleApplicationCredentials struct {
Type string `json:"type"`
ProjectID string `json:"project_id"`
PrivateKeyID string `json:"private_key_id"`
PrivateKey string `json:"private_key"`
ClientEmail string `json:"client_email"`
ClientID string `json:"client_id"`
AuthURI string `json:"auth_uri"`
TokenURI string `json:"token_uri"`
AuthProviderCertURL string `json:"auth_provider_x509_cert_url"`
ClientX509CertURL string `json:"client_x509_cert_url"`
}