fluent-plugin-google-cloud 0.6.10 → 0.6.11.pre.memory.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 +6 -6
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/out_google_cloud.rb +136 -75
- data/test/plugin/base_test.rb +37 -22
- data/test/plugin/constants.rb +1 -1
- data/test/plugin/test_out_google_cloud.rb +39 -21
- data/test/plugin/test_out_google_cloud_grpc.rb +68 -109
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fadfeb3397203502f2708012a6019ca93fbf4b28
|
4
|
+
data.tar.gz: d2ebfbc912f30cd1caa3120fe1d282570e98da6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5884686ae0eae5dad3f533d5399b171029bc03352b251c1690c20425071c141eddb34449bebcb8fa486d5fd6c6752ffe9dd207ec47889f7eed812781d01c9d12
|
7
|
+
data.tar.gz: feffa60a8bf9b93d83b9ec8762e12f74e6c2934fe57a4d10d219410bf8618ce97bc5c14a2deae8e20dbb5a1f0697f1bfec0f167b7cb9b1a2bbf61b2a916272a4
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-google-cloud (0.6.
|
4
|
+
fluent-plugin-google-cloud (0.6.11.pre.memory.1)
|
5
5
|
fluentd (~> 0.10)
|
6
6
|
google-api-client (~> 0.14)
|
7
7
|
google-cloud-logging (~> 1.2, >= 1.2.3)
|
@@ -16,14 +16,14 @@ GEM
|
|
16
16
|
addressable (2.5.2)
|
17
17
|
public_suffix (>= 2.0.2, < 4.0)
|
18
18
|
ast (2.3.0)
|
19
|
-
cool.io (1.5.
|
19
|
+
cool.io (1.5.3)
|
20
20
|
crack (0.4.3)
|
21
21
|
safe_yaml (~> 1.0.0)
|
22
22
|
declarative (0.0.10)
|
23
23
|
declarative-option (0.1.0)
|
24
24
|
faraday (0.13.1)
|
25
25
|
multipart-post (>= 1.2, < 3)
|
26
|
-
fluentd (0.14.
|
26
|
+
fluentd (0.14.25)
|
27
27
|
cool.io (>= 1.4.5, < 2.0.0)
|
28
28
|
http_parser.rb (>= 0.5.1, < 0.7.0)
|
29
29
|
msgpack (>= 0.7.0, < 2.0.0)
|
@@ -34,7 +34,7 @@ GEM
|
|
34
34
|
tzinfo (~> 1.0)
|
35
35
|
tzinfo-data (~> 1.0)
|
36
36
|
yajl-ruby (~> 1.0)
|
37
|
-
google-api-client (0.17.
|
37
|
+
google-api-client (0.17.4)
|
38
38
|
addressable (~> 2.5, >= 2.5.1)
|
39
39
|
googleauth (>= 0.5, < 0.7.0)
|
40
40
|
httpclient (>= 2.8.1, < 3.0)
|
@@ -45,11 +45,11 @@ GEM
|
|
45
45
|
google-cloud-env (~> 1.0)
|
46
46
|
google-cloud-env (1.0.1)
|
47
47
|
faraday (~> 0.11)
|
48
|
-
google-cloud-logging (1.3.
|
48
|
+
google-cloud-logging (1.3.2)
|
49
49
|
google-cloud-core (~> 1.1)
|
50
50
|
google-gax (~> 0.10.1)
|
51
51
|
stackdriver-core (~> 1.2)
|
52
|
-
google-gax (0.10.
|
52
|
+
google-gax (0.10.2)
|
53
53
|
google-protobuf (~> 3.2)
|
54
54
|
googleapis-common-protos (>= 1.3.5, < 2.0)
|
55
55
|
googleauth (~> 0.6.2)
|
@@ -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.6.
|
13
|
+
gem.version = '0.6.11.pre.memory.1'
|
14
14
|
gem.authors = ['Todd Derr', 'Alex Robinson']
|
15
15
|
gem.email = ['salty@google.com']
|
16
16
|
gem.required_ruby_version = Gem::Requirement.new('>= 2.0')
|
@@ -20,6 +20,8 @@ require 'time'
|
|
20
20
|
require 'yaml'
|
21
21
|
require 'google/apis'
|
22
22
|
require 'google/apis/logging_v2'
|
23
|
+
require 'google/cloud/logging/v2'
|
24
|
+
require 'google/gax'
|
23
25
|
require 'google/logging/v2/logging_pb'
|
24
26
|
require 'google/logging/v2/logging_services_pb'
|
25
27
|
require 'google/logging/v2/log_entry_pb'
|
@@ -193,7 +195,7 @@ module Fluent
|
|
193
195
|
Fluent::Plugin.register_output('google_cloud', self)
|
194
196
|
|
195
197
|
PLUGIN_NAME = 'Fluentd Google Cloud Logging plugin'.freeze
|
196
|
-
PLUGIN_VERSION = '0.6.
|
198
|
+
PLUGIN_VERSION = '0.6.11.pre.memory.1'.freeze
|
197
199
|
|
198
200
|
# Name of the the Google cloud logging write scope.
|
199
201
|
LOGGING_SCOPE = 'https://www.googleapis.com/auth/logging.write'.freeze
|
@@ -391,6 +393,7 @@ module Fluent
|
|
391
393
|
'The number of log entries that failed to be ingested by the'\
|
392
394
|
' Stackdriver output plugin due to a transient error and were'\
|
393
395
|
' retried')
|
396
|
+
@ok_code = @use_grpc ? 0 : 200
|
394
397
|
end
|
395
398
|
|
396
399
|
# Alert on old authentication configuration.
|
@@ -514,17 +517,6 @@ module Fluent
|
|
514
517
|
severity = compute_severity(
|
515
518
|
entry_level_resource.type, record, entry_level_common_labels)
|
516
519
|
|
517
|
-
ts_secs = begin
|
518
|
-
Integer ts_secs
|
519
|
-
rescue ArgumentError, TypeError
|
520
|
-
ts_secs
|
521
|
-
end
|
522
|
-
ts_nanos = begin
|
523
|
-
Integer ts_nanos
|
524
|
-
rescue ArgumentError, TypeError
|
525
|
-
ts_nanos
|
526
|
-
end
|
527
|
-
|
528
520
|
if @use_grpc
|
529
521
|
entry = Google::Logging::V2::LogEntry.new(
|
530
522
|
labels: entry_level_common_labels,
|
@@ -583,18 +575,16 @@ module Fluent
|
|
583
575
|
[k.encode('utf-8'), convert_to_utf8(v)]
|
584
576
|
end
|
585
577
|
|
586
|
-
|
578
|
+
entries_count = entries.length
|
579
|
+
client.write_log_entries(
|
580
|
+
entries,
|
587
581
|
log_name: log_name,
|
588
582
|
resource: Google::Api::MonitoredResource.new(
|
589
583
|
type: group_level_resource.type,
|
590
584
|
labels: group_level_resource.labels.to_h
|
591
585
|
),
|
592
|
-
labels: labels_utf8_pairs.to_h
|
593
|
-
entries: entries
|
586
|
+
labels: labels_utf8_pairs.to_h
|
594
587
|
)
|
595
|
-
|
596
|
-
entries_count = entries.length
|
597
|
-
client.write_log_entries(write_request)
|
598
588
|
increment_successful_requests_count
|
599
589
|
increment_ingested_entries_count(entries_count)
|
600
590
|
|
@@ -605,45 +595,62 @@ module Fluent
|
|
605
595
|
@log.info 'Successfully sent gRPC to Stackdriver Logging API.'
|
606
596
|
end
|
607
597
|
|
608
|
-
rescue
|
609
|
-
|
610
|
-
|
611
|
-
# RPC cancelled, so retry via re-raising the error.
|
612
|
-
@log.debug "Retrying #{entries_count} log message(s) later.",
|
613
|
-
error: error.to_s, error_code: error.code.to_s
|
614
|
-
raise error
|
615
|
-
|
616
|
-
rescue GRPC::BadStatus => error
|
598
|
+
rescue Google::Gax::GaxError => gax_error
|
599
|
+
# GRPC::BadStatus is wrapped in error.cause.
|
600
|
+
error = gax_error.cause
|
617
601
|
increment_failed_requests_count(error.code)
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
602
|
+
|
603
|
+
# See the mapping between HTTP status and gRPC status code at:
|
604
|
+
# https://github.com/grpc/grpc/blob/master/src/core/lib/transport/status_conversion.cc
|
605
|
+
case error
|
606
|
+
# Server error, so retry via re-raising the error.
|
607
|
+
when \
|
608
|
+
# HTTP status 500 (Internal Server Error).
|
609
|
+
GRPC::Internal,
|
610
|
+
# HTTP status 501 (Not Implemented).
|
611
|
+
GRPC::Unimplemented,
|
612
|
+
# HTTP status 503 (Service Unavailable).
|
613
|
+
GRPC::Unavailable,
|
614
|
+
# HTTP status 504 (Gateway Timeout).
|
615
|
+
GRPC::DeadlineExceeded
|
616
|
+
increment_retried_entries_count(entries_count, error.code)
|
626
617
|
@log.debug "Retrying #{entries_count} log message(s) later.",
|
627
618
|
error: error.to_s, error_code: error.code.to_s
|
628
619
|
raise error
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
620
|
+
|
621
|
+
# Most client errors indicate a problem with the request itself and
|
622
|
+
# should not be retried.
|
623
|
+
when \
|
624
|
+
# HTTP status 400 (Bad Request).
|
625
|
+
GRPC::InvalidArgument,
|
626
|
+
# HTTP status 401 (Unauthorized).
|
627
|
+
# These are usually solved via a `gcloud auth` call, or by
|
628
|
+
# modifying the permissions on the Google Cloud project.
|
629
|
+
GRPC::Unauthenticated,
|
630
|
+
# HTTP status 403 (Forbidden).
|
631
|
+
GRPC::PermissionDenied,
|
632
|
+
# HTTP status 404 (Not Found).
|
633
|
+
GRPC::NotFound,
|
634
|
+
# HTTP status 409 (Conflict).
|
635
|
+
GRPC::Aborted,
|
636
|
+
# HTTP status 412 (Precondition Failed).
|
637
|
+
GRPC::FailedPrecondition,
|
638
|
+
# HTTP status 429 (Too Many Requests).
|
639
|
+
GRPC::ResourceExhausted,
|
640
|
+
# HTTP status 499 (Client Closed Request).
|
641
|
+
GRPC::Cancelled,
|
642
|
+
# the remaining http codes in both 4xx and 5xx category.
|
643
|
+
# It's debatable whether to retry or drop these log entries.
|
644
|
+
# This decision is made to avoid retrying forever due to client
|
645
|
+
# errors.
|
646
|
+
GRPC::Unknown
|
647
|
+
increment_dropped_entries_count(entries_count, error.code)
|
641
648
|
@log.warn "Dropping #{entries_count} log message(s)",
|
642
649
|
error: error.to_s, error_code: error.code.to_s
|
650
|
+
|
643
651
|
else
|
644
|
-
# Assume
|
645
|
-
|
646
|
-
increment_dropped_entries_count(entries_count)
|
652
|
+
# Assume it is a problem with the request itself and don't retry.
|
653
|
+
increment_dropped_entries_count(entries_count, error.code)
|
647
654
|
@log.error "Unknown response code #{error.code} from the "\
|
648
655
|
"server, dropping #{entries_count} log message(s)",
|
649
656
|
error: error.to_s, error_code: error.code.to_s
|
@@ -681,36 +688,38 @@ module Fluent
|
|
681
688
|
end
|
682
689
|
|
683
690
|
rescue Google::Apis::ServerError => error
|
684
|
-
#
|
685
|
-
increment_retried_entries_count(
|
691
|
+
# 5xx server errors. Retry via re-raising the error.
|
692
|
+
increment_retried_entries_count(entries_count, error.status_code)
|
686
693
|
@log.debug "Retrying #{entries_count} log message(s) later.",
|
687
694
|
error: error.to_s, error_code: error.status_code.to_s
|
688
695
|
raise error
|
689
696
|
|
690
697
|
rescue Google::Apis::AuthorizationError => error
|
691
|
-
#
|
698
|
+
# 401 authorization error.
|
692
699
|
# These are usually solved via a `gcloud auth` call, or by modifying
|
693
700
|
# the permissions on the Google Cloud project.
|
694
|
-
increment_dropped_entries_count(entries_count)
|
701
|
+
increment_dropped_entries_count(entries_count, error.status_code)
|
695
702
|
@log.warn "Dropping #{entries_count} log message(s)",
|
696
703
|
error_class: error.class.to_s, error: error.to_s
|
697
704
|
|
698
705
|
rescue Google::Apis::ClientError => error
|
699
|
-
# Most
|
700
|
-
# should not be retried.
|
706
|
+
# 4xx client errors. Most client errors indicate a problem with the
|
707
|
+
# request itself and should not be retried.
|
701
708
|
error_details_map = construct_error_details_map(error)
|
702
709
|
if error_details_map.empty?
|
703
|
-
increment_dropped_entries_count(entries_count)
|
710
|
+
increment_dropped_entries_count(entries_count, error.status_code)
|
704
711
|
@log.warn "Dropping #{entries_count} log message(s)",
|
705
712
|
error_class: error.class.to_s, error: error.to_s
|
706
713
|
else
|
707
714
|
error_details_map.each do |(error_code, error_message), indexes|
|
708
715
|
partial_error_count = indexes.length
|
709
|
-
increment_dropped_entries_count(partial_error_count)
|
716
|
+
increment_dropped_entries_count(partial_error_count, error_code)
|
717
|
+
entries_count -= partial_error_count
|
710
718
|
@log.warn "Dropping #{partial_error_count} log message(s)",
|
711
719
|
error_code: "google.rpc.Code[#{error_code}]",
|
712
720
|
error: error_message
|
713
721
|
end
|
722
|
+
increment_ingested_entries_count(entries_count)
|
714
723
|
end
|
715
724
|
end
|
716
725
|
end
|
@@ -839,11 +848,9 @@ module Fluent
|
|
839
848
|
# 2. If not, try to retrieve it by calling metadata server directly.
|
840
849
|
# 3. If still not set, try to obtain it from the credentials.
|
841
850
|
def set_project_id
|
851
|
+
@project_id ||= CredentialsInfo.project_id
|
842
852
|
@project_id ||= fetch_gce_metadata('project/project-id') if
|
843
853
|
@platform == Platform::GCE
|
844
|
-
@project_id ||= CredentialsInfo.project_id
|
845
|
-
rescue StandardError => e
|
846
|
-
@log.error 'Failed to obtain project id: ', error: e
|
847
854
|
end
|
848
855
|
|
849
856
|
# 1. Return the value if it is explicitly set in the config already.
|
@@ -1312,7 +1319,14 @@ module Fluent
|
|
1312
1319
|
instance_prefix
|
1313
1320
|
end
|
1314
1321
|
|
1322
|
+
def time_or_nil(ts_secs, ts_nanos)
|
1323
|
+
Time.at((Integer ts_secs), (Integer ts_nanos) / 1_000.0)
|
1324
|
+
rescue ArgumentError, TypeError
|
1325
|
+
nil
|
1326
|
+
end
|
1327
|
+
|
1315
1328
|
def compute_timestamp(resource_type, record, time)
|
1329
|
+
current_time = Time.now
|
1316
1330
|
if record.key?('timestamp') &&
|
1317
1331
|
record['timestamp'].is_a?(Hash) &&
|
1318
1332
|
record['timestamp'].key?('seconds') &&
|
@@ -1320,10 +1334,12 @@ module Fluent
|
|
1320
1334
|
ts_secs = record['timestamp']['seconds']
|
1321
1335
|
ts_nanos = record['timestamp']['nanos']
|
1322
1336
|
record.delete('timestamp')
|
1337
|
+
timestamp = time_or_nil(ts_secs, ts_nanos)
|
1323
1338
|
elsif record.key?('timestampSeconds') &&
|
1324
1339
|
record.key?('timestampNanos')
|
1325
1340
|
ts_secs = record.delete('timestampSeconds')
|
1326
1341
|
ts_nanos = record.delete('timestampNanos')
|
1342
|
+
timestamp = time_or_nil(ts_secs, ts_nanos)
|
1327
1343
|
elsif record.key?('timeNanos')
|
1328
1344
|
# This is deprecated since the precision is insufficient.
|
1329
1345
|
# Use timestampSeconds/timestampNanos instead
|
@@ -1336,11 +1352,13 @@ module Fluent
|
|
1336
1352
|
@log.warn 'timeNanos is deprecated - please use ' \
|
1337
1353
|
'timestampSeconds and timestampNanos instead.'
|
1338
1354
|
end
|
1355
|
+
timestamp = time_or_nil(ts_secs, ts_nanos)
|
1339
1356
|
elsif resource_type == CLOUDFUNCTIONS_CONSTANTS[:resource_type] &&
|
1340
1357
|
@cloudfunctions_log_match
|
1341
|
-
timestamp = DateTime.parse(
|
1342
|
-
|
1343
|
-
|
1358
|
+
timestamp = DateTime.parse(
|
1359
|
+
@cloudfunctions_log_match['timestamp']).to_time
|
1360
|
+
ts_secs = timestamp.tv_sec
|
1361
|
+
ts_nanos = timestamp.tv_nsec
|
1344
1362
|
elsif record.key?('time')
|
1345
1363
|
# k8s ISO8601 timestamp
|
1346
1364
|
begin
|
@@ -1355,6 +1373,44 @@ module Fluent
|
|
1355
1373
|
ts_secs = timestamp.tv_sec
|
1356
1374
|
ts_nanos = timestamp.tv_nsec
|
1357
1375
|
end
|
1376
|
+
ts_secs = begin
|
1377
|
+
Integer ts_secs
|
1378
|
+
rescue ArgumentError, TypeError
|
1379
|
+
ts_secs
|
1380
|
+
end
|
1381
|
+
ts_nanos = begin
|
1382
|
+
Integer ts_nanos
|
1383
|
+
rescue ArgumentError, TypeError
|
1384
|
+
ts_nanos
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
# Adjust timestamps from the future.
|
1388
|
+
# There are two cases:
|
1389
|
+
# 1. The parsed timestamp is later in the current year:
|
1390
|
+
# This can happen when system log lines from previous years are missing
|
1391
|
+
# the year, so the date parser assumes the current year.
|
1392
|
+
# We treat these lines as coming from last year. This could label
|
1393
|
+
# 2-year-old logs incorrectly, but this probably isn't super important.
|
1394
|
+
#
|
1395
|
+
# 2. The parsed timestamp is past the end of the current year:
|
1396
|
+
# Since the year is different from the current year, this isn't the
|
1397
|
+
# missing year in system logs. It is unlikely that users explicitly
|
1398
|
+
# write logs at a future date. This could result from an unsynchronized
|
1399
|
+
# clock on a VM, or some random value being parsed as the timestamp.
|
1400
|
+
# We reset the timestamp on those lines to the default value and let the
|
1401
|
+
# downstream API handle it.
|
1402
|
+
if timestamp
|
1403
|
+
next_year = Time.mktime(current_time.year + 1)
|
1404
|
+
one_day_later = current_time.to_datetime.next_day.to_time
|
1405
|
+
if timestamp >= next_year # Case 2.
|
1406
|
+
ts_secs = 0
|
1407
|
+
ts_nanos = 0
|
1408
|
+
elsif timestamp >= one_day_later # Case 1.
|
1409
|
+
adjusted_timestamp = timestamp.to_datetime.prev_year.to_time
|
1410
|
+
ts_secs = adjusted_timestamp.tv_sec
|
1411
|
+
# The value of ts_nanos should not change when subtracting a year.
|
1412
|
+
end
|
1413
|
+
end
|
1358
1414
|
[ts_secs, ts_nanos]
|
1359
1415
|
end
|
1360
1416
|
|
@@ -1454,7 +1510,7 @@ module Fluent
|
|
1454
1510
|
|
1455
1511
|
def parse_severity(severity_str)
|
1456
1512
|
# The API is case insensitive, but uppercase to make things simpler.
|
1457
|
-
severity = severity_str.upcase.strip
|
1513
|
+
severity = severity_str.to_s.upcase.strip
|
1458
1514
|
|
1459
1515
|
# If the severity is already valid, just return it.
|
1460
1516
|
return severity if VALID_SEVERITIES.include?(severity)
|
@@ -1714,15 +1770,19 @@ module Fluent
|
|
1714
1770
|
def api_client
|
1715
1771
|
if @use_grpc
|
1716
1772
|
ssl_creds = GRPC::Core::ChannelCredentials.new
|
1717
|
-
authentication = Google::Auth.get_application_default
|
1718
|
-
creds = GRPC::Core::CallCredentials.new(
|
1773
|
+
authentication = Google::Auth.get_application_default(LOGGING_SCOPE)
|
1774
|
+
creds = GRPC::Core::CallCredentials.new(lambda do |a_hash|
|
1775
|
+
authentication.apply(a_hash, use_configured_scope: true)
|
1776
|
+
end)
|
1719
1777
|
creds = ssl_creds.compose(creds)
|
1720
|
-
@client = Google::Logging::V2::
|
1721
|
-
|
1778
|
+
@client = Google::Cloud::Logging::V2::LoggingServiceV2Client.new(
|
1779
|
+
channel: GRPC::Core::Channel.new(
|
1780
|
+
'logging.googleapis.com', nil, creds))
|
1722
1781
|
else
|
1723
1782
|
unless @client.authorization.expired?
|
1724
1783
|
begin
|
1725
|
-
@client.authorization.fetch_access_token!
|
1784
|
+
@client.authorization.fetch_access_token!(
|
1785
|
+
use_configured_scope: true)
|
1726
1786
|
rescue MultiJson::ParseError
|
1727
1787
|
# Workaround an issue in the API client; just re-raise a more
|
1728
1788
|
# descriptive error for the user (which will still cause a retry).
|
@@ -1873,7 +1933,7 @@ module Fluent
|
|
1873
1933
|
# Increment the metric for the number of successful requests.
|
1874
1934
|
def increment_successful_requests_count
|
1875
1935
|
return unless @successful_requests_count
|
1876
|
-
@successful_requests_count.increment(grpc: @use_grpc)
|
1936
|
+
@successful_requests_count.increment(grpc: @use_grpc, code: @ok_code)
|
1877
1937
|
end
|
1878
1938
|
|
1879
1939
|
# Increment the metric for the number of failed requests, labeled by
|
@@ -1887,21 +1947,22 @@ module Fluent
|
|
1887
1947
|
# ingested by the Stackdriver Logging API.
|
1888
1948
|
def increment_ingested_entries_count(count)
|
1889
1949
|
return unless @ingested_entries_count
|
1890
|
-
@ingested_entries_count.increment({},
|
1950
|
+
@ingested_entries_count.increment({ grpc: @use_grpc, code: @ok_code },
|
1951
|
+
count)
|
1891
1952
|
end
|
1892
1953
|
|
1893
1954
|
# Increment the metric for the number of log entries that were dropped
|
1894
1955
|
# and not ingested by the Stackdriver Logging API.
|
1895
|
-
def increment_dropped_entries_count(count)
|
1956
|
+
def increment_dropped_entries_count(count, code)
|
1896
1957
|
return unless @dropped_entries_count
|
1897
|
-
@dropped_entries_count.increment({}, count)
|
1958
|
+
@dropped_entries_count.increment({ grpc: @use_grpc, code: code }, count)
|
1898
1959
|
end
|
1899
1960
|
|
1900
1961
|
# Increment the metric for the number of log entries that were dropped
|
1901
1962
|
# and not ingested by the Stackdriver Logging API.
|
1902
1963
|
def increment_retried_entries_count(count, code)
|
1903
1964
|
return unless @retried_entries_count
|
1904
|
-
@retried_entries_count.increment({ code: code }, count)
|
1965
|
+
@retried_entries_count.increment({ grpc: @use_grpc, code: code }, count)
|
1905
1966
|
end
|
1906
1967
|
end
|
1907
1968
|
end
|
data/test/plugin/base_test.rb
CHANGED
@@ -177,7 +177,6 @@ module BaseTest
|
|
177
177
|
def test_ec2_metadata_requires_project_id
|
178
178
|
setup_ec2_metadata_stubs
|
179
179
|
exception_count = 0
|
180
|
-
Fluent::GoogleCloudOutput::CredentialsInfo.stubs(:project_id).returns(nil)
|
181
180
|
begin
|
182
181
|
create_driver
|
183
182
|
rescue Fluent::ConfigError => error
|
@@ -188,13 +187,15 @@ module BaseTest
|
|
188
187
|
assert_equal 1, exception_count
|
189
188
|
end
|
190
189
|
|
191
|
-
def
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
190
|
+
def test_project_id_from_credentials
|
191
|
+
%w(gce ec2).each do |platform|
|
192
|
+
send("setup_#{platform}_metadata_stubs")
|
193
|
+
[IAM_CREDENTIALS, LEGACY_CREDENTIALS].each do |creds|
|
194
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = creds[:path]
|
195
|
+
d = create_driver
|
196
|
+
d.run
|
197
|
+
assert_equal creds[:project_id], d.instance.project_id
|
198
|
+
end
|
198
199
|
end
|
199
200
|
end
|
200
201
|
|
@@ -216,18 +217,17 @@ module BaseTest
|
|
216
217
|
d.emit('message' => log_entry(0))
|
217
218
|
d.run
|
218
219
|
end
|
219
|
-
verify_log_entries(1, COMPUTE_PARAMS
|
220
|
+
verify_log_entries(1, COMPUTE_PARAMS.merge(
|
221
|
+
project_id: IAM_CREDENTIALS[:project_id]))
|
220
222
|
end
|
221
223
|
|
222
|
-
def
|
223
|
-
|
224
|
-
|
225
|
-
setup_logging_stubs do
|
226
|
-
d = create_driver
|
227
|
-
d.emit('message' => log_entry(0))
|
224
|
+
def test_invalid_json_credentials
|
225
|
+
%w(gce_metadata ec2_metadata no_metadata_service).each do |platform|
|
226
|
+
send("setup_#{platform}_stubs")
|
228
227
|
exception_count = 0
|
228
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = INVALID_CREDENTIALS[:path]
|
229
229
|
begin
|
230
|
-
|
230
|
+
create_driver
|
231
231
|
rescue RuntimeError => error
|
232
232
|
assert error.message.include? 'Unable to read the credential file'
|
233
233
|
exception_count += 1
|
@@ -607,7 +607,22 @@ module BaseTest
|
|
607
607
|
|
608
608
|
def test_timestamps
|
609
609
|
setup_gce_metadata_stubs
|
610
|
-
|
610
|
+
current_time = Time.now
|
611
|
+
next_year = Time.mktime(current_time.year + 1)
|
612
|
+
one_second_before_next_year = next_year - 1
|
613
|
+
adjusted_to_last_year =
|
614
|
+
one_second_before_next_year.to_datetime.prev_year.to_time
|
615
|
+
one_second_into_next_year = next_year + 1
|
616
|
+
one_day_into_next_year = next_year.to_date.next_day.to_time
|
617
|
+
{
|
618
|
+
Time.at(123_456.789) => Time.at(123_456.789),
|
619
|
+
Time.at(0) => Time.at(0),
|
620
|
+
current_time => current_time,
|
621
|
+
one_second_before_next_year => adjusted_to_last_year,
|
622
|
+
next_year => Time.at(0),
|
623
|
+
one_second_into_next_year => Time.at(0),
|
624
|
+
one_day_into_next_year => Time.at(0)
|
625
|
+
}.each do |ts, adjusted_ts|
|
611
626
|
expected_ts = []
|
612
627
|
emit_index = 0
|
613
628
|
setup_logging_stubs do
|
@@ -615,24 +630,24 @@ module BaseTest
|
|
615
630
|
d = create_driver
|
616
631
|
# Test the "native" fluentd timestamp as well as our nanosecond tags.
|
617
632
|
d.emit({ 'message' => log_entry(emit_index) }, ts.to_f)
|
618
|
-
expected_ts.push(
|
633
|
+
expected_ts.push(adjusted_ts)
|
619
634
|
emit_index += 1
|
620
635
|
d.emit('message' => log_entry(emit_index),
|
621
636
|
'timeNanos' => ts.tv_sec * 1_000_000_000 + ts.tv_nsec)
|
622
|
-
expected_ts.push(
|
637
|
+
expected_ts.push(adjusted_ts)
|
623
638
|
emit_index += 1
|
624
639
|
d.emit('message' => log_entry(emit_index),
|
625
640
|
'timestamp' => { 'seconds' => ts.tv_sec, 'nanos' => ts.tv_nsec })
|
626
|
-
expected_ts.push(
|
641
|
+
expected_ts.push(adjusted_ts)
|
627
642
|
emit_index += 1
|
628
643
|
d.emit('message' => log_entry(emit_index),
|
629
644
|
'timestampSeconds' => ts.tv_sec, 'timestampNanos' => ts.tv_nsec)
|
630
|
-
expected_ts.push(
|
645
|
+
expected_ts.push(adjusted_ts)
|
631
646
|
emit_index += 1
|
632
647
|
d.emit('message' => log_entry(emit_index),
|
633
648
|
'timestampSeconds' => ts.tv_sec.to_s,
|
634
649
|
'timestampNanos' => ts.tv_nsec.to_s)
|
635
|
-
expected_ts.push(
|
650
|
+
expected_ts.push(adjusted_ts)
|
636
651
|
emit_index += 1
|
637
652
|
d.run
|
638
653
|
verify_index = 0
|
data/test/plugin/constants.rb
CHANGED
@@ -53,24 +53,31 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
53
53
|
|
54
54
|
def test_partial_success
|
55
55
|
setup_gce_metadata_stubs
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
d
|
66
|
-
4.times do |i|
|
67
|
-
d.emit('message' => log_entry(i.to_s))
|
68
|
-
end
|
69
|
-
d.run
|
70
|
-
assert_prometheus_metric_value(:stackdriver_dropped_entries_count,
|
71
|
-
failed_entry_count)
|
56
|
+
setup_prometheus
|
57
|
+
# The API Client should not retry this and the plugin should consume
|
58
|
+
# the exception.
|
59
|
+
root_error_code = PARTIAL_SUCCESS_RESPONSE_BODY['error']['code']
|
60
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI)
|
61
|
+
.to_return(status: root_error_code,
|
62
|
+
body: PARTIAL_SUCCESS_RESPONSE_BODY.to_json)
|
63
|
+
d = create_driver(PROMETHEUS_ENABLE_CONFIG + PARTIAL_SUCCESS_CONFIG)
|
64
|
+
4.times do |i|
|
65
|
+
d.emit('message' => log_entry(i.to_s))
|
72
66
|
end
|
73
|
-
|
67
|
+
d.run
|
68
|
+
assert_prometheus_metric_value(
|
69
|
+
:stackdriver_successful_requests_count, 0, grpc: false, code: 200)
|
70
|
+
assert_prometheus_metric_value(
|
71
|
+
:stackdriver_failed_requests_count, 1, grpc: false, code: root_error_code)
|
72
|
+
assert_prometheus_metric_value(
|
73
|
+
:stackdriver_ingested_entries_count, 1, grpc: false, code: 200)
|
74
|
+
assert_prometheus_metric_value(
|
75
|
+
:stackdriver_dropped_entries_count, 2, grpc: false, code: 3)
|
76
|
+
assert_prometheus_metric_value(
|
77
|
+
:stackdriver_dropped_entries_count, 1, grpc: false, code: 7)
|
78
|
+
assert_prometheus_metric_value(
|
79
|
+
:stackdriver_retried_entries_count, 0, grpc: false)
|
80
|
+
assert_requested(:post, WRITE_LOG_ENTRIES_URI, times: 1)
|
74
81
|
end
|
75
82
|
|
76
83
|
def test_server_error
|
@@ -131,16 +138,20 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
131
138
|
ingested_entries_count, dropped_entries_count,
|
132
139
|
retried_entries_count = metric_values
|
133
140
|
assert_prometheus_metric_value(:stackdriver_successful_requests_count,
|
134
|
-
successful_requests_count,
|
141
|
+
successful_requests_count,
|
142
|
+
grpc: false, code: 200)
|
135
143
|
assert_prometheus_metric_value(:stackdriver_failed_requests_count,
|
136
144
|
failed_requests_count,
|
137
145
|
grpc: false, code: code)
|
138
146
|
assert_prometheus_metric_value(:stackdriver_ingested_entries_count,
|
139
|
-
ingested_entries_count
|
147
|
+
ingested_entries_count,
|
148
|
+
grpc: false, code: 200)
|
140
149
|
assert_prometheus_metric_value(:stackdriver_dropped_entries_count,
|
141
|
-
dropped_entries_count
|
150
|
+
dropped_entries_count,
|
151
|
+
grpc: false, code: code)
|
142
152
|
assert_prometheus_metric_value(:stackdriver_retried_entries_count,
|
143
|
-
retried_entries_count,
|
153
|
+
retried_entries_count,
|
154
|
+
grpc: false, code: code)
|
144
155
|
end
|
145
156
|
end
|
146
157
|
|
@@ -206,6 +217,8 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
206
217
|
assert_equal(100, test_obj.parse_severity(' 105'))
|
207
218
|
assert_equal(100, test_obj.parse_severity(' 105 '))
|
208
219
|
|
220
|
+
assert_equal(100, test_obj.parse_severity(100))
|
221
|
+
|
209
222
|
assert_equal('DEFAULT', test_obj.parse_severity('-100'))
|
210
223
|
assert_equal('DEFAULT', test_obj.parse_severity('105 100'))
|
211
224
|
|
@@ -243,6 +256,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
243
256
|
assert_equal('DEFAULT', test_obj.parse_severity('ER ROR'))
|
244
257
|
|
245
258
|
# anything else should translate to 'DEFAULT'
|
259
|
+
assert_equal('DEFAULT', test_obj.parse_severity(nil))
|
260
|
+
assert_equal('DEFAULT', test_obj.parse_severity(Object.new))
|
261
|
+
assert_equal('DEFAULT', test_obj.parse_severity({}))
|
262
|
+
assert_equal('DEFAULT', test_obj.parse_severity([]))
|
263
|
+
assert_equal('DEFAULT', test_obj.parse_severity(100.0))
|
246
264
|
assert_equal('DEFAULT', test_obj.parse_severity(''))
|
247
265
|
assert_equal('DEFAULT', test_obj.parse_severity('garbage'))
|
248
266
|
assert_equal('DEFAULT', test_obj.parse_severity('er'))
|
@@ -28,12 +28,19 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
28
28
|
|
29
29
|
def test_client_error
|
30
30
|
setup_gce_metadata_stubs
|
31
|
-
{
|
32
|
-
|
33
|
-
|
31
|
+
{
|
32
|
+
GRPC::Core::StatusCodes::CANCELLED => 'Cancelled',
|
33
|
+
GRPC::Core::StatusCodes::UNKNOWN => 'Unknown',
|
34
|
+
GRPC::Core::StatusCodes::INVALID_ARGUMENT => 'InvalidArgument',
|
35
|
+
GRPC::Core::StatusCodes::NOT_FOUND => 'NotFound',
|
36
|
+
GRPC::Core::StatusCodes::PERMISSION_DENIED => 'PermissionDenied',
|
37
|
+
GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED => 'ResourceExhausted',
|
38
|
+
GRPC::Core::StatusCodes::FAILED_PRECONDITION => 'FailedPrecondition',
|
39
|
+
GRPC::Core::StatusCodes::ABORTED => 'Aborted',
|
40
|
+
GRPC::Core::StatusCodes::UNAUTHENTICATED => 'Unauthenticated'
|
41
|
+
}.each_with_index do |(code, message), index|
|
34
42
|
setup_logging_stubs(true, code, message) do
|
35
|
-
d = create_driver(USE_GRPC_CONFIG, 'test'
|
36
|
-
GRPCLoggingMockFailingService.rpc_stub_class)
|
43
|
+
d = create_driver(USE_GRPC_CONFIG, 'test')
|
37
44
|
# The API Client should not retry this and the plugin should consume the
|
38
45
|
# exception.
|
39
46
|
d.emit('message' => log_entry(0))
|
@@ -45,23 +52,20 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
45
52
|
|
46
53
|
def test_server_error
|
47
54
|
setup_gce_metadata_stubs
|
48
|
-
{
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
55
|
+
{
|
56
|
+
GRPC::Core::StatusCodes::DEADLINE_EXCEEDED => 'DeadlineExceeded',
|
57
|
+
GRPC::Core::StatusCodes::UNIMPLEMENTED => 'Unimplemented',
|
58
|
+
GRPC::Core::StatusCodes::INTERNAL => 'Internal',
|
59
|
+
GRPC::Core::StatusCodes::UNAVAILABLE => 'Unavailable'
|
60
|
+
}.each_with_index do |(code, message), index|
|
53
61
|
exception_count = 0
|
54
62
|
setup_logging_stubs(true, code, message) do
|
55
|
-
d = create_driver(USE_GRPC_CONFIG, 'test'
|
56
|
-
GRPCLoggingMockFailingService.rpc_stub_class)
|
63
|
+
d = create_driver(USE_GRPC_CONFIG, 'test')
|
57
64
|
# The API client should retry this once, then throw an exception which
|
58
65
|
# gets propagated through the plugin
|
59
66
|
d.emit('message' => log_entry(0))
|
60
67
|
begin
|
61
68
|
d.run
|
62
|
-
rescue GRPC::Cancelled
|
63
|
-
# No need to check the message -- we already know the code.
|
64
|
-
exception_count += 1
|
65
69
|
rescue GRPC::BadStatus => error
|
66
70
|
assert_equal "#{code}:#{message}", error.message
|
67
71
|
exception_count += 1
|
@@ -93,8 +97,7 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
93
97
|
setup_prometheus
|
94
98
|
(1..request_count).each do
|
95
99
|
setup_logging_stubs(should_fail, code, 'SomeMessage') do
|
96
|
-
d = create_driver(USE_GRPC_CONFIG + PROMETHEUS_ENABLE_CONFIG, 'test'
|
97
|
-
GRPCLoggingMockFailingService.rpc_stub_class)
|
100
|
+
d = create_driver(USE_GRPC_CONFIG + PROMETHEUS_ENABLE_CONFIG, 'test')
|
98
101
|
(1..entry_count).each do |i|
|
99
102
|
d.emit('message' => log_entry(i.to_s))
|
100
103
|
end
|
@@ -110,16 +113,20 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
110
113
|
ingested_entries_count, dropped_entries_count,
|
111
114
|
retried_entries_count = metric_values
|
112
115
|
assert_prometheus_metric_value(:stackdriver_successful_requests_count,
|
113
|
-
successful_requests_count,
|
116
|
+
successful_requests_count,
|
117
|
+
grpc: true, code: 0)
|
114
118
|
assert_prometheus_metric_value(:stackdriver_failed_requests_count,
|
115
119
|
failed_requests_count,
|
116
120
|
grpc: true, code: code)
|
117
121
|
assert_prometheus_metric_value(:stackdriver_ingested_entries_count,
|
118
|
-
ingested_entries_count
|
122
|
+
ingested_entries_count,
|
123
|
+
grpc: true, code: 0)
|
119
124
|
assert_prometheus_metric_value(:stackdriver_dropped_entries_count,
|
120
|
-
dropped_entries_count
|
125
|
+
dropped_entries_count,
|
126
|
+
grpc: true, code: code)
|
121
127
|
assert_prometheus_metric_value(:stackdriver_retried_entries_count,
|
122
|
-
retried_entries_count,
|
128
|
+
retried_entries_count,
|
129
|
+
grpc: true, code: code)
|
123
130
|
end
|
124
131
|
end
|
125
132
|
|
@@ -212,82 +219,58 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
212
219
|
use_grpc true
|
213
220
|
).freeze
|
214
221
|
|
215
|
-
@@mock_port = 0 # rubocop:disable Style/ClassVars
|
216
|
-
|
217
|
-
def generate_mock_host
|
218
|
-
# rubocop:disable Style/ClassVars
|
219
|
-
@@mock_port = (@@mock_port + 1) % 10_000 + 50_000
|
220
|
-
"localhost:#{@@mock_port}"
|
221
|
-
# rubocop:enable Style/ClassVars
|
222
|
-
end
|
223
|
-
|
224
222
|
# Create a Fluentd output test driver with the Google Cloud Output plugin with
|
225
223
|
# grpc enabled. The signature of this method is different between the grpc
|
226
224
|
# path and the non-grpc path. For grpc, an additional grpc stub class can be
|
227
225
|
# passed in to construct the mock used by the test driver.
|
228
|
-
def create_driver(conf = APPLICATION_DEFAULT_CONFIG, tag = 'test'
|
229
|
-
grpc_stub = GRPCLoggingMockService.rpc_stub_class)
|
226
|
+
def create_driver(conf = APPLICATION_DEFAULT_CONFIG, tag = 'test')
|
230
227
|
conf += USE_GRPC_CONFIG
|
231
228
|
Fluent::Test::BufferedOutputTestDriver.new(
|
232
|
-
GoogleCloudOutputWithGRPCMock.new(grpc_stub,
|
233
|
-
tag).configure(conf, true)
|
229
|
+
GoogleCloudOutputWithGRPCMock.new(@grpc_stub), tag).configure(conf, true)
|
234
230
|
end
|
235
231
|
|
236
232
|
# Google Cloud Fluent output stub with grpc mock.
|
237
233
|
class GoogleCloudOutputWithGRPCMock < Fluent::GoogleCloudOutput
|
238
|
-
def initialize(grpc_stub
|
234
|
+
def initialize(grpc_stub)
|
239
235
|
super()
|
240
236
|
@grpc_stub = grpc_stub
|
241
|
-
@mock_host = mock_host
|
242
237
|
end
|
243
238
|
|
244
239
|
def api_client
|
245
240
|
ssl_creds = GRPC::Core::ChannelCredentials.new
|
246
|
-
authentication = Google::Auth.get_application_default
|
247
|
-
creds = GRPC::Core::CallCredentials.new(
|
241
|
+
authentication = Google::Auth.get_application_default(LOGGING_SCOPE)
|
242
|
+
creds = GRPC::Core::CallCredentials.new(lambda do |a_hash|
|
243
|
+
authentication.apply(a_hash, use_configured_scope: true)
|
244
|
+
end)
|
248
245
|
ssl_creds.compose(creds)
|
249
246
|
|
250
|
-
|
251
|
-
# channel insecure.
|
252
|
-
@grpc_stub.new(@mock_host, :this_channel_is_insecure)
|
247
|
+
@grpc_stub
|
253
248
|
end
|
254
249
|
end
|
255
250
|
|
256
251
|
# GRPC logging mock that successfully logs the records.
|
257
|
-
class GRPCLoggingMockService <
|
252
|
+
class GRPCLoggingMockService <
|
253
|
+
Google::Cloud::Logging::V2::LoggingServiceV2Client
|
258
254
|
def initialize(requests_received)
|
259
255
|
super()
|
260
256
|
@requests_received = requests_received
|
261
257
|
end
|
262
258
|
|
263
|
-
def write_log_entries(
|
259
|
+
def write_log_entries(entries, log_name: nil, resource: nil, labels: nil)
|
260
|
+
request = Google::Apis::LoggingV2::WriteLogEntriesRequest.new(
|
261
|
+
log_name: log_name,
|
262
|
+
resource: resource,
|
263
|
+
labels: labels,
|
264
|
+
entries: entries
|
265
|
+
)
|
264
266
|
@requests_received << request
|
265
267
|
WriteLogEntriesResponse.new
|
266
268
|
end
|
267
|
-
|
268
|
-
# TODO(lingshi) Remove these dummy methods when grpc/9033 is fixed.
|
269
|
-
#
|
270
|
-
# These methods should never be called, so they will just fail the tests
|
271
|
-
# with "unimplemented" errors..
|
272
|
-
def _undefined
|
273
|
-
raise "Method #{__callee__} is unimplemented and needs to be overridden."
|
274
|
-
end
|
275
|
-
|
276
|
-
alias list_logs _undefined
|
277
|
-
alias list_log_entries _undefined
|
278
|
-
alias list_log_services _undefined
|
279
|
-
alias list_log_service_indexes _undefined
|
280
|
-
alias list_monitored_resource_descriptors _undefined
|
281
|
-
alias delete_log _undefined
|
282
|
-
undef_method :_undefined
|
283
269
|
end
|
284
270
|
|
285
271
|
# GRPC logging mock that fails and returns server side or client side errors.
|
286
272
|
class GRPCLoggingMockFailingService <
|
287
|
-
Google::Logging::V2::
|
288
|
-
# 'code_sent' and 'message_sent' are references of external variables. We
|
289
|
-
# will assert the values of them later. 'code_value' and 'message_value'
|
290
|
-
# are actual error code and message we expect this mock to return.
|
273
|
+
Google::Cloud::Logging::V2::LoggingServiceV2Client
|
291
274
|
def initialize(code, message, failed_attempts)
|
292
275
|
@code = code
|
293
276
|
@message = message
|
@@ -295,66 +278,42 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
295
278
|
super()
|
296
279
|
end
|
297
280
|
|
298
|
-
|
281
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
282
|
+
def write_log_entries(entries, log_name: nil, resource: nil, labels: nil)
|
299
283
|
@failed_attempts << 1
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
# with "unimplemented" errors..
|
307
|
-
def _undefined
|
308
|
-
raise "Method #{__callee__} is unimplemented and needs to be overridden."
|
284
|
+
begin
|
285
|
+
raise GRPC::BadStatus.new_status_exception(@code, @message)
|
286
|
+
rescue
|
287
|
+
# Google::Gax::GaxError will wrap the latest thrown exception as @cause.
|
288
|
+
raise Google::Gax::GaxError, @message
|
289
|
+
end
|
309
290
|
end
|
310
|
-
|
311
|
-
alias list_logs _undefined
|
312
|
-
alias list_log_entries _undefined
|
313
|
-
alias list_log_services _undefined
|
314
|
-
alias list_log_service_indexes _undefined
|
315
|
-
alias list_monitored_resource_descriptors _undefined
|
316
|
-
alias delete_log _undefined
|
317
|
-
undef_method :_undefined
|
291
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
318
292
|
end
|
319
293
|
|
320
294
|
# Set up grpc stubs to mock the external calls.
|
321
|
-
|
322
|
-
# Due to a gRPC load balancing issue (grpc/grpc#12506), we have to use a
|
323
|
-
# different port each time we create a gRPC mock as a temporary workaround.
|
324
|
-
# Thus we can only create one driver in each setup_logging_stubs context.
|
325
|
-
def setup_logging_stubs(should_fail = false, code = 0, message = 'Ok')
|
326
|
-
# Save the mock host in an instance variable, so later on when creating the
|
327
|
-
# logging driver, we can refer to this host with exactly the same port.
|
328
|
-
@mock_host = generate_mock_host
|
329
|
-
srv = GRPC::RpcServer.new
|
330
|
-
@failed_attempts = []
|
331
|
-
@requests_sent = []
|
295
|
+
def setup_logging_stubs(should_fail = false, code = nil, message = nil)
|
332
296
|
if should_fail
|
333
|
-
|
297
|
+
@failed_attempts = []
|
298
|
+
@grpc_stub = GRPCLoggingMockFailingService.new(
|
299
|
+
code, message, @failed_attempts)
|
334
300
|
else
|
335
|
-
|
336
|
-
|
337
|
-
srv.handle(grpc)
|
338
|
-
srv.add_http2_port(@mock_host, :this_port_is_insecure)
|
339
|
-
t = Thread.new { srv.run }
|
340
|
-
srv.wait_till_running
|
341
|
-
begin
|
342
|
-
yield
|
343
|
-
rescue Test::Unit::Failure, StandardError => e
|
344
|
-
srv.stop
|
345
|
-
t.join
|
346
|
-
raise e
|
301
|
+
@requests_sent = []
|
302
|
+
@grpc_stub = GRPCLoggingMockService.new(@requests_sent)
|
347
303
|
end
|
348
|
-
|
349
|
-
t.join
|
350
|
-
@mock_host = nil
|
304
|
+
yield
|
351
305
|
end
|
352
306
|
|
353
307
|
# Verify the number and the content of the log entries match the expectation.
|
354
308
|
# The caller can optionally provide a block which is called for each entry.
|
355
309
|
def verify_log_entries(n, params, payload_type = 'textPayload', &block)
|
356
310
|
@requests_sent.each do |request|
|
357
|
-
@logs_sent <<
|
311
|
+
@logs_sent << {
|
312
|
+
'entries' => request.entries.map { |entry| JSON.parse(entry.to_json) },
|
313
|
+
'labels' => request.labels,
|
314
|
+
'resource' => request.resource,
|
315
|
+
'logName' => request.log_name
|
316
|
+
}
|
358
317
|
end
|
359
318
|
verify_json_log_entries(n, params, payload_type, &block)
|
360
319
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-google-cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.11.pre.memory.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Derr
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-12-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fluentd
|
@@ -243,9 +243,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
243
243
|
version: '2.0'
|
244
244
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
245
245
|
requirements:
|
246
|
-
- - "
|
246
|
+
- - ">"
|
247
247
|
- !ruby/object:Gem::Version
|
248
|
-
version:
|
248
|
+
version: 1.3.1
|
249
249
|
requirements: []
|
250
250
|
rubyforge_project:
|
251
251
|
rubygems_version: 2.4.8
|