fluent-plugin-google-cloud 0.8.4 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +49 -35
- data/fluent-plugin-google-cloud.gemspec +3 -3
- data/lib/fluent/plugin/common.rb +386 -0
- data/lib/fluent/plugin/filter_analyze_config.rb +344 -0
- data/lib/fluent/plugin/out_google_cloud.rb +81 -360
- data/test/plugin/asserts.rb +77 -0
- data/test/plugin/base_test.rb +71 -186
- data/test/plugin/constants.rb +67 -1
- data/test/plugin/data/google-fluentd-baseline.conf +24 -0
- data/test/plugin/data/google-fluentd-custom.conf +40 -0
- data/test/plugin/test_driver.rb +1 -14
- data/test/plugin/test_filter_analyze_config.rb +200 -0
- data/test/plugin/utils.rb +147 -0
- metadata +19 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f873763395e9eff23e78cf7d645e42277be2b12e022334954b97d5a8b1a96f73
|
4
|
+
data.tar.gz: 26a2146530ef1bce151f6ee4d4fe0625f7dfec6019108cb96f68390c1aef6288
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '051824ee94d4a2de635afe4b28e91475e422767d66407d2040e9d315f6a822d7cdaece7014ab2e6ab7211817b948f51fc385779182258d180e1a5492974f0ac1'
|
7
|
+
data.tar.gz: 8d373bb349402697ab45a3ec11186b0970fadb8ac66ddf25190bf68c4a6ccf0939b627ceb151922d4d8871e361b20ba3fadcfb254e7422c9d0f10b0ade7cb68b
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-google-cloud (0.
|
4
|
+
fluent-plugin-google-cloud (0.9.1)
|
5
5
|
fluentd (= 1.7.4)
|
6
6
|
google-api-client (= 0.30.8)
|
7
7
|
google-cloud-logging (= 1.6.6)
|
8
|
-
google-protobuf (= 3.
|
8
|
+
google-protobuf (= 3.12.2)
|
9
9
|
googleapis-common-protos (= 1.3.9)
|
10
10
|
googleauth (= 0.9.0)
|
11
|
-
grpc (= 1.
|
11
|
+
grpc (= 1.30.2)
|
12
12
|
json (= 2.2.0)
|
13
13
|
opencensus (= 0.5.0)
|
14
14
|
opencensus-stackdriver (= 0.3.2)
|
@@ -18,7 +18,7 @@ GEM
|
|
18
18
|
specs:
|
19
19
|
addressable (2.7.0)
|
20
20
|
public_suffix (>= 2.0.2, < 5.0)
|
21
|
-
ast (2.4.
|
21
|
+
ast (2.4.1)
|
22
22
|
concurrent-ruby (1.1.6)
|
23
23
|
cool.io (1.6.0)
|
24
24
|
coveralls (0.8.23)
|
@@ -29,7 +29,7 @@ GEM
|
|
29
29
|
tins (~> 1.6)
|
30
30
|
crack (0.4.3)
|
31
31
|
safe_yaml (~> 1.0.0)
|
32
|
-
declarative (0.0.
|
32
|
+
declarative (0.0.20)
|
33
33
|
declarative-option (0.1.0)
|
34
34
|
dig_rb (1.0.1)
|
35
35
|
docile (1.3.2)
|
@@ -46,6 +46,12 @@ GEM
|
|
46
46
|
tzinfo (~> 2.0)
|
47
47
|
tzinfo-data (~> 1.0)
|
48
48
|
yajl-ruby (~> 1.0)
|
49
|
+
gapic-common (0.3.1)
|
50
|
+
google-protobuf (~> 3.12, >= 3.12.2)
|
51
|
+
googleapis-common-protos (>= 1.3.9, < 2.0)
|
52
|
+
googleapis-common-protos-types (>= 1.0.4, < 2.0)
|
53
|
+
googleauth (~> 0.9)
|
54
|
+
grpc (~> 1.25)
|
49
55
|
google-api-client (0.30.8)
|
50
56
|
addressable (~> 2.5, >= 2.5.1)
|
51
57
|
googleauth (>= 0.5, < 0.10.0)
|
@@ -57,36 +63,44 @@ GEM
|
|
57
63
|
google-cloud-core (1.5.0)
|
58
64
|
google-cloud-env (~> 1.0)
|
59
65
|
google-cloud-errors (~> 1.0)
|
60
|
-
google-cloud-env (1.3.
|
66
|
+
google-cloud-env (1.3.3)
|
61
67
|
faraday (>= 0.17.3, < 2.0)
|
62
|
-
google-cloud-errors (1.0.
|
68
|
+
google-cloud-errors (1.0.1)
|
63
69
|
google-cloud-logging (1.6.6)
|
64
70
|
concurrent-ruby (~> 1.1)
|
65
71
|
google-cloud-core (~> 1.2)
|
66
72
|
google-gax (~> 1.7)
|
67
73
|
googleapis-common-protos-types (>= 1.0.2)
|
68
74
|
stackdriver-core (~> 1.3)
|
69
|
-
google-cloud-monitoring (0.
|
70
|
-
google-gax (~> 1.
|
71
|
-
googleapis-common-protos
|
72
|
-
|
75
|
+
google-cloud-monitoring (0.38.0)
|
76
|
+
google-gax (~> 1.8)
|
77
|
+
googleapis-common-protos (>= 1.3.9, < 2.0)
|
78
|
+
googleapis-common-protos-types (>= 1.0.4, < 2.0)
|
79
|
+
google-cloud-trace (0.40.0)
|
73
80
|
concurrent-ruby (~> 1.1)
|
74
|
-
google-cloud-core (~> 1.
|
75
|
-
google-
|
81
|
+
google-cloud-core (~> 1.5)
|
82
|
+
google-cloud-trace-v1 (~> 0.0)
|
83
|
+
google-cloud-trace-v2 (~> 0.0)
|
76
84
|
stackdriver-core (~> 1.3)
|
77
|
-
google-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
85
|
+
google-cloud-trace-v1 (0.1.0)
|
86
|
+
gapic-common (~> 0.3)
|
87
|
+
google-cloud-errors (~> 1.0)
|
88
|
+
google-cloud-trace-v2 (0.1.0)
|
89
|
+
gapic-common (~> 0.3)
|
90
|
+
google-cloud-errors (~> 1.0)
|
91
|
+
google-gax (1.8.1)
|
92
|
+
google-protobuf (~> 3.9)
|
93
|
+
googleapis-common-protos (>= 1.3.9, < 2.0)
|
94
|
+
googleauth (~> 0.9)
|
95
|
+
grpc (~> 1.24)
|
82
96
|
rly (~> 0.2.3)
|
83
|
-
google-protobuf (3.
|
97
|
+
google-protobuf (3.12.2)
|
84
98
|
googleapis-common-protos (1.3.9)
|
85
99
|
google-protobuf (~> 3.0)
|
86
100
|
googleapis-common-protos-types (~> 1.0)
|
87
101
|
grpc (~> 1.0)
|
88
|
-
googleapis-common-protos-types (1.0.
|
89
|
-
google-protobuf (~> 3.
|
102
|
+
googleapis-common-protos-types (1.0.5)
|
103
|
+
google-protobuf (~> 3.11)
|
90
104
|
googleauth (0.9.0)
|
91
105
|
faraday (~> 0.12)
|
92
106
|
jwt (>= 1.4, < 3.0)
|
@@ -94,8 +108,8 @@ GEM
|
|
94
108
|
multi_json (~> 1.11)
|
95
109
|
os (>= 0.9, < 2.0)
|
96
110
|
signet (~> 0.7)
|
97
|
-
grpc (1.
|
98
|
-
google-protobuf (~> 3.
|
111
|
+
grpc (1.30.2)
|
112
|
+
google-protobuf (~> 3.12)
|
99
113
|
googleapis-common-protos-types (~> 1.0)
|
100
114
|
hashdiff (1.0.1)
|
101
115
|
http_parser.rb (0.6.0)
|
@@ -108,7 +122,7 @@ GEM
|
|
108
122
|
mocha (1.9.0)
|
109
123
|
metaclass (~> 0.0.1)
|
110
124
|
msgpack (1.3.3)
|
111
|
-
multi_json (1.
|
125
|
+
multi_json (1.15.0)
|
112
126
|
multipart-post (2.1.1)
|
113
127
|
opencensus (0.5.0)
|
114
128
|
opencensus-stackdriver (0.3.2)
|
@@ -116,14 +130,14 @@ GEM
|
|
116
130
|
google-cloud-monitoring (~> 0.32)
|
117
131
|
google-cloud-trace (~> 0.35)
|
118
132
|
opencensus (~> 0.5)
|
119
|
-
os (1.0
|
120
|
-
parser (2.7.
|
121
|
-
ast (~> 2.4.
|
122
|
-
power_assert (1.
|
133
|
+
os (1.1.0)
|
134
|
+
parser (2.7.1.4)
|
135
|
+
ast (~> 2.4.1)
|
136
|
+
power_assert (1.2.0)
|
123
137
|
powerpack (0.1.2)
|
124
138
|
prometheus-client (0.9.0)
|
125
139
|
quantile (~> 0.2.1)
|
126
|
-
public_suffix (4.0.
|
140
|
+
public_suffix (4.0.5)
|
127
141
|
quantile (0.2.1)
|
128
142
|
rainbow (2.2.2)
|
129
143
|
rake
|
@@ -145,7 +159,7 @@ GEM
|
|
145
159
|
serverengine (2.2.1)
|
146
160
|
sigdump (~> 0.2.2)
|
147
161
|
sigdump (0.2.4)
|
148
|
-
signet (0.
|
162
|
+
signet (0.14.0)
|
149
163
|
addressable (~> 2.3)
|
150
164
|
faraday (>= 0.17.3, < 2.0)
|
151
165
|
jwt (>= 1.5, < 3.0)
|
@@ -157,18 +171,18 @@ GEM
|
|
157
171
|
simplecov-html (0.10.2)
|
158
172
|
stackdriver-core (1.4.0)
|
159
173
|
google-cloud-core (~> 1.2)
|
160
|
-
strptime (0.2.
|
174
|
+
strptime (0.2.4)
|
161
175
|
sync (0.5.0)
|
162
176
|
term-ansicolor (1.7.1)
|
163
177
|
tins (~> 1.0)
|
164
178
|
test-unit (3.3.3)
|
165
179
|
power_assert
|
166
180
|
thor (1.0.1)
|
167
|
-
tins (1.
|
181
|
+
tins (1.25.0)
|
168
182
|
sync
|
169
|
-
tzinfo (2.0.
|
183
|
+
tzinfo (2.0.2)
|
170
184
|
concurrent-ruby (~> 1.0)
|
171
|
-
tzinfo-data (1.
|
185
|
+
tzinfo-data (1.2020.1)
|
172
186
|
tzinfo (>= 1.0.0)
|
173
187
|
uber (0.1.0)
|
174
188
|
unicode-display_width (1.7.0)
|
@@ -192,4 +206,4 @@ DEPENDENCIES
|
|
192
206
|
webmock (= 3.6.2)
|
193
207
|
|
194
208
|
BUNDLED WITH
|
195
|
-
2.1.
|
209
|
+
2.1.4
|
@@ -10,7 +10,7 @@ eos
|
|
10
10
|
gem.homepage =
|
11
11
|
'https://github.com/GoogleCloudPlatform/fluent-plugin-google-cloud'
|
12
12
|
gem.license = 'Apache-2.0'
|
13
|
-
gem.version = '0.
|
13
|
+
gem.version = '0.9.1'
|
14
14
|
gem.authors = ['Stackdriver Agents Team']
|
15
15
|
gem.email = ['stackdriver-agents@google.com']
|
16
16
|
gem.required_ruby_version = Gem::Requirement.new('>= 2.2')
|
@@ -24,8 +24,8 @@ eos
|
|
24
24
|
gem.add_runtime_dependency 'googleauth', '0.9.0'
|
25
25
|
gem.add_runtime_dependency 'google-api-client', '0.30.8'
|
26
26
|
gem.add_runtime_dependency 'google-cloud-logging', '1.6.6'
|
27
|
-
gem.add_runtime_dependency 'google-protobuf', '3.
|
28
|
-
gem.add_runtime_dependency 'grpc', '1.
|
27
|
+
gem.add_runtime_dependency 'google-protobuf', '3.12.2'
|
28
|
+
gem.add_runtime_dependency 'grpc', '1.30.2'
|
29
29
|
gem.add_runtime_dependency 'json', '2.2.0'
|
30
30
|
gem.add_runtime_dependency 'opencensus', '0.5.0'
|
31
31
|
gem.add_runtime_dependency 'opencensus-stackdriver', '0.3.2'
|
@@ -0,0 +1,386 @@
|
|
1
|
+
# Copyright 2020 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Common
|
16
|
+
# Constants for service names, resource types and etc.
|
17
|
+
module ServiceConstants
|
18
|
+
APPENGINE_CONSTANTS = {
|
19
|
+
service: 'appengine.googleapis.com',
|
20
|
+
resource_type: 'gae_app',
|
21
|
+
metadata_attributes: %w(gae_backend_name gae_backend_version)
|
22
|
+
}.freeze
|
23
|
+
COMPUTE_CONSTANTS = {
|
24
|
+
service: 'compute.googleapis.com',
|
25
|
+
resource_type: 'gce_instance'
|
26
|
+
}.freeze
|
27
|
+
GKE_CONSTANTS = {
|
28
|
+
service: 'container.googleapis.com',
|
29
|
+
resource_type: 'gke_container',
|
30
|
+
extra_resource_labels: %w(namespace_id pod_id container_name),
|
31
|
+
extra_common_labels: %w(namespace_name pod_name),
|
32
|
+
metadata_attributes: %w(cluster-name cluster-location),
|
33
|
+
stream_severity_map: {
|
34
|
+
'stdout' => 'INFO',
|
35
|
+
'stderr' => 'ERROR'
|
36
|
+
}
|
37
|
+
}.freeze
|
38
|
+
K8S_CONTAINER_CONSTANTS = {
|
39
|
+
resource_type: 'k8s_container'
|
40
|
+
}.freeze
|
41
|
+
K8S_POD_CONSTANTS = {
|
42
|
+
resource_type: 'k8s_pod'
|
43
|
+
}.freeze
|
44
|
+
K8S_NODE_CONSTANTS = {
|
45
|
+
resource_type: 'k8s_node'
|
46
|
+
}.freeze
|
47
|
+
DATAFLOW_CONSTANTS = {
|
48
|
+
service: 'dataflow.googleapis.com',
|
49
|
+
resource_type: 'dataflow_step',
|
50
|
+
extra_resource_labels: %w(region job_name job_id step_id)
|
51
|
+
}.freeze
|
52
|
+
DATAPROC_CONSTANTS = {
|
53
|
+
service: 'cluster.dataproc.googleapis.com',
|
54
|
+
resource_type: 'cloud_dataproc_cluster',
|
55
|
+
metadata_attributes: %w(dataproc-cluster-uuid dataproc-cluster-name)
|
56
|
+
}.freeze
|
57
|
+
EC2_CONSTANTS = {
|
58
|
+
service: 'ec2.amazonaws.com',
|
59
|
+
resource_type: 'aws_ec2_instance'
|
60
|
+
}.freeze
|
61
|
+
ML_CONSTANTS = {
|
62
|
+
service: 'ml.googleapis.com',
|
63
|
+
resource_type: 'ml_job',
|
64
|
+
extra_resource_labels: %w(job_id task_name)
|
65
|
+
}.freeze
|
66
|
+
|
67
|
+
# The map between a subservice name and a resource type.
|
68
|
+
SUBSERVICE_MAP =
|
69
|
+
[APPENGINE_CONSTANTS, GKE_CONSTANTS, DATAFLOW_CONSTANTS,
|
70
|
+
DATAPROC_CONSTANTS, ML_CONSTANTS]
|
71
|
+
.map { |consts| [consts[:service], consts[:resource_type]] }.to_h
|
72
|
+
# Default back to GCE if invalid value is detected.
|
73
|
+
SUBSERVICE_MAP.default = COMPUTE_CONSTANTS[:resource_type]
|
74
|
+
SUBSERVICE_MAP.freeze
|
75
|
+
|
76
|
+
# The map between a resource type and expected subservice attributes.
|
77
|
+
SUBSERVICE_METADATA_ATTRIBUTES =
|
78
|
+
[APPENGINE_CONSTANTS, GKE_CONSTANTS, DATAPROC_CONSTANTS].map do |consts|
|
79
|
+
[consts[:resource_type], consts[:metadata_attributes].to_set]
|
80
|
+
end.to_h.freeze
|
81
|
+
end
|
82
|
+
|
83
|
+
# Name of the the Google cloud logging write scope.
|
84
|
+
LOGGING_SCOPE = 'https://www.googleapis.com/auth/logging.write'.freeze
|
85
|
+
|
86
|
+
# Address of the metadata service.
|
87
|
+
METADATA_SERVICE_ADDR = '169.254.169.254'.freeze
|
88
|
+
|
89
|
+
# "enum" of Platform values
|
90
|
+
module Platform
|
91
|
+
OTHER = 0 # Other/unkown platform
|
92
|
+
GCE = 1 # Google Compute Engine
|
93
|
+
EC2 = 2 # Amazon EC2
|
94
|
+
end
|
95
|
+
|
96
|
+
# Utilities for managing the resource used when writing to the
|
97
|
+
# Google API.
|
98
|
+
class Utils
|
99
|
+
include Common::ServiceConstants
|
100
|
+
|
101
|
+
def initialize(log)
|
102
|
+
@log = log
|
103
|
+
end
|
104
|
+
|
105
|
+
# Determine what platform we are running on by consulting the metadata
|
106
|
+
# service (unless the user has explicitly disabled using that).
|
107
|
+
def detect_platform(use_metadata_service)
|
108
|
+
unless use_metadata_service
|
109
|
+
@log.info 'use_metadata_service is false; not detecting platform'
|
110
|
+
return Platform::OTHER
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
open('http://' + METADATA_SERVICE_ADDR, proxy: false) do |f|
|
115
|
+
if f.meta['metadata-flavor'] == 'Google'
|
116
|
+
@log.info 'Detected GCE platform'
|
117
|
+
return Platform::GCE
|
118
|
+
end
|
119
|
+
if f.meta['server'] == 'EC2ws'
|
120
|
+
@log.info 'Detected EC2 platform'
|
121
|
+
return Platform::EC2
|
122
|
+
end
|
123
|
+
end
|
124
|
+
rescue StandardError => e
|
125
|
+
@log.error 'Failed to access metadata service: ', error: e
|
126
|
+
end
|
127
|
+
|
128
|
+
@log.info 'Unable to determine platform'
|
129
|
+
Platform::OTHER
|
130
|
+
end
|
131
|
+
|
132
|
+
def fetch_gce_metadata(platform, metadata_path)
|
133
|
+
raise "Called fetch_gce_metadata with platform=#{platform}" unless
|
134
|
+
platform == Platform::GCE
|
135
|
+
# See https://cloud.google.com/compute/docs/metadata
|
136
|
+
open('http://' + METADATA_SERVICE_ADDR + '/computeMetadata/v1/' +
|
137
|
+
metadata_path, 'Metadata-Flavor' => 'Google', :proxy => false,
|
138
|
+
&:read)
|
139
|
+
end
|
140
|
+
|
141
|
+
# EC2 Metadata server returns everything in one call. Store it after the
|
142
|
+
# first fetch to avoid making multiple calls.
|
143
|
+
def ec2_metadata(platform)
|
144
|
+
raise "Called ec2_metadata with platform=#{platform}" unless
|
145
|
+
platform == Platform::EC2
|
146
|
+
unless @ec2_metadata
|
147
|
+
# See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
|
148
|
+
open('http://' + METADATA_SERVICE_ADDR +
|
149
|
+
'/latest/dynamic/instance-identity/document', proxy: false) do |f|
|
150
|
+
contents = f.read
|
151
|
+
@ec2_metadata = JSON.parse(contents)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
@ec2_metadata
|
156
|
+
end
|
157
|
+
|
158
|
+
# Check required variables like @project_id, @vm_id, @vm_name and @zone.
|
159
|
+
def check_required_metadata_variables(platform, project_id, zone, vm_id)
|
160
|
+
missing = []
|
161
|
+
missing << 'project_id' unless project_id
|
162
|
+
if platform != Platform::OTHER
|
163
|
+
missing << 'zone' unless zone
|
164
|
+
missing << 'vm_id' unless vm_id
|
165
|
+
end
|
166
|
+
return if missing.empty?
|
167
|
+
raise Fluent::ConfigError,
|
168
|
+
"Unable to obtain metadata parameters: #{missing.join(' ')}"
|
169
|
+
end
|
170
|
+
|
171
|
+
# 1. Return the value if it is explicitly set in the config already.
|
172
|
+
# 2. If not, try to retrieve it by calling metadata server directly.
|
173
|
+
# 3. If still not set, try to obtain it from the credentials.
|
174
|
+
def get_project_id(platform, project_id)
|
175
|
+
project_id ||= CredentialsInfo.project_id
|
176
|
+
project_id ||= fetch_gce_metadata(platform, 'project/project-id') if
|
177
|
+
platform == Platform::GCE
|
178
|
+
project_id
|
179
|
+
end
|
180
|
+
|
181
|
+
# 1. Return the value if it is explicitly set in the config already.
|
182
|
+
# 2. If not, try to retrieve it by calling metadata servers directly.
|
183
|
+
def get_vm_id(platform, vm_id)
|
184
|
+
vm_id ||= fetch_gce_metadata(platform, 'instance/id') if
|
185
|
+
platform == Platform::GCE
|
186
|
+
vm_id ||= ec2_metadata(platform)['instanceId'] if
|
187
|
+
platform == Platform::EC2
|
188
|
+
vm_id
|
189
|
+
rescue StandardError => e
|
190
|
+
@log.error 'Failed to obtain vm_id: ', error: e
|
191
|
+
end
|
192
|
+
|
193
|
+
# 1. Return the value if it is explicitly set in the config already.
|
194
|
+
# 2. If not, try to retrieve it locally.
|
195
|
+
def get_vm_name(vm_name)
|
196
|
+
vm_name ||= Socket.gethostname
|
197
|
+
vm_name
|
198
|
+
rescue StandardError => e
|
199
|
+
@log.error 'Failed to obtain vm name: ', error: e
|
200
|
+
end
|
201
|
+
|
202
|
+
# 1. Return the value if it is explicitly set in the config already.
|
203
|
+
# 2. If not, try to retrieve it locally.
|
204
|
+
def get_location(platform, zone, use_aws_availability_zone)
|
205
|
+
# Response format: "projects/<number>/zones/<zone>"
|
206
|
+
zone ||= fetch_gce_metadata(platform,
|
207
|
+
'instance/zone').rpartition('/')[2] if
|
208
|
+
platform == Platform::GCE
|
209
|
+
aws_location_key = if use_aws_availability_zone
|
210
|
+
'availabilityZone'
|
211
|
+
else
|
212
|
+
'region'
|
213
|
+
end
|
214
|
+
zone ||= 'aws:' + ec2_metadata(platform)[aws_location_key] if
|
215
|
+
platform == Platform::EC2 &&
|
216
|
+
ec2_metadata(platform).key?(aws_location_key)
|
217
|
+
zone
|
218
|
+
rescue StandardError => e
|
219
|
+
@log.error 'Failed to obtain location: ', error: e
|
220
|
+
end
|
221
|
+
|
222
|
+
# Create a monitored resource from type and labels.
|
223
|
+
def create_monitored_resource(type, labels)
|
224
|
+
Google::Apis::LoggingV2::MonitoredResource.new(
|
225
|
+
type: type, labels: labels.to_h)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Retrieve monitored resource via the legacy way.
|
229
|
+
#
|
230
|
+
# Note: This is just a failover plan if we fail to get metadata from
|
231
|
+
# Metadata Agent. Thus it should be equivalent to what Metadata Agent
|
232
|
+
# returns.
|
233
|
+
def determine_agent_level_monitored_resource_via_legacy(
|
234
|
+
platform, subservice_name, detect_subservice, vm_id, zone)
|
235
|
+
resource_type = determine_agent_level_monitored_resource_type(
|
236
|
+
platform, subservice_name, detect_subservice)
|
237
|
+
create_monitored_resource(
|
238
|
+
resource_type,
|
239
|
+
determine_agent_level_monitored_resource_labels(
|
240
|
+
platform, resource_type, vm_id, zone))
|
241
|
+
end
|
242
|
+
|
243
|
+
# Determine agent level monitored resource type.
|
244
|
+
def determine_agent_level_monitored_resource_type(
|
245
|
+
platform, subservice_name, detect_subservice)
|
246
|
+
case platform
|
247
|
+
when Platform::OTHER
|
248
|
+
# Unknown platform will be defaulted to GCE instance.
|
249
|
+
return COMPUTE_CONSTANTS[:resource_type]
|
250
|
+
|
251
|
+
when Platform::EC2
|
252
|
+
return EC2_CONSTANTS[:resource_type]
|
253
|
+
|
254
|
+
when Platform::GCE
|
255
|
+
# Resource types determined by subservice_name config.
|
256
|
+
return SUBSERVICE_MAP[subservice_name] if subservice_name
|
257
|
+
|
258
|
+
# Resource types determined by detect_subservice config.
|
259
|
+
if detect_subservice
|
260
|
+
begin
|
261
|
+
attributes = fetch_gce_metadata(platform,
|
262
|
+
'instance/attributes/').split.to_set
|
263
|
+
SUBSERVICE_METADATA_ATTRIBUTES.each do |resource_type, expected|
|
264
|
+
return resource_type if attributes.superset?(expected)
|
265
|
+
end
|
266
|
+
rescue StandardError => e
|
267
|
+
@log.error 'Failed to detect subservice: ', error: e
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# GCE instance.
|
272
|
+
return COMPUTE_CONSTANTS[:resource_type]
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Determine agent level monitored resource labels based on the resource
|
277
|
+
# type. Each resource type has its own labels that need to be filled in.
|
278
|
+
def determine_agent_level_monitored_resource_labels(
|
279
|
+
platform, type, vm_id, zone)
|
280
|
+
case type
|
281
|
+
# GAE app.
|
282
|
+
when APPENGINE_CONSTANTS[:resource_type]
|
283
|
+
return {
|
284
|
+
'module_id' =>
|
285
|
+
fetch_gce_metadata(platform,
|
286
|
+
'instance/attributes/gae_backend_name'),
|
287
|
+
'version_id' =>
|
288
|
+
fetch_gce_metadata(platform,
|
289
|
+
'instance/attributes/gae_backend_version')
|
290
|
+
}
|
291
|
+
|
292
|
+
# GCE.
|
293
|
+
when COMPUTE_CONSTANTS[:resource_type]
|
294
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
295
|
+
unless vm_id && zone
|
296
|
+
return {
|
297
|
+
'instance_id' => vm_id,
|
298
|
+
'zone' => zone
|
299
|
+
}
|
300
|
+
|
301
|
+
# GKE container.
|
302
|
+
when GKE_CONSTANTS[:resource_type]
|
303
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
304
|
+
unless vm_id && zone
|
305
|
+
return {
|
306
|
+
'instance_id' => vm_id,
|
307
|
+
'zone' => zone,
|
308
|
+
'cluster_name' =>
|
309
|
+
fetch_gce_metadata(platform, 'instance/attributes/cluster-name')
|
310
|
+
}
|
311
|
+
|
312
|
+
# Cloud Dataproc.
|
313
|
+
when DATAPROC_CONSTANTS[:resource_type]
|
314
|
+
return {
|
315
|
+
'cluster_uuid' =>
|
316
|
+
fetch_gce_metadata(platform,
|
317
|
+
'instance/attributes/dataproc-cluster-uuid'),
|
318
|
+
'cluster_name' =>
|
319
|
+
fetch_gce_metadata(platform,
|
320
|
+
'instance/attributes/dataproc-cluster-name'),
|
321
|
+
'region' =>
|
322
|
+
fetch_gce_metadata(platform,
|
323
|
+
'instance/attributes/dataproc-region')
|
324
|
+
}
|
325
|
+
|
326
|
+
# EC2.
|
327
|
+
when EC2_CONSTANTS[:resource_type]
|
328
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
329
|
+
unless vm_id && zone
|
330
|
+
labels = {
|
331
|
+
'instance_id' => vm_id,
|
332
|
+
'region' => zone
|
333
|
+
}
|
334
|
+
labels['aws_account'] = ec2_metadata(platform)['accountId'] if
|
335
|
+
ec2_metadata(platform).key?('accountId')
|
336
|
+
return labels
|
337
|
+
end
|
338
|
+
|
339
|
+
{}
|
340
|
+
rescue StandardError => e
|
341
|
+
if [Platform::GCE, Platform::EC2].include?(platform)
|
342
|
+
@log.error "Failed to set monitored resource labels for #{type}: ",
|
343
|
+
error: e
|
344
|
+
end
|
345
|
+
{}
|
346
|
+
end
|
347
|
+
|
348
|
+
# TODO: This functionality should eventually be available in another
|
349
|
+
# library, but implement it ourselves for now.
|
350
|
+
module CredentialsInfo
|
351
|
+
# Determine the project ID from the credentials, if possible.
|
352
|
+
# Returns the project ID (as a string) on success, or nil on failure.
|
353
|
+
def self.project_id
|
354
|
+
creds = Google::Auth.get_application_default(LOGGING_SCOPE)
|
355
|
+
if creds.respond_to?(:project_id)
|
356
|
+
return creds.project_id if creds.project_id
|
357
|
+
end
|
358
|
+
if creds.issuer
|
359
|
+
id = extract_project_id(creds.issuer)
|
360
|
+
return id unless id.nil?
|
361
|
+
end
|
362
|
+
if creds.client_id
|
363
|
+
id = extract_project_id(creds.client_id)
|
364
|
+
return id unless id.nil?
|
365
|
+
end
|
366
|
+
nil
|
367
|
+
end
|
368
|
+
|
369
|
+
# Extracts the project id (either name or number) from str and returns
|
370
|
+
# it (as a string) on success, or nil on failure.
|
371
|
+
#
|
372
|
+
# Recognizes IAM format (account@project-name.iam.gserviceaccount.com)
|
373
|
+
# as well as the legacy format with a project number at the front of the
|
374
|
+
# string, terminated by a dash (-) which is not part of the ID, i.e.:
|
375
|
+
# <PROJECT_ID>-<OTHER_PARTS>.apps.googleusercontent.com
|
376
|
+
def self.extract_project_id(str)
|
377
|
+
[/^.*@(?<project_id>.+)\.iam\.gserviceaccount\.com/,
|
378
|
+
/^(?<project_id>\d+)-/].each do |exp|
|
379
|
+
match_data = exp.match(str)
|
380
|
+
return match_data['project_id'] unless match_data.nil?
|
381
|
+
end
|
382
|
+
nil
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|