This repository has been archived by the owner on Oct 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 79
/
monitored_resources.go
232 lines (197 loc) · 7.78 KB
/
monitored_resources.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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// Copyright 2018, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package monitoredresource
import (
"fmt"
"os"
"sync"
)
// Interface is a type that represent monitor resource that satisfies monitoredresource.Interface
type Interface interface {
// MonitoredResource returns the resource type and resource labels.
MonitoredResource() (resType string, labels map[string]string)
}
// GKEContainer represents gke_container type monitored resource.
// For definition refer to
// https://cloud.google.com/monitoring/api/resources#tag_gke_container
type GKEContainer struct {
// ProjectID is the identifier of the GCP project associated with this resource, such as "my-project".
ProjectID string
// InstanceID is the numeric VM instance identifier assigned by Compute Engine.
InstanceID string
// ClusterName is the name for the cluster the container is running in.
ClusterName string
// ContainerName is the name of the container.
ContainerName string
// NamespaceID is the identifier for the cluster namespace the container is running in
NamespaceID string
// PodID is the identifier for the pod the container is running in.
PodID string
// Zone is the Compute Engine zone in which the VM is running.
Zone string
// LoggingMonitoringV2Enabled is the identifier if user enabled V2 logging and monitoring for GKE
LoggingMonitoringV2Enabled bool
}
// MonitoredResource returns resource type and resource labels for GKEContainer
func (gke *GKEContainer) MonitoredResource() (resType string, labels map[string]string) {
labels = map[string]string{
"project_id": gke.ProjectID,
"cluster_name": gke.ClusterName,
"container_name": gke.ContainerName,
}
var typ string
if gke.LoggingMonitoringV2Enabled {
typ = "k8s_container"
labels["pod_name"] = gke.PodID
labels["namespace_name"] = gke.NamespaceID
labels["location"] = gke.Zone
} else {
typ = "gke_container"
labels["pod_id"] = gke.PodID
labels["namespace_id"] = gke.NamespaceID
labels["zone"] = gke.Zone
labels["instance_id"] = gke.InstanceID
}
return typ, labels
}
// GCEInstance represents gce_instance type monitored resource.
// For definition refer to
// https://cloud.google.com/monitoring/api/resources#tag_gce_instance
type GCEInstance struct {
// ProjectID is the identifier of the GCP project associated with this resource, such as "my-project".
ProjectID string
// InstanceID is the numeric VM instance identifier assigned by Compute Engine.
InstanceID string
// Zone is the Compute Engine zone in which the VM is running.
Zone string
}
// MonitoredResource returns resource type and resource labels for GCEInstance
func (gce *GCEInstance) MonitoredResource() (resType string, labels map[string]string) {
labels = map[string]string{
"project_id": gce.ProjectID,
"instance_id": gce.InstanceID,
"zone": gce.Zone,
}
return "gce_instance", labels
}
// AWSEC2Instance represents aws_ec2_instance type monitored resource.
// For definition refer to
// https://cloud.google.com/monitoring/api/resources#tag_aws_ec2_instance
type AWSEC2Instance struct {
// AWSAccount is the AWS account number for the VM.
AWSAccount string
// InstanceID is the instance id of the instance.
InstanceID string
// Region is the AWS region for the VM. The format of this field is "aws:{region}",
// where supported values for {region} are listed at
// http://docs.aws.amazon.com/general/latest/gr/rande.html.
Region string
}
// MonitoredResource returns resource type and resource labels for AWSEC2Instance
func (aws *AWSEC2Instance) MonitoredResource() (resType string, labels map[string]string) {
labels = map[string]string{
"aws_account": aws.AWSAccount,
"instance_id": aws.InstanceID,
"region": aws.Region,
}
return "aws_ec2_instance", labels
}
// Autodetect auto detects monitored resources based on
// the environment where the application is running.
// It supports detection of following resource types
// 1. gke_container:
// 2. gce_instance:
// 3. aws_ec2_instance:
//
// Returns MonitoredResInterface which implements getLabels() and getType()
// For resource definition go to https://cloud.google.com/monitoring/api/resources
func Autodetect() Interface {
return func() Interface {
detectOnce.Do(func() {
var awsIdentityDoc *awsIdentityDocument
var gcpMetadata *gcpMetadata
// First attempts to retrieve AWS Identity Doc and GCP metadata.
// It then determines the resource type
// In GCP and AWS environment both func finishes quickly. However,
// in an environment other than those (e.g local laptop) it
// takes 2 seconds for GCP and 5-6 for AWS.
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
awsIdentityDoc = retrieveAWSIdentityDocument()
}()
go func() {
defer wg.Done()
gcpMetadata = retrieveGCPMetadata()
}()
wg.Wait()
autoDetected = detectResourceType(awsIdentityDoc, gcpMetadata)
})
return autoDetected
}()
}
// createAWSEC2InstanceMonitoredResource creates a aws_ec2_instance monitored resource
// awsIdentityDoc contains AWS EC2 specific attributes.
func createAWSEC2InstanceMonitoredResource(awsIdentityDoc *awsIdentityDocument) *AWSEC2Instance {
awsInstance := AWSEC2Instance{
AWSAccount: awsIdentityDoc.accountID,
InstanceID: awsIdentityDoc.instanceID,
Region: fmt.Sprintf("aws:%s", awsIdentityDoc.region),
}
return &awsInstance
}
// createGCEInstanceMonitoredResource creates a gce_instance monitored resource
// gcpMetadata contains GCP (GKE or GCE) specific attributes.
func createGCEInstanceMonitoredResource(gcpMetadata *gcpMetadata) *GCEInstance {
gceInstance := GCEInstance{
ProjectID: gcpMetadata.projectID,
InstanceID: gcpMetadata.instanceID,
Zone: gcpMetadata.zone,
}
return &gceInstance
}
// createGKEContainerMonitoredResource creates a gke_container monitored resource
// gcpMetadata contains GCP (GKE or GCE) specific attributes.
func createGKEContainerMonitoredResource(gcpMetadata *gcpMetadata) *GKEContainer {
gkeContainer := GKEContainer{
ProjectID: gcpMetadata.projectID,
InstanceID: gcpMetadata.instanceID,
Zone: gcpMetadata.zone,
ContainerName: gcpMetadata.containerName,
ClusterName: gcpMetadata.clusterName,
NamespaceID: gcpMetadata.namespaceID,
PodID: gcpMetadata.podID,
LoggingMonitoringV2Enabled: gcpMetadata.monitoringV2,
}
return &gkeContainer
}
// detectOnce is used to make sure GCP and AWS metadata detect function executes only once.
var detectOnce sync.Once
// autoDetected is the metadata detected after the first execution of Autodetect function.
var autoDetected Interface
// detectResourceType determines the resource type.
// awsIdentityDoc contains AWS EC2 attributes. nil if it is not AWS EC2 environment
// gcpMetadata contains GCP (GKE or GCE) specific attributes.
func detectResourceType(awsIdentityDoc *awsIdentityDocument, gcpMetadata *gcpMetadata) Interface {
if os.Getenv("KUBERNETES_SERVICE_HOST") != "" &&
gcpMetadata != nil && gcpMetadata.instanceID != "" {
return createGKEContainerMonitoredResource(gcpMetadata)
} else if gcpMetadata != nil && gcpMetadata.instanceID != "" {
return createGCEInstanceMonitoredResource(gcpMetadata)
} else if awsIdentityDoc != nil {
return createAWSEC2InstanceMonitoredResource(awsIdentityDoc)
}
return nil
}