fluent-plugin-google-cloud 0.8.6 → 0.8.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/common.rb +381 -0
- data/lib/fluent/plugin/out_google_cloud.rb +24 -357
- data/test/plugin/base_test.rb +1 -1
- data/test/plugin/constants.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 851c496e93becdfb6a735f9c71aceecfdeccfff14519ce8311bb3dd42c7ed382
|
4
|
+
data.tar.gz: d893b865df5a2b10bac43c65381abe1b95e27333ff77ac45c6cb988c2f446036
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f840e9c06e995be5dd4abd0dcd9d04042c6d78507896fc842ab2b1fb8cb82eac4535fdb6259656cc703e99955e074e64c1ec0292c31d77647cbc95d54e7b919
|
7
|
+
data.tar.gz: c1573f562d3691a83b8b3dd2b8e8a0ed1585edac5f67df6179bc8c62af4a3728ce97b90be8827008718921069806eb6e0d2e81fd5c7f6de4c6603a1c2738774e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-google-cloud (0.8.
|
4
|
+
fluent-plugin-google-cloud (0.8.7)
|
5
5
|
fluentd (= 1.7.4)
|
6
6
|
google-api-client (= 0.30.8)
|
7
7
|
google-cloud-logging (= 1.6.6)
|
@@ -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)
|
@@ -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.8.
|
13
|
+
gem.version = '0.8.7'
|
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')
|
@@ -0,0 +1,381 @@
|
|
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
|
+
# Retrieve monitored resource via the legacy way.
|
223
|
+
#
|
224
|
+
# Note: This is just a failover plan if we fail to get metadata from
|
225
|
+
# Metadata Agent. Thus it should be equivalent to what Metadata Agent
|
226
|
+
# returns.
|
227
|
+
def determine_agent_level_monitored_resource_via_legacy(
|
228
|
+
platform, subservice_name, detect_subservice, vm_id, zone)
|
229
|
+
resource = Google::Apis::LoggingV2::MonitoredResource.new(
|
230
|
+
labels: {})
|
231
|
+
resource.type = determine_agent_level_monitored_resource_type(
|
232
|
+
platform, subservice_name, detect_subservice)
|
233
|
+
resource.labels = determine_agent_level_monitored_resource_labels(
|
234
|
+
platform, resource.type, vm_id, zone)
|
235
|
+
resource
|
236
|
+
end
|
237
|
+
|
238
|
+
# Determine agent level monitored resource type.
|
239
|
+
def determine_agent_level_monitored_resource_type(
|
240
|
+
platform, subservice_name, detect_subservice)
|
241
|
+
case platform
|
242
|
+
when Platform::OTHER
|
243
|
+
# Unknown platform will be defaulted to GCE instance.
|
244
|
+
return COMPUTE_CONSTANTS[:resource_type]
|
245
|
+
|
246
|
+
when Platform::EC2
|
247
|
+
return EC2_CONSTANTS[:resource_type]
|
248
|
+
|
249
|
+
when Platform::GCE
|
250
|
+
# Resource types determined by subservice_name config.
|
251
|
+
return SUBSERVICE_MAP[subservice_name] if subservice_name
|
252
|
+
|
253
|
+
# Resource types determined by detect_subservice config.
|
254
|
+
if detect_subservice
|
255
|
+
begin
|
256
|
+
attributes = fetch_gce_metadata(platform,
|
257
|
+
'instance/attributes/').split.to_set
|
258
|
+
SUBSERVICE_METADATA_ATTRIBUTES.each do |resource_type, expected|
|
259
|
+
return resource_type if attributes.superset?(expected)
|
260
|
+
end
|
261
|
+
rescue StandardError => e
|
262
|
+
@log.error 'Failed to detect subservice: ', error: e
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# GCE instance.
|
267
|
+
return COMPUTE_CONSTANTS[:resource_type]
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Determine agent level monitored resource labels based on the resource
|
272
|
+
# type. Each resource type has its own labels that need to be filled in.
|
273
|
+
def determine_agent_level_monitored_resource_labels(
|
274
|
+
platform, type, vm_id, zone)
|
275
|
+
case type
|
276
|
+
# GAE app.
|
277
|
+
when APPENGINE_CONSTANTS[:resource_type]
|
278
|
+
return {
|
279
|
+
'module_id' =>
|
280
|
+
fetch_gce_metadata(platform,
|
281
|
+
'instance/attributes/gae_backend_name'),
|
282
|
+
'version_id' =>
|
283
|
+
fetch_gce_metadata(platform,
|
284
|
+
'instance/attributes/gae_backend_version')
|
285
|
+
}
|
286
|
+
|
287
|
+
# GCE.
|
288
|
+
when COMPUTE_CONSTANTS[:resource_type]
|
289
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
290
|
+
unless vm_id && zone
|
291
|
+
return {
|
292
|
+
'instance_id' => vm_id,
|
293
|
+
'zone' => zone
|
294
|
+
}
|
295
|
+
|
296
|
+
# GKE container.
|
297
|
+
when GKE_CONSTANTS[:resource_type]
|
298
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
299
|
+
unless vm_id && zone
|
300
|
+
return {
|
301
|
+
'instance_id' => vm_id,
|
302
|
+
'zone' => zone,
|
303
|
+
'cluster_name' =>
|
304
|
+
fetch_gce_metadata(platform, 'instance/attributes/cluster-name')
|
305
|
+
}
|
306
|
+
|
307
|
+
# Cloud Dataproc.
|
308
|
+
when DATAPROC_CONSTANTS[:resource_type]
|
309
|
+
return {
|
310
|
+
'cluster_uuid' =>
|
311
|
+
fetch_gce_metadata(platform,
|
312
|
+
'instance/attributes/dataproc-cluster-uuid'),
|
313
|
+
'cluster_name' =>
|
314
|
+
fetch_gce_metadata(platform,
|
315
|
+
'instance/attributes/dataproc-cluster-name'),
|
316
|
+
'region' =>
|
317
|
+
fetch_gce_metadata(platform,
|
318
|
+
'instance/attributes/dataproc-region')
|
319
|
+
}
|
320
|
+
|
321
|
+
# EC2.
|
322
|
+
when EC2_CONSTANTS[:resource_type]
|
323
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
324
|
+
unless vm_id && zone
|
325
|
+
labels = {
|
326
|
+
'instance_id' => vm_id,
|
327
|
+
'region' => zone
|
328
|
+
}
|
329
|
+
labels['aws_account'] = ec2_metadata(platform)['accountId'] if
|
330
|
+
ec2_metadata(platform).key?('accountId')
|
331
|
+
return labels
|
332
|
+
end
|
333
|
+
|
334
|
+
{}
|
335
|
+
rescue StandardError => e
|
336
|
+
if [Platform::GCE, Platform::EC2].include?(platform)
|
337
|
+
@log.error "Failed to set monitored resource labels for #{type}: ",
|
338
|
+
error: e
|
339
|
+
end
|
340
|
+
{}
|
341
|
+
end
|
342
|
+
|
343
|
+
# TODO: This functionality should eventually be available in another
|
344
|
+
# library, but implement it ourselves for now.
|
345
|
+
module CredentialsInfo
|
346
|
+
# Determine the project ID from the credentials, if possible.
|
347
|
+
# Returns the project ID (as a string) on success, or nil on failure.
|
348
|
+
def self.project_id
|
349
|
+
creds = Google::Auth.get_application_default(LOGGING_SCOPE)
|
350
|
+
if creds.respond_to?(:project_id)
|
351
|
+
return creds.project_id if creds.project_id
|
352
|
+
end
|
353
|
+
if creds.issuer
|
354
|
+
id = extract_project_id(creds.issuer)
|
355
|
+
return id unless id.nil?
|
356
|
+
end
|
357
|
+
if creds.client_id
|
358
|
+
id = extract_project_id(creds.client_id)
|
359
|
+
return id unless id.nil?
|
360
|
+
end
|
361
|
+
nil
|
362
|
+
end
|
363
|
+
|
364
|
+
# Extracts the project id (either name or number) from str and returns
|
365
|
+
# it (as a string) on success, or nil on failure.
|
366
|
+
#
|
367
|
+
# Recognizes IAM format (account@project-name.iam.gserviceaccount.com)
|
368
|
+
# as well as the legacy format with a project number at the front of the
|
369
|
+
# string, terminated by a dash (-) which is not part of the ID, i.e.:
|
370
|
+
# <PROJECT_ID>-<OTHER_PARTS>.apps.googleusercontent.com
|
371
|
+
def self.extract_project_id(str)
|
372
|
+
[/^.*@(?<project_id>.+)\.iam\.gserviceaccount\.com/,
|
373
|
+
/^(?<project_id>\d+)-/].each do |exp|
|
374
|
+
match_data = exp.match(str)
|
375
|
+
return match_data['project_id'] unless match_data.nil?
|
376
|
+
end
|
377
|
+
nil
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
@@ -28,6 +28,7 @@ require 'google/logging/v2/logging_services_pb'
|
|
28
28
|
require 'google/logging/v2/log_entry_pb'
|
29
29
|
require 'googleauth'
|
30
30
|
|
31
|
+
require_relative 'common'
|
31
32
|
require_relative 'monitoring'
|
32
33
|
require_relative 'statusz'
|
33
34
|
|
@@ -90,73 +91,6 @@ end
|
|
90
91
|
module Fluent
|
91
92
|
# fluentd output plugin for the Stackdriver Logging API
|
92
93
|
class GoogleCloudOutput < BufferedOutput
|
93
|
-
# Constants for service names, resource types and etc.
|
94
|
-
module ServiceConstants
|
95
|
-
APPENGINE_CONSTANTS = {
|
96
|
-
service: 'appengine.googleapis.com',
|
97
|
-
resource_type: 'gae_app',
|
98
|
-
metadata_attributes: %w(gae_backend_name gae_backend_version)
|
99
|
-
}.freeze
|
100
|
-
COMPUTE_CONSTANTS = {
|
101
|
-
service: 'compute.googleapis.com',
|
102
|
-
resource_type: 'gce_instance'
|
103
|
-
}.freeze
|
104
|
-
GKE_CONSTANTS = {
|
105
|
-
service: 'container.googleapis.com',
|
106
|
-
resource_type: 'gke_container',
|
107
|
-
extra_resource_labels: %w(namespace_id pod_id container_name),
|
108
|
-
extra_common_labels: %w(namespace_name pod_name),
|
109
|
-
metadata_attributes: %w(cluster-name cluster-location),
|
110
|
-
stream_severity_map: {
|
111
|
-
'stdout' => 'INFO',
|
112
|
-
'stderr' => 'ERROR'
|
113
|
-
}
|
114
|
-
}.freeze
|
115
|
-
K8S_CONTAINER_CONSTANTS = {
|
116
|
-
resource_type: 'k8s_container'
|
117
|
-
}.freeze
|
118
|
-
K8S_POD_CONSTANTS = {
|
119
|
-
resource_type: 'k8s_pod'
|
120
|
-
}.freeze
|
121
|
-
K8S_NODE_CONSTANTS = {
|
122
|
-
resource_type: 'k8s_node'
|
123
|
-
}.freeze
|
124
|
-
DATAFLOW_CONSTANTS = {
|
125
|
-
service: 'dataflow.googleapis.com',
|
126
|
-
resource_type: 'dataflow_step',
|
127
|
-
extra_resource_labels: %w(region job_name job_id step_id)
|
128
|
-
}.freeze
|
129
|
-
DATAPROC_CONSTANTS = {
|
130
|
-
service: 'cluster.dataproc.googleapis.com',
|
131
|
-
resource_type: 'cloud_dataproc_cluster',
|
132
|
-
metadata_attributes: %w(dataproc-cluster-uuid dataproc-cluster-name)
|
133
|
-
}.freeze
|
134
|
-
EC2_CONSTANTS = {
|
135
|
-
service: 'ec2.amazonaws.com',
|
136
|
-
resource_type: 'aws_ec2_instance'
|
137
|
-
}.freeze
|
138
|
-
ML_CONSTANTS = {
|
139
|
-
service: 'ml.googleapis.com',
|
140
|
-
resource_type: 'ml_job',
|
141
|
-
extra_resource_labels: %w(job_id task_name)
|
142
|
-
}.freeze
|
143
|
-
|
144
|
-
# The map between a subservice name and a resource type.
|
145
|
-
SUBSERVICE_MAP =
|
146
|
-
[APPENGINE_CONSTANTS, GKE_CONSTANTS, DATAFLOW_CONSTANTS,
|
147
|
-
DATAPROC_CONSTANTS, ML_CONSTANTS]
|
148
|
-
.map { |consts| [consts[:service], consts[:resource_type]] }.to_h
|
149
|
-
# Default back to GCE if invalid value is detected.
|
150
|
-
SUBSERVICE_MAP.default = COMPUTE_CONSTANTS[:resource_type]
|
151
|
-
SUBSERVICE_MAP.freeze
|
152
|
-
|
153
|
-
# The map between a resource type and expected subservice attributes.
|
154
|
-
SUBSERVICE_METADATA_ATTRIBUTES =
|
155
|
-
[APPENGINE_CONSTANTS, GKE_CONSTANTS, DATAPROC_CONSTANTS].map do |consts|
|
156
|
-
[consts[:resource_type], consts[:metadata_attributes].to_set]
|
157
|
-
end.to_h.freeze
|
158
|
-
end
|
159
|
-
|
160
94
|
# Constants for configuration.
|
161
95
|
module ConfigConstants
|
162
96
|
# Default values for JSON payload keys to set the "httpRequest",
|
@@ -247,7 +181,7 @@ module Fluent
|
|
247
181
|
.freeze
|
248
182
|
end
|
249
183
|
|
250
|
-
include
|
184
|
+
include Common::ServiceConstants
|
251
185
|
include self::ConfigConstants
|
252
186
|
include self::InternalConstants
|
253
187
|
|
@@ -278,12 +212,6 @@ module Fluent
|
|
278
212
|
end
|
279
213
|
end.freeze
|
280
214
|
|
281
|
-
# Name of the the Google cloud logging write scope.
|
282
|
-
LOGGING_SCOPE = 'https://www.googleapis.com/auth/logging.write'.freeze
|
283
|
-
|
284
|
-
# Address of the metadata service.
|
285
|
-
METADATA_SERVICE_ADDR = '169.254.169.254'.freeze
|
286
|
-
|
287
215
|
# Disable this warning to conform to fluentd config_param conventions.
|
288
216
|
# rubocop:disable Style/HashSyntax
|
289
217
|
|
@@ -539,7 +467,9 @@ module Fluent
|
|
539
467
|
|
540
468
|
set_regexp_patterns
|
541
469
|
|
542
|
-
@
|
470
|
+
@utils = Common::Utils.new(@log)
|
471
|
+
|
472
|
+
@platform = @utils.detect_platform(@use_metadata_service)
|
543
473
|
|
544
474
|
# Treat an empty setting of the credentials file path environment variable
|
545
475
|
# as unset. This way the googleauth lib could fetch the credentials
|
@@ -548,12 +478,20 @@ module Fluent
|
|
548
478
|
ENV[CREDENTIALS_PATH_ENV_VAR] == ''
|
549
479
|
|
550
480
|
# Set required variables: @project_id, @vm_id, @vm_name and @zone.
|
551
|
-
|
481
|
+
@project_id = @utils.get_project_id(@platform, @project_id)
|
482
|
+
@vm_id = @utils.get_vm_id(@platform, @vm_id)
|
483
|
+
@vm_name = @utils.get_vm_name(@vm_name)
|
484
|
+
@zone = @utils.get_location(@platform, @zone, @use_aws_availability_zone)
|
485
|
+
|
486
|
+
# All metadata parameters must now be set.
|
487
|
+
@utils.check_required_metadata_variables(
|
488
|
+
@platform, @project_id, @zone, @vm_id)
|
552
489
|
|
553
490
|
# Retrieve monitored resource.
|
554
491
|
# Fail over to retrieve monitored resource via the legacy path if we fail
|
555
492
|
# to get it from Metadata Agent.
|
556
|
-
@resource ||= determine_agent_level_monitored_resource_via_legacy
|
493
|
+
@resource ||= @utils.determine_agent_level_monitored_resource_via_legacy(
|
494
|
+
@platform, @subservice_name, @detect_subservice, @vm_id, @zone)
|
557
495
|
|
558
496
|
# If monitoring is enabled, register metrics in the default registry
|
559
497
|
# and store metric objects for future use.
|
@@ -611,7 +549,7 @@ module Fluent
|
|
611
549
|
|
612
550
|
# Determine the common labels that should be added to all log entries
|
613
551
|
# processed by this logging agent.
|
614
|
-
@common_labels = determine_agent_level_common_labels
|
552
|
+
@common_labels = determine_agent_level_common_labels(@resource)
|
615
553
|
|
616
554
|
# The resource and labels are now set up; ensure they can't be modified
|
617
555
|
# without first duping them.
|
@@ -627,7 +565,7 @@ module Fluent
|
|
627
565
|
@write_request = method(:write_request_via_rest)
|
628
566
|
end
|
629
567
|
|
630
|
-
if [Platform::GCE, Platform::EC2].include?(@platform)
|
568
|
+
if [Common::Platform::GCE, Common::Platform::EC2].include?(@platform)
|
631
569
|
# Log an informational message containing the Logs viewer URL
|
632
570
|
@log.info 'Logs viewer address: https://console.cloud.google.com/logs/',
|
633
571
|
"viewer?project=#{@project_id}&resource=#{@resource.type}/",
|
@@ -1094,66 +1032,6 @@ module Fluent
|
|
1094
1032
|
nil
|
1095
1033
|
end
|
1096
1034
|
|
1097
|
-
# "enum" of Platform values
|
1098
|
-
module Platform
|
1099
|
-
OTHER = 0 # Other/unkown platform
|
1100
|
-
GCE = 1 # Google Compute Engine
|
1101
|
-
EC2 = 2 # Amazon EC2
|
1102
|
-
end
|
1103
|
-
|
1104
|
-
# Determine what platform we are running on by consulting the metadata
|
1105
|
-
# service (unless the user has explicitly disabled using that).
|
1106
|
-
def detect_platform
|
1107
|
-
unless @use_metadata_service
|
1108
|
-
@log.info 'use_metadata_service is false; not detecting platform'
|
1109
|
-
return Platform::OTHER
|
1110
|
-
end
|
1111
|
-
|
1112
|
-
begin
|
1113
|
-
open('http://' + METADATA_SERVICE_ADDR, proxy: false) do |f|
|
1114
|
-
if f.meta['metadata-flavor'] == 'Google'
|
1115
|
-
@log.info 'Detected GCE platform'
|
1116
|
-
return Platform::GCE
|
1117
|
-
end
|
1118
|
-
if f.meta['server'] == 'EC2ws'
|
1119
|
-
@log.info 'Detected EC2 platform'
|
1120
|
-
return Platform::EC2
|
1121
|
-
end
|
1122
|
-
end
|
1123
|
-
rescue StandardError => e
|
1124
|
-
@log.error 'Failed to access metadata service: ', error: e
|
1125
|
-
end
|
1126
|
-
|
1127
|
-
@log.info 'Unable to determine platform'
|
1128
|
-
Platform::OTHER
|
1129
|
-
end
|
1130
|
-
|
1131
|
-
def fetch_gce_metadata(metadata_path)
|
1132
|
-
raise "Called fetch_gce_metadata with platform=#{@platform}" unless
|
1133
|
-
@platform == Platform::GCE
|
1134
|
-
# See https://cloud.google.com/compute/docs/metadata
|
1135
|
-
open('http://' + METADATA_SERVICE_ADDR + '/computeMetadata/v1/' +
|
1136
|
-
metadata_path, 'Metadata-Flavor' => 'Google', :proxy => false,
|
1137
|
-
&:read)
|
1138
|
-
end
|
1139
|
-
|
1140
|
-
# EC2 Metadata server returns everything in one call. Store it after the
|
1141
|
-
# first fetch to avoid making multiple calls.
|
1142
|
-
def ec2_metadata
|
1143
|
-
raise "Called ec2_metadata with platform=#{@platform}" unless
|
1144
|
-
@platform == Platform::EC2
|
1145
|
-
unless @ec2_metadata
|
1146
|
-
# See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
|
1147
|
-
open('http://' + METADATA_SERVICE_ADDR +
|
1148
|
-
'/latest/dynamic/instance-identity/document', proxy: false) do |f|
|
1149
|
-
contents = f.read
|
1150
|
-
@ec2_metadata = JSON.parse(contents)
|
1151
|
-
end
|
1152
|
-
end
|
1153
|
-
|
1154
|
-
@ec2_metadata
|
1155
|
-
end
|
1156
|
-
|
1157
1035
|
# Set regexp patterns to parse tags and logs.
|
1158
1036
|
def set_regexp_patterns
|
1159
1037
|
@compiled_kubernetes_tag_regexp = Regexp.new(@kubernetes_tag_regexp) if
|
@@ -1163,187 +1041,14 @@ module Fluent
|
|
1163
1041
|
/^\s*(?<seconds>\d+)(?<decimal>\.\d+)?\s*s\s*$/
|
1164
1042
|
end
|
1165
1043
|
|
1166
|
-
# Set required variables like @project_id, @vm_id, @vm_name and @zone.
|
1167
|
-
def set_required_metadata_variables
|
1168
|
-
set_project_id
|
1169
|
-
set_vm_id
|
1170
|
-
set_vm_name
|
1171
|
-
set_location
|
1172
|
-
|
1173
|
-
# All metadata parameters must now be set.
|
1174
|
-
missing = []
|
1175
|
-
missing << 'project_id' unless @project_id
|
1176
|
-
if @platform != Platform::OTHER
|
1177
|
-
missing << 'zone' unless @zone
|
1178
|
-
missing << 'vm_id' unless @vm_id
|
1179
|
-
end
|
1180
|
-
return if missing.empty?
|
1181
|
-
raise Fluent::ConfigError,
|
1182
|
-
"Unable to obtain metadata parameters: #{missing.join(' ')}"
|
1183
|
-
end
|
1184
|
-
|
1185
|
-
# 1. Return the value if it is explicitly set in the config already.
|
1186
|
-
# 2. If not, try to retrieve it by calling metadata server directly.
|
1187
|
-
# 3. If still not set, try to obtain it from the credentials.
|
1188
|
-
def set_project_id
|
1189
|
-
@project_id ||= CredentialsInfo.project_id
|
1190
|
-
@project_id ||= fetch_gce_metadata('project/project-id') if
|
1191
|
-
@platform == Platform::GCE
|
1192
|
-
end
|
1193
|
-
|
1194
|
-
# 1. Return the value if it is explicitly set in the config already.
|
1195
|
-
# 2. If not, try to retrieve it by calling metadata servers directly.
|
1196
|
-
def set_vm_id
|
1197
|
-
@vm_id ||= fetch_gce_metadata('instance/id') if @platform == Platform::GCE
|
1198
|
-
@vm_id ||= ec2_metadata['instanceId'] if @platform == Platform::EC2
|
1199
|
-
rescue StandardError => e
|
1200
|
-
@log.error 'Failed to obtain vm_id: ', error: e
|
1201
|
-
end
|
1202
|
-
|
1203
|
-
# 1. Return the value if it is explicitly set in the config already.
|
1204
|
-
# 2. If not, try to retrieve it locally.
|
1205
|
-
def set_vm_name
|
1206
|
-
@vm_name ||= Socket.gethostname
|
1207
|
-
rescue StandardError => e
|
1208
|
-
@log.error 'Failed to obtain vm name: ', error: e
|
1209
|
-
end
|
1210
|
-
|
1211
|
-
# 1. Return the value if it is explicitly set in the config already.
|
1212
|
-
# 2. If not, try to retrieve it locally.
|
1213
|
-
def set_location
|
1214
|
-
# Response format: "projects/<number>/zones/<zone>"
|
1215
|
-
@zone ||= fetch_gce_metadata('instance/zone').rpartition('/')[2] if
|
1216
|
-
@platform == Platform::GCE
|
1217
|
-
aws_location_key = if @use_aws_availability_zone
|
1218
|
-
'availabilityZone'
|
1219
|
-
else
|
1220
|
-
'region'
|
1221
|
-
end
|
1222
|
-
@zone ||= 'aws:' + ec2_metadata[aws_location_key] if
|
1223
|
-
@platform == Platform::EC2 && ec2_metadata.key?(aws_location_key)
|
1224
|
-
rescue StandardError => e
|
1225
|
-
@log.error 'Failed to obtain location: ', error: e
|
1226
|
-
end
|
1227
|
-
|
1228
|
-
# Retrieve monitored resource via the legacy way.
|
1229
|
-
#
|
1230
|
-
# Note: This is just a failover plan if we fail to get metadata from
|
1231
|
-
# Metadata Agent. Thus it should be equivalent to what Metadata Agent
|
1232
|
-
# returns.
|
1233
|
-
def determine_agent_level_monitored_resource_via_legacy
|
1234
|
-
resource = Google::Apis::LoggingV2::MonitoredResource.new(
|
1235
|
-
labels: {})
|
1236
|
-
resource.type = determine_agent_level_monitored_resource_type
|
1237
|
-
resource.labels = determine_agent_level_monitored_resource_labels(
|
1238
|
-
resource.type)
|
1239
|
-
resource
|
1240
|
-
end
|
1241
|
-
|
1242
|
-
# Determine agent level monitored resource type.
|
1243
|
-
def determine_agent_level_monitored_resource_type
|
1244
|
-
case @platform
|
1245
|
-
when Platform::OTHER
|
1246
|
-
# Unknown platform will be defaulted to GCE instance.
|
1247
|
-
return COMPUTE_CONSTANTS[:resource_type]
|
1248
|
-
|
1249
|
-
when Platform::EC2
|
1250
|
-
return EC2_CONSTANTS[:resource_type]
|
1251
|
-
|
1252
|
-
when Platform::GCE
|
1253
|
-
# Resource types determined by @subservice_name config.
|
1254
|
-
return SUBSERVICE_MAP[@subservice_name] if @subservice_name
|
1255
|
-
|
1256
|
-
# Resource types determined by @detect_subservice config.
|
1257
|
-
if @detect_subservice
|
1258
|
-
begin
|
1259
|
-
attributes = fetch_gce_metadata('instance/attributes/').split.to_set
|
1260
|
-
SUBSERVICE_METADATA_ATTRIBUTES.each do |resource_type, expected|
|
1261
|
-
return resource_type if attributes.superset?(expected)
|
1262
|
-
end
|
1263
|
-
rescue StandardError => e
|
1264
|
-
@log.error 'Failed to detect subservice: ', error: e
|
1265
|
-
end
|
1266
|
-
end
|
1267
|
-
|
1268
|
-
# GCE instance.
|
1269
|
-
return COMPUTE_CONSTANTS[:resource_type]
|
1270
|
-
end
|
1271
|
-
end
|
1272
|
-
|
1273
|
-
# Determine agent level monitored resource labels based on the resource
|
1274
|
-
# type. Each resource type has its own labels that need to be filled in.
|
1275
|
-
def determine_agent_level_monitored_resource_labels(type)
|
1276
|
-
case type
|
1277
|
-
# GAE app.
|
1278
|
-
when APPENGINE_CONSTANTS[:resource_type]
|
1279
|
-
return {
|
1280
|
-
'module_id' =>
|
1281
|
-
fetch_gce_metadata('instance/attributes/gae_backend_name'),
|
1282
|
-
'version_id' =>
|
1283
|
-
fetch_gce_metadata('instance/attributes/gae_backend_version')
|
1284
|
-
}
|
1285
|
-
|
1286
|
-
# GCE.
|
1287
|
-
when COMPUTE_CONSTANTS[:resource_type]
|
1288
|
-
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
1289
|
-
unless @vm_id && @zone
|
1290
|
-
return {
|
1291
|
-
'instance_id' => @vm_id,
|
1292
|
-
'zone' => @zone
|
1293
|
-
}
|
1294
|
-
|
1295
|
-
# GKE container.
|
1296
|
-
when GKE_CONSTANTS[:resource_type]
|
1297
|
-
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
1298
|
-
unless @vm_id && @zone
|
1299
|
-
return {
|
1300
|
-
'instance_id' => @vm_id,
|
1301
|
-
'zone' => @zone,
|
1302
|
-
'cluster_name' =>
|
1303
|
-
fetch_gce_metadata('instance/attributes/cluster-name')
|
1304
|
-
}
|
1305
|
-
|
1306
|
-
# Cloud Dataproc.
|
1307
|
-
when DATAPROC_CONSTANTS[:resource_type]
|
1308
|
-
return {
|
1309
|
-
'cluster_uuid' =>
|
1310
|
-
fetch_gce_metadata('instance/attributes/dataproc-cluster-uuid'),
|
1311
|
-
'cluster_name' =>
|
1312
|
-
fetch_gce_metadata('instance/attributes/dataproc-cluster-name'),
|
1313
|
-
'region' =>
|
1314
|
-
fetch_gce_metadata('instance/attributes/dataproc-region')
|
1315
|
-
}
|
1316
|
-
|
1317
|
-
# EC2.
|
1318
|
-
when EC2_CONSTANTS[:resource_type]
|
1319
|
-
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
1320
|
-
unless @vm_id && @zone
|
1321
|
-
labels = {
|
1322
|
-
'instance_id' => @vm_id,
|
1323
|
-
'region' => @zone
|
1324
|
-
}
|
1325
|
-
labels['aws_account'] = ec2_metadata['accountId'] if
|
1326
|
-
ec2_metadata.key?('accountId')
|
1327
|
-
return labels
|
1328
|
-
end
|
1329
|
-
|
1330
|
-
{}
|
1331
|
-
rescue StandardError => e
|
1332
|
-
if [Platform::GCE, Platform::EC2].include?(@platform)
|
1333
|
-
@log.error "Failed to set monitored resource labels for #{type}: ",
|
1334
|
-
error: e
|
1335
|
-
end
|
1336
|
-
{}
|
1337
|
-
end
|
1338
|
-
|
1339
1044
|
# Determine the common labels that should be added to all log entries
|
1340
1045
|
# processed by this logging agent.
|
1341
|
-
def determine_agent_level_common_labels
|
1046
|
+
def determine_agent_level_common_labels(resource)
|
1342
1047
|
labels = {}
|
1343
1048
|
# User can specify labels via config. We want to capture those as well.
|
1344
1049
|
labels.merge!(@labels) if @labels
|
1345
1050
|
|
1346
|
-
case
|
1051
|
+
case resource.type
|
1347
1052
|
# GAE, Cloud Dataflow, Cloud Dataproc and Cloud ML.
|
1348
1053
|
when APPENGINE_CONSTANTS[:resource_type],
|
1349
1054
|
DATAFLOW_CONSTANTS[:resource_type],
|
@@ -1548,44 +1253,6 @@ module Fluent
|
|
1548
1253
|
[resource, common_labels]
|
1549
1254
|
end
|
1550
1255
|
|
1551
|
-
# TODO: This functionality should eventually be available in another
|
1552
|
-
# library, but implement it ourselves for now.
|
1553
|
-
module CredentialsInfo
|
1554
|
-
# Determine the project ID from the credentials, if possible.
|
1555
|
-
# Returns the project ID (as a string) on success, or nil on failure.
|
1556
|
-
def self.project_id
|
1557
|
-
creds = Google::Auth.get_application_default(LOGGING_SCOPE)
|
1558
|
-
if creds.respond_to?(:project_id)
|
1559
|
-
return creds.project_id if creds.project_id
|
1560
|
-
end
|
1561
|
-
if creds.issuer
|
1562
|
-
id = extract_project_id(creds.issuer)
|
1563
|
-
return id unless id.nil?
|
1564
|
-
end
|
1565
|
-
if creds.client_id
|
1566
|
-
id = extract_project_id(creds.client_id)
|
1567
|
-
return id unless id.nil?
|
1568
|
-
end
|
1569
|
-
nil
|
1570
|
-
end
|
1571
|
-
|
1572
|
-
# Extracts the project id (either name or number) from str and returns
|
1573
|
-
# it (as a string) on success, or nil on failure.
|
1574
|
-
#
|
1575
|
-
# Recognizes IAM format (account@project-name.iam.gserviceaccount.com)
|
1576
|
-
# as well as the legacy format with a project number at the front of the
|
1577
|
-
# string, terminated by a dash (-) which is not part of the ID, i.e.:
|
1578
|
-
# <PROJECT_ID>-<OTHER_PARTS>.apps.googleusercontent.com
|
1579
|
-
def self.extract_project_id(str)
|
1580
|
-
[/^.*@(?<project_id>.+)\.iam\.gserviceaccount\.com/,
|
1581
|
-
/^(?<project_id>\d+)-/].each do |exp|
|
1582
|
-
match_data = exp.match(str)
|
1583
|
-
return match_data['project_id'] unless match_data.nil?
|
1584
|
-
end
|
1585
|
-
nil
|
1586
|
-
end
|
1587
|
-
end
|
1588
|
-
|
1589
1256
|
def time_or_nil(ts_secs, ts_nanos)
|
1590
1257
|
Time.at((Integer ts_secs), (Integer ts_nanos) / 1_000.0)
|
1591
1258
|
rescue ArgumentError, TypeError
|
@@ -2081,7 +1748,7 @@ module Fluent
|
|
2081
1748
|
Google::Apis::ClientOptions.default.application_version = PLUGIN_VERSION
|
2082
1749
|
@client = Google::Apis::LoggingV2::LoggingService.new
|
2083
1750
|
@client.authorization = Google::Auth.get_application_default(
|
2084
|
-
LOGGING_SCOPE)
|
1751
|
+
Common::LOGGING_SCOPE)
|
2085
1752
|
end
|
2086
1753
|
end
|
2087
1754
|
|
@@ -2310,10 +1977,10 @@ module Fluent
|
|
2310
1977
|
@k8s_cluster_location = nil if @k8s_cluster_location == ''
|
2311
1978
|
|
2312
1979
|
begin
|
2313
|
-
@k8s_cluster_name ||= fetch_gce_metadata(
|
2314
|
-
'instance/attributes/cluster-name')
|
2315
|
-
@k8s_cluster_location ||= fetch_gce_metadata(
|
2316
|
-
'instance/attributes/cluster-location')
|
1980
|
+
@k8s_cluster_name ||= @utils.fetch_gce_metadata(
|
1981
|
+
@platform, 'instance/attributes/cluster-name')
|
1982
|
+
@k8s_cluster_location ||= @utils.fetch_gce_metadata(
|
1983
|
+
@platform, 'instance/attributes/cluster-location')
|
2317
1984
|
rescue StandardError => e
|
2318
1985
|
@log.error 'Failed to retrieve k8s cluster name and location.', \
|
2319
1986
|
error: e
|
data/test/plugin/base_test.rb
CHANGED
@@ -107,7 +107,7 @@ module BaseTest
|
|
107
107
|
|
108
108
|
def test_configure_metadata_missing_parts_on_other_platforms
|
109
109
|
setup_no_metadata_service_stubs
|
110
|
-
|
110
|
+
Common::Utils::CredentialsInfo.stubs(:project_id).returns(nil)
|
111
111
|
[[CONFIG_MISSING_METADATA_PROJECT_ID, ['project_id'], false],
|
112
112
|
[CONFIG_MISSING_METADATA_ZONE, [], true],
|
113
113
|
[CONFIG_MISSING_METADATA_VM_ID, [], true],
|
data/test/plugin/constants.rb
CHANGED
@@ -45,7 +45,7 @@ end
|
|
45
45
|
|
46
46
|
# Constants used by unit tests for Google Cloud Logging plugin.
|
47
47
|
module Constants
|
48
|
-
include
|
48
|
+
include Common::ServiceConstants
|
49
49
|
include Fluent::GoogleCloudOutput::ConfigConstants
|
50
50
|
include Fluent::GoogleCloudOutput::InternalConstants
|
51
51
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-google-cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stackdriver Agents Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -266,6 +266,7 @@ files:
|
|
266
266
|
- README.rdoc
|
267
267
|
- Rakefile
|
268
268
|
- fluent-plugin-google-cloud.gemspec
|
269
|
+
- lib/fluent/plugin/common.rb
|
269
270
|
- lib/fluent/plugin/filter_add_insert_ids.rb
|
270
271
|
- lib/fluent/plugin/filter_analyze_config.rb
|
271
272
|
- lib/fluent/plugin/in_object_space_dump.rb
|