fluent-plugin-google-cloud 0.7.5 → 0.7.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c8f41809aee8029c651ce49f3214853c27afa693e8396759cc51a940aa8474b
4
- data.tar.gz: 595f84df87e4d92c2b554091731eb677bf5ef22f82e3a4b80a91468a9a404882
3
+ metadata.gz: 2a93bebee6c0d361009e34f871a735f85766599f9c42100d1d8d0580318177c3
4
+ data.tar.gz: 067150e565ba137c65846bd22ba0f1b47a0500a7ef16ae5f51a5c30284db5586
5
5
  SHA512:
6
- metadata.gz: 34479043c6ad5f90f4859f8fc08e916a09ec70330cb81e5a3762c77d2db2a9daba743a985415de9ae3b1419150a2ad19c09c2935009988110130b7b325a9937f
7
- data.tar.gz: f7f1826c54523041287c1ac1fd6cf5620c5eeb40d08d0a0988845d263ba4f71d8d57aa655e8afb8b33ca2003a9ba19eca407f3d15ebd6777e5a63de532de1877
6
+ metadata.gz: fa5799c20d5c118bdc333b7924b89cbca158f8a259efbd625280c963d0e9fff89c5bf842c7cf481dec325455bc25cdbc666b78edc1baba2a155e07440a84af81
7
+ data.tar.gz: 2701198d7c27c923a26cb44d26d3d03dae62c0b3135a6cb898bc302edd071c5dc5ee1232b650b105f8e20e352aca84d9cef6915d7586a46eb36656d7442b7514
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-google-cloud (0.7.5)
4
+ fluent-plugin-google-cloud (0.7.6)
5
5
  fluentd (= 1.2.5)
6
- google-api-client (= 0.23.9)
7
- google-cloud-logging (= 1.5.4)
6
+ google-api-client (= 0.28.4)
7
+ google-cloud-logging (= 1.6.0)
8
8
  google-protobuf (= 3.6.1)
9
9
  googleapis-common-protos (= 1.3.7)
10
10
  googleauth (= 0.6.6)
11
- grpc (= 1.8.3)
11
+ grpc (= 1.14.2)
12
12
  json (= 2.1.0)
13
13
 
14
14
  GEM
@@ -17,6 +17,7 @@ GEM
17
17
  addressable (2.6.0)
18
18
  public_suffix (>= 2.0.2, < 4.0)
19
19
  ast (2.4.0)
20
+ concurrent-ruby (1.1.5)
20
21
  cool.io (1.5.3)
21
22
  crack (0.4.3)
22
23
  safe_yaml (~> 1.0.0)
@@ -36,19 +37,20 @@ GEM
36
37
  tzinfo (~> 1.0)
37
38
  tzinfo-data (~> 1.0)
38
39
  yajl-ruby (~> 1.0)
39
- google-api-client (0.23.9)
40
+ google-api-client (0.28.4)
40
41
  addressable (~> 2.5, >= 2.5.1)
41
- googleauth (>= 0.5, < 0.7.0)
42
+ googleauth (>= 0.5, < 0.10.0)
42
43
  httpclient (>= 2.8.1, < 3.0)
43
44
  mime-types (~> 3.0)
44
45
  representable (~> 3.0)
45
46
  retriable (>= 2.0, < 4.0)
46
- signet (~> 0.9)
47
+ signet (~> 0.10)
47
48
  google-cloud-core (1.3.0)
48
49
  google-cloud-env (~> 1.0)
49
50
  google-cloud-env (1.0.5)
50
51
  faraday (~> 0.11)
51
- google-cloud-logging (1.5.4)
52
+ google-cloud-logging (1.6.0)
53
+ concurrent-ruby (~> 1.0)
52
54
  google-cloud-core (~> 1.2)
53
55
  google-gax (~> 1.3)
54
56
  googleapis-common-protos-types (>= 1.0.2)
@@ -73,10 +75,9 @@ GEM
73
75
  multi_json (~> 1.11)
74
76
  os (>= 0.9, < 2.0)
75
77
  signet (~> 0.7)
76
- grpc (1.8.3)
78
+ grpc (1.14.2)
77
79
  google-protobuf (~> 3.1)
78
80
  googleapis-common-protos-types (~> 1.0.0)
79
- googleauth (>= 0.5.1, < 0.7)
80
81
  hashdiff (0.3.8)
81
82
  http_parser.rb (0.6.0)
82
83
  httpclient (2.8.3)
@@ -89,7 +90,7 @@ GEM
89
90
  mime-types-data (3.2018.0812)
90
91
  mocha (1.8.0)
91
92
  metaclass (~> 0.0.1)
92
- msgpack (1.2.6)
93
+ msgpack (1.2.9)
93
94
  multi_json (1.13.1)
94
95
  multipart-post (2.0.0)
95
96
  os (1.0.0)
@@ -117,7 +118,7 @@ GEM
117
118
  ruby-progressbar (~> 1.7)
118
119
  unicode-display_width (~> 1.0, >= 1.0.1)
119
120
  ruby-progressbar (1.10.0)
120
- safe_yaml (1.0.4)
121
+ safe_yaml (1.0.5)
121
122
  serverengine (2.1.0)
122
123
  sigdump (~> 0.2.2)
123
124
  sigdump (0.2.4)
@@ -137,7 +138,7 @@ GEM
137
138
  tzinfo-data (1.2018.9)
138
139
  tzinfo (>= 1.0.0)
139
140
  uber (0.1.0)
140
- unicode-display_width (1.4.1)
141
+ unicode-display_width (1.5.0)
141
142
  webmock (2.3.2)
142
143
  addressable (>= 2.3.6)
143
144
  crack (>= 0.3.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.7.5'
13
+ gem.version = '0.7.6'
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')
@@ -22,10 +22,10 @@ eos
22
22
  gem.add_runtime_dependency 'fluentd', '1.2.5'
23
23
  gem.add_runtime_dependency 'googleapis-common-protos', '1.3.7'
24
24
  gem.add_runtime_dependency 'googleauth', '0.6.6'
25
- gem.add_runtime_dependency 'google-api-client', '0.23.9'
26
- gem.add_runtime_dependency 'google-cloud-logging', '1.5.4'
25
+ gem.add_runtime_dependency 'google-api-client', '0.28.4'
26
+ gem.add_runtime_dependency 'google-cloud-logging', '1.6.0'
27
27
  gem.add_runtime_dependency 'google-protobuf', '3.6.1'
28
- gem.add_runtime_dependency 'grpc', '1.8.3'
28
+ gem.add_runtime_dependency 'grpc', '1.14.2'
29
29
  gem.add_runtime_dependency 'json', '2.1.0'
30
30
 
31
31
  gem.add_development_dependency 'mocha', '~> 1.1'
@@ -153,6 +153,7 @@ module Fluent
153
153
  'logging.googleapis.com/sourceLocation'.freeze
154
154
  DEFAULT_SPAN_ID_KEY = 'logging.googleapis.com/spanId'.freeze
155
155
  DEFAULT_TRACE_KEY = 'logging.googleapis.com/trace'.freeze
156
+ DEFAULT_TRACE_SAMPLED_KEY = 'logging.googleapis.com/trace_sampled'.freeze
156
157
 
157
158
  DEFAULT_METADATA_AGENT_URL =
158
159
  'http://local-metadata-agent.stackdriver.com:8000'.freeze
@@ -245,7 +246,7 @@ module Fluent
245
246
  PLUGIN_VERSION = begin
246
247
  # Extract plugin version from file path.
247
248
  match_data = __FILE__.match(
248
- %r{fluent-plugin-google-cloud-(?<version>[0-9a-zA-Z\.]*)/})
249
+ %r{fluent-plugin-google-cloud-(?<version>[^/]*)/})
249
250
  if match_data
250
251
  match_data['version']
251
252
  else
@@ -306,6 +307,8 @@ module Fluent
306
307
  DEFAULT_SOURCE_LOCATION_KEY
307
308
  config_param :span_id_key, :string, :default => DEFAULT_SPAN_ID_KEY
308
309
  config_param :trace_key, :string, :default => DEFAULT_TRACE_KEY
310
+ config_param :trace_sampled_key, :string, :default =>
311
+ DEFAULT_TRACE_SAMPLED_KEY
309
312
 
310
313
  # Whether to try to detect if the record is a text log entry with JSON
311
314
  # content that needs to be parsed.
@@ -626,7 +629,8 @@ module Fluent
626
629
  @operation_key,
627
630
  @source_location_key,
628
631
  @span_id_key,
629
- @trace_key
632
+ @trace_key,
633
+ @trace_sampled_key
630
634
  ]
631
635
 
632
636
  # If the log is json, we want to export it as a structured log
@@ -643,7 +647,8 @@ module Fluent
643
647
  # Propagate these if necessary. Note that we don't want to
644
648
  # override these keys in the JSON we've just parsed.
645
649
  preserved_keys.each do |key|
646
- record_json[key] ||= record[key] if record.key?(key)
650
+ record_json[key] ||= record[key] if
651
+ record.key?(key) && !record_json.key?(key)
647
652
  end
648
653
 
649
654
  record = record_json
@@ -667,13 +672,15 @@ module Fluent
667
672
  ts_secs,
668
673
  ts_nanos)
669
674
 
670
- trace = record.delete(@trace_key)
671
- entry.trace = compute_trace(trace) if trace
672
-
673
- span_id = record.delete(@span_id_key)
674
- entry.span_id = span_id if span_id
675
675
  insert_id = record.delete(@insert_id_key)
676
676
  entry.insert_id = insert_id if insert_id
677
+ span_id = record.delete(@span_id_key)
678
+ entry.span_id = span_id if span_id
679
+ trace = record.delete(@trace_key)
680
+ entry.trace = compute_trace(trace) if trace
681
+ trace_sampled = record.delete(@trace_sampled_key)
682
+ entry.trace_sampled = parse_bool(trace_sampled) unless
683
+ trace_sampled.nil?
677
684
 
678
685
  set_log_entry_fields(record, entry)
679
686
  set_payload(entry_level_resource.type, record, entry, is_json)
@@ -716,6 +723,10 @@ module Fluent
716
723
  end
717
724
  end
718
725
 
726
+ def multi_workers_ready?
727
+ true
728
+ end
729
+
719
730
  private
720
731
 
721
732
  def compute_trace(trace)
@@ -969,8 +980,7 @@ module Fluent
969
980
  end
970
981
 
971
982
  def parse_json_or_nil(input)
972
- # Only here to please rubocop...
973
- return nil if input.nil?
983
+ return nil unless input.is_a?(String)
974
984
 
975
985
  input.each_codepoint do |c|
976
986
  if c == 123
@@ -1997,6 +2007,8 @@ module Fluent
1997
2007
  ret
1998
2008
  end
1999
2009
 
2010
+ # TODO(qingling128): Fix the inconsistent behavior of 'message', 'log' and
2011
+ # 'msg' in the next major version 1.0.0.
2000
2012
  def set_payload(resource_type, record, entry, is_json)
2001
2013
  # Only one of {text_payload, json_payload} will be set.
2002
2014
  text_payload = nil
@@ -2032,6 +2044,7 @@ module Fluent
2032
2044
  json_payload
2033
2045
  end
2034
2046
  elsif text_payload
2047
+ text_payload = text_payload.to_s
2035
2048
  entry.text_payload = if @use_grpc
2036
2049
  convert_to_utf8(text_payload)
2037
2050
  else
@@ -536,6 +536,78 @@ module BaseTest
536
536
  end
537
537
  end
538
538
 
539
+ # TODO(qingling128): Fix the inconsistent behavior of 'message', 'log' and
540
+ # 'msg' in the next major version 1.0.0.
541
+ def test_structured_payload_json_log_detect_json_with_hash_input
542
+ hash_value = {
543
+ 'msg' => 'test log entry 0',
544
+ 'tag2' => 'test',
545
+ 'data' => 5000,
546
+ 'some_null_field' => nil
547
+ }
548
+ [
549
+ {
550
+ config: APPLICATION_DEFAULT_CONFIG,
551
+ field_name: 'log',
552
+ expected_payload: 'jsonPayload'
553
+ },
554
+ {
555
+ config: APPLICATION_DEFAULT_CONFIG,
556
+ field_name: 'msg',
557
+ expected_payload: 'jsonPayload'
558
+ },
559
+ {
560
+ config: APPLICATION_DEFAULT_CONFIG,
561
+ field_name: 'message',
562
+ expected_payload: 'textPayload'
563
+ },
564
+ {
565
+ config: DETECT_JSON_CONFIG,
566
+ field_name: 'log',
567
+ expected_payload: 'jsonPayload'
568
+ },
569
+ {
570
+ config: DETECT_JSON_CONFIG,
571
+ field_name: 'msg',
572
+ expected_payload: 'jsonPayload'
573
+ },
574
+ {
575
+ config: DETECT_JSON_CONFIG,
576
+ field_name: 'message',
577
+ expected_payload: 'textPayload'
578
+ }
579
+ ].each do |test_params|
580
+ new_stub_context do
581
+ setup_gce_metadata_stubs
582
+ setup_logging_stubs do
583
+ d = create_driver(test_params[:config])
584
+ d.emit(test_params[:field_name] => hash_value)
585
+ d.run
586
+ end
587
+ if test_params[:expected_payload] == 'textPayload'
588
+ verify_log_entries(1, COMPUTE_PARAMS, 'textPayload') do |entry|
589
+ text_payload = entry['textPayload']
590
+ assert_equal '{"msg"=>"test log entry 0", "tag2"=>"test", ' \
591
+ '"data"=>5000, "some_null_field"=>nil}',
592
+ text_payload, entry
593
+ end
594
+ else
595
+ verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
596
+ json_payload = get_fields(entry['jsonPayload'])
597
+ assert_equal 1, json_payload.size, entry
598
+ fields = get_fields(
599
+ get_struct(json_payload[test_params[:field_name]]))
600
+ assert_equal 4, fields.size, entry
601
+ assert_equal 'test log entry 0', get_string(fields['msg']), entry
602
+ assert_equal 'test', get_string(fields['tag2']), entry
603
+ assert_equal 5000, get_number(fields['data']), entry
604
+ assert_equal null_value, fields['some_null_field'], entry
605
+ end
606
+ end
607
+ end
608
+ end
609
+ end
610
+
539
611
  def test_structured_payload_json_log_detect_json_parsed
540
612
  setup_gce_metadata_stubs
541
613
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
@@ -1442,6 +1514,15 @@ module BaseTest
1442
1514
  sample_value: TRACE)
1443
1515
  end
1444
1516
 
1517
+ def test_log_entry_trace_sampled_field
1518
+ verify_field_key('traceSampled',
1519
+ default_key: DEFAULT_TRACE_SAMPLED_KEY,
1520
+ custom_key: 'custom_trace_sampled_key',
1521
+ custom_key_config:
1522
+ CONFIG_CUSTOM_TRACE_SAMPLED_KEY_SPECIFIED,
1523
+ sample_value: TRACE_SAMPLED)
1524
+ end
1525
+
1445
1526
  # Verify the cascading JSON detection of LogEntry fields.
1446
1527
 
1447
1528
  def test_cascading_json_detection_with_log_entry_insert_id_field
@@ -1490,6 +1571,15 @@ module BaseTest
1490
1571
  nested_level_value: TRACE2)
1491
1572
  end
1492
1573
 
1574
+ def test_cascading_json_detection_with_log_entry_trace_sampled_field
1575
+ verify_cascading_json_detection_with_log_entry_fields(
1576
+ 'traceSampled', DEFAULT_TRACE_SAMPLED_KEY,
1577
+ root_level_value: TRACE_SAMPLED,
1578
+ nested_level_value: TRACE_SAMPLED2,
1579
+ default_value_from_root: false,
1580
+ default_value_from_nested: false)
1581
+ end
1582
+
1493
1583
  # Verify that labels present in multiple inputs respect the expected priority
1494
1584
  # order:
1495
1585
  # 1. Labels from the field "logging.googleapis.com/labels" in payload.
@@ -2506,6 +2596,10 @@ module BaseTest
2506
2596
  :expected_value_from_root, root_level_value)
2507
2597
  expected_value_from_nested = expectation.fetch(
2508
2598
  :expected_value_from_nested, nested_level_value)
2599
+ default_value_from_root = expectation.fetch(
2600
+ :default_value_from_root, nil)
2601
+ default_value_from_nested = expectation.fetch(
2602
+ :default_value_from_nested, nil)
2509
2603
 
2510
2604
  setup_gce_metadata_stubs
2511
2605
 
@@ -2543,21 +2637,34 @@ module BaseTest
2543
2637
  log_entry_with_both_level_fields = log_entry_with_nested_level_field.merge(
2544
2638
  default_key => root_level_value)
2545
2639
 
2546
- {
2547
- log_entry_with_root_level_field => expected_value_from_root,
2548
- log_entry_with_nested_level_field => expected_value_from_nested,
2549
- log_entry_with_both_level_fields => expected_value_from_nested
2550
- }.each_with_index do |(input_log_entry, expected_value), index|
2640
+ [
2641
+ [
2642
+ log_entry_with_root_level_field,
2643
+ expected_value_from_root,
2644
+ default_value_from_root
2645
+ ],
2646
+ [
2647
+ log_entry_with_nested_level_field,
2648
+ expected_value_from_nested,
2649
+ default_value_from_nested
2650
+ ],
2651
+ [
2652
+ log_entry_with_both_level_fields,
2653
+ expected_value_from_nested,
2654
+ default_value_from_nested
2655
+ ]
2656
+ ].each_with_index do |(log_entry, expected_value, default_value), index|
2551
2657
  setup_logging_stubs do
2552
2658
  @logs_sent = []
2553
2659
  d = create_driver(DETECT_JSON_CONFIG)
2554
- d.emit(input_log_entry)
2660
+ d.emit(log_entry)
2555
2661
  d.run
2556
2662
  end
2557
2663
  verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload', false) do |entry|
2558
- assert_equal expected_value, entry[log_entry_field],
2559
- "Index #{index} failed. #{expected_value} is expected" \
2560
- " for #{log_entry_field} field."
2664
+ assert_equal_with_default \
2665
+ entry[log_entry_field], expected_value, default_value,
2666
+ "Index #{index} failed. #{expected_value} is expected for " \
2667
+ "#{log_entry_field} field."
2561
2668
  payload_fields = get_fields(entry['jsonPayload'])
2562
2669
  assert_equal structured_log_entry.size, payload_fields.size
2563
2670
  payload_fields.each do |key, value|
@@ -99,12 +99,14 @@ module Constants
99
99
  MANAGED_VM_BACKEND_VERSION = 'guestbook2.0'.freeze
100
100
 
101
101
  # LogEntry fields for extraction.
102
- TRACE = 'projects/proj1/traces/1234567890abcdef1234567890abcdef'.freeze
103
- TRACE2 = 'projects/proj1/traces/1234567890abcdef1234567890fedcba'.freeze
104
- SPAN_ID = '000000000000004a'.freeze
105
- SPAN_ID2 = '000000000000007e'.freeze
106
102
  INSERT_ID = 'fah7yr7iw64tg857y'.freeze
107
103
  INSERT_ID2 = 'fah7yr7iw64tgaeuf'.freeze
104
+ SPAN_ID = '000000000000004a'.freeze
105
+ SPAN_ID2 = '000000000000007e'.freeze
106
+ TRACE = 'projects/proj1/traces/1234567890abcdef1234567890abcdef'.freeze
107
+ TRACE2 = 'projects/proj1/traces/1234567890abcdef1234567890fedcba'.freeze
108
+ TRACE_SAMPLED = true
109
+ TRACE_SAMPLED2 = false
108
110
 
109
111
  STACKDRIVER_TRACE_ID = '1234567890abcdef1234567890abcdef'.freeze
110
112
  FULL_STACKDRIVER_TRACE = \
@@ -396,6 +398,10 @@ module Constants
396
398
  trace_key custom_trace_key
397
399
  ).freeze
398
400
 
401
+ CONFIG_CUSTOM_TRACE_SAMPLED_KEY_SPECIFIED = %(
402
+ trace_sampled_key custom_trace_sampled_key
403
+ ).freeze
404
+
399
405
  # For 'labels' config.
400
406
  LABELS_FROM_LABELS_CONFIG = {
401
407
  'a_label_from_labels_config' => 'some_value',
@@ -1106,6 +1112,7 @@ module Constants
1106
1112
  DEFAULT_OPERATION_KEY => OPERATION_MESSAGE,
1107
1113
  DEFAULT_SOURCE_LOCATION_KEY => SOURCE_LOCATION_MESSAGE,
1108
1114
  DEFAULT_SPAN_ID_KEY => SPAN_ID,
1109
- DEFAULT_TRACE_KEY => TRACE
1115
+ DEFAULT_TRACE_KEY => TRACE,
1116
+ DEFAULT_TRACE_SAMPLED_KEY => TRACE_SAMPLED
1110
1117
  }.freeze
1111
1118
  end
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.7.5
4
+ version: 0.7.6
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: 2019-02-17 00:00:00.000000000 Z
11
+ date: 2019-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.23.9
61
+ version: 0.28.4
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.23.9
68
+ version: 0.28.4
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: google-cloud-logging
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 1.5.4
75
+ version: 1.6.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 1.5.4
82
+ version: 1.6.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: google-protobuf
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 1.8.3
103
+ version: 1.14.2
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 1.8.3
110
+ version: 1.14.2
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: json
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -260,7 +260,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
260
260
  version: '0'
261
261
  requirements: []
262
262
  rubyforge_project:
263
- rubygems_version: 2.7.8
263
+ rubygems_version: 2.7.9
264
264
  signing_key:
265
265
  specification_version: 4
266
266
  summary: fluentd plugins for the Stackdriver Logging API