fluent-plugin-google-cloud 0.5.3.grpc.alpha.4 → 0.5.3.grpc.alpha.5

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
  SHA1:
3
- metadata.gz: 29718f443dea67bcf817ee44390e61373a307db7
4
- data.tar.gz: 54b6472916c8657230db649ff339ab1d31b5362d
3
+ metadata.gz: af37e8c845023885ae3cec2dcef35368f30e7ee3
4
+ data.tar.gz: 57cd2c566bb2c89ee063dbb12fbd02a75e8744c9
5
5
  SHA512:
6
- metadata.gz: 1d5695d8834eafc6f059c5a591ff9d3188739814fd7dcc4e2dc976324c8e45f3b5f0b7d914062c9581b2242f76dfd75d0356178c5a6b7f2cbadd3d49b064ec61
7
- data.tar.gz: 46c8d492364314a4220f3ea61a81814fbd9db64c3af06331e025853582404d33806a5bcacc7be64379aa2a646f415d5e6507e6fcae6d95085fafe838b4f5e19a
6
+ metadata.gz: c8ca9cfcb3c564822cfd06870010e21358352612a401bdfda9c0d49f4715f9a0831e3daab338a69d9b584a2b568255aa2bae35e512771cfb837de74b64712be0
7
+ data.tar.gz: 43fa64e97398e3526a6153db587806b9a56291c330b6b066f5a7a106abf769c040cd4bb6a849a4d6bf7b8ba65427dc1a3b5cd5ff3a3ed156ee01e56f790005cf
@@ -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.5.3.grpc.alpha.4'
13
+ gem.version = '0.5.3.grpc.alpha.5'
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')
@@ -39,7 +39,7 @@ module Fluent
39
39
  Fluent::Plugin.register_output('google_cloud', self)
40
40
 
41
41
  PLUGIN_NAME = 'Fluentd Google Cloud Logging plugin'
42
- PLUGIN_VERSION = '0.5.3.grpc.alpha.4'
42
+ PLUGIN_VERSION = '0.5.3.grpc.alpha.5'
43
43
 
44
44
  # Constants for service names.
45
45
  APPENGINE_SERVICE = 'appengine.googleapis.com'
@@ -599,338 +599,6 @@ module Fluent
599
599
  end
600
600
  end
601
601
 
602
- # def old_write(chunk)
603
- # # Group the entries since we have to make one call per tag.
604
- # grouped_entries = {}
605
- # chunk.msgpack_each do |tag, *arr|
606
- # grouped_entries[tag] = [] unless grouped_entries.key?(tag)
607
- # grouped_entries[tag].push(arr)
608
- # end
609
- #
610
- # grouped_entries.each do |tag, arr|
611
- # entries = []
612
- # labels = @common_labels.clone
613
- #
614
- # if @running_cloudfunctions
615
- # # If the current group of entries is coming from a Cloud Functions
616
- # # function, the function name can be extracted from the tag.
617
- # match_data = @cloudfunctions_tag_regexp.match(tag)
618
- # if match_data
619
- # # Service name is set to Cloud Functions only for logs actually
620
- # # coming from a function.
621
- # @service_name = CLOUDFUNCTIONS_SERVICE
622
- # labels["#{CLOUDFUNCTIONS_SERVICE}/region"] = @gcf_region
623
- # labels["#{CLOUDFUNCTIONS_SERVICE}/function_name"] =
624
- # decode_cloudfunctions_function_name(
625
- # match_data['encoded_function_name'])
626
- # else
627
- # # Other logs are considered as coming from the Container Engine
628
- # # service.
629
- # @service_name = CONTAINER_SERVICE
630
- # end
631
- # end
632
- # if @service_name == CONTAINER_SERVICE && \
633
- # @compiled_kubernetes_tag_regexp
634
- # # Container logs in Kubernetes are tagged based on where they came
635
- # # from, so we can extract useful metadata from the tag.
636
- # # Do this here to avoid having to repeat it for each record.
637
- # match_data = @compiled_kubernetes_tag_regexp.match(tag)
638
- # if match_data
639
- # %w(namespace_name pod_name container_name).each do |field|
640
- # labels["#{CONTAINER_SERVICE}/#{field}"] = match_data[field]
641
- # end
642
- # end
643
- # end
644
- #
645
- # if @use_grpc
646
- # arr.each do |time, record|
647
- # next unless record.is_a?(Hash)
648
- #
649
- # entry = Google::Logging::V1::LogEntry.new(
650
- # metadata: Google::Logging::V1::LogEntryMetadata.new(
651
- # service_name: @service_name.encode('utf-8'),
652
- # project_id: @project_id.encode('utf-8'),
653
- # zone: @zone.encode('utf-8'),
654
- # labels: {}
655
- # ))
656
- #
657
- # if @service_name == CLOUDFUNCTIONS_SERVICE && record.key?('log')
658
- # @cloudfunctions_log_match =
659
- # @cloudfunctions_log_regexp.match(record['log'])
660
- # end
661
- # if @service_name == CONTAINER_SERVICE
662
- # # Move the stdout/stderr annotation from the record into a
663
- # # label.
664
- # field_to_label(record, 'stream', entry.metadata.labels,
665
- # "#{CONTAINER_SERVICE}/stream")
666
- # # If the record has been annotated by the
667
- # # kubernetes_metadata_filter
668
- # # plugin, then use that metadata. Otherwise, rely on
669
- # # commonLabels
670
- # # populated at the grouped_entries level from the group's tag.
671
- # if record.key?('kubernetes')
672
- # handle_container_metadata(record, entry)
673
- # end
674
- #
675
- # # Save the timestamp if available, then clear it out to allow
676
- # # for determining whether we should parse the log or message
677
- # # field.
678
- # timestamp = record.key?('time') ? record['time'] : nil
679
- # record.delete('time')
680
- # # If the log is json, we want to export it as a structured log
681
- # # unless there is additional metadata that would be lost.
682
- # is_json = false
683
- # if record.length == 1 && record.key?('log')
684
- # record_json = parse_json_or_nil(record['log'])
685
- # end
686
- # if record.length == 1 && record.key?('message')
687
- # record_json = parse_json_or_nil(record['message'])
688
- # end
689
- # unless record_json.nil?
690
- # record = record_json
691
- # is_json = true
692
- # end
693
- # # Restore timestamp if necessary.
694
- # unless record.key?('time') || timestamp.nil?
695
- # record['time'] = timestamp
696
- # end
697
- # end
698
- #
699
- # ts_secs, ts_nanos = compute_timestamp(record, time)
700
- # entry.metadata.timestamp = Google::Protobuf::Timestamp.new(
701
- # seconds: ts_secs,
702
- # nanos: ts_nanos
703
- # )
704
- #
705
- # entry.metadata.severity =
706
- # grpc_severity(compute_severity(record, entry))
707
- #
708
- # set_http_request_grpc(record, entry) # FIXME
709
- #
710
- # # If a field is present in the label_map, send its value as a
711
- # # label
712
- # # (mapping the field name to label name as specified in the
713
- # # config)
714
- # # and do not send that field as part of the payload.
715
- # if @label_map
716
- # @label_map.each do |field, label|
717
- # field_to_label(record, field, entry.metadata.labels, label)
718
- # end
719
- # end
720
- #
721
- # if @service_name == CLOUDFUNCTIONS_SERVICE &&
722
- # @cloudfunctions_log_match &&
723
- # @cloudfunctions_log_match['execution_id']
724
- # entry.metadata.labels['execution_id'] =
725
- # @cloudfunctions_log_match['execution_id']
726
- # end
727
- #
728
- # set_payload_grpc(record, entry, is_json)
729
- #
730
- # entries.push(entry)
731
- # end
732
- # # Don't send an empty request if we rejected all the entries.
733
- # next if entries.empty?
734
- #
735
- # log_name = log_name(tag, labels)
736
- #
737
- # begin
738
- # # Does the actual write to the cloud logging api.
739
- #
740
- # client = api_client
741
- #
742
- # labels_utf8_pairs = labels.map do |k, v|
743
- # [k.encode('utf-8'), v.encode('utf-8')]
744
- # end
745
- #
746
- # write_request = Google::Logging::V1::WriteLogEntriesRequest.new(
747
- # log_name: log_name.encode('utf-8'),
748
- # common_labels: Hash[labels_utf8_pairs],
749
- # entries: entries
750
- # )
751
- #
752
- # client.write_log_entries(write_request)
753
- #
754
- # # Let the user explicitly know when the first call succeeded,
755
- # # to aid with verification and troubleshooting.
756
- # unless @successful_call
757
- # @successful_call = true
758
- # @log.info 'Successfully sent gRPC to Stackdriver Logging API.'
759
- # end
760
- #
761
- # rescue GRPC::Cancelled => error
762
- # # RPC cancelled, so retry via re-raising the error.
763
- # raise error
764
- #
765
- # rescue GRPC::BadStatus => error
766
- # case error.code
767
- # when GRPC::Core::StatusCodes::CANCELLED,
768
- # GRPC::Core::StatusCodes::UNAVAILABLE,
769
- # GRPC::Core::StatusCodes::DEADLINE_EXCEEDED,
770
- # GRPC::Core::StatusCodes::INTERNAL,
771
- # GRPC::Core::StatusCodes::UNKNOWN
772
- # # TODO
773
- # # Server error, so retry via re-raising the error.
774
- # raise error
775
- # when GRPC::Core::StatusCodes::UNIMPLEMENTED,
776
- # GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED
777
- # # Most client errors indicate a problem with the request itself
778
- # # and should not be retried.
779
- # dropped = entries.length
780
- # @log.warn "Dropping #{dropped} log message(s)",
781
- # error: error.to_s, error_code: error.code.to_s
782
- # when GRPC::Core::StatusCodes::UNAUTHENTICATED
783
- # # Authorization error.
784
- # # These are usually solved via a `gcloud auth` call, or by
785
- # # modifying the permissions on the Google Cloud project.
786
- # dropped = entries.length
787
- # @log.warn "Dropping #{dropped} log message(s)",
788
- # error: error.to_s, error_code: error.code.to_s
789
- # else
790
- # @log.error "Unknown response code #{error.code} from the " \
791
- # "server",
792
- # error: error.to_s, error_code: error.code.to_s
793
- # end
794
- # end
795
- # else
796
- # arr.each do |time, record|
797
- # next unless record.is_a?(Hash)
798
- #
799
- # entry = Google::Apis::LoggingV1beta3::LogEntry.new(
800
- # metadata: Google::Apis::LoggingV1beta3::LogEntryMetadata.new(
801
- # service_name: @service_name,
802
- # project_id: @project_id,
803
- # zone: @zone,
804
- # labels: {}
805
- # ))
806
- #
807
- # if @service_name == CLOUDFUNCTIONS_SERVICE && record.key?('log')
808
- # @cloudfunctions_log_match =
809
- # @cloudfunctions_log_regexp.match(record['log'])
810
- # end
811
- # if @service_name == CONTAINER_SERVICE
812
- # # Move the stdout/stderr annotation from the record into a label
813
- # field_to_label(record, 'stream', entry.metadata.labels,
814
- # "#{CONTAINER_SERVICE}/stream")
815
- # # If the record has been annotated by the
816
- # # kubernetes_metadata_filter
817
- # # plugin, then use that metadata. Otherwise, rely on
818
- # # commonLabels
819
- # # populated at the grouped_entries level from the group's tag.
820
- # if record.key?('kubernetes')
821
- # handle_container_metadata(record, entry)
822
- # end
823
- #
824
- # # Save the timestamp if available, then clear it out to allow
825
- # # for determining whether we should parse the log or message
826
- # # field.
827
- # timestamp = record.key?('time') ? record['time'] : nil
828
- # record.delete('time')
829
- # # If the log is json, we want to export it as a structured log
830
- # # unless there is additional metadata that would be lost.
831
- # is_json = false
832
- # if record.length == 1 && record.key?('log')
833
- # record_json = parse_json_or_nil(record['log'])
834
- # end
835
- # if record.length == 1 && record.key?('message')
836
- # record_json = parse_json_or_nil(record['message'])
837
- # end
838
- # unless record_json.nil?
839
- # record = record_json
840
- # is_json = true
841
- # end
842
- # # Restore timestamp if necessary.
843
- # unless record.key?('time') || timestamp.nil?
844
- # record['time'] = timestamp
845
- # end
846
- # end
847
- #
848
- # ts_secs, ts_nanos = compute_timestamp(record, time)
849
- # entry.metadata.timestamp = {
850
- # seconds: ts_secs,
851
- # nanos: ts_nanos
852
- # }
853
- #
854
- # entry.metadata.severity = compute_severity(record, entry)
855
- #
856
- # set_http_request(record, entry)
857
- #
858
- # # If a field is present in the label_map, send its value as a
859
- # # label
860
- # # (mapping the field name to label name as specified in the
861
- # # config)
862
- # # and do not send that field as part of the payload.
863
- # if @label_map
864
- # @label_map.each do |field, label|
865
- # field_to_label(record, field, entry.metadata.labels, label)
866
- # end
867
- # end
868
- #
869
- # if @service_name == CLOUDFUNCTIONS_SERVICE &&
870
- # @cloudfunctions_log_match &&
871
- # @cloudfunctions_log_match['execution_id']
872
- # entry.metadata.labels['execution_id'] =
873
- # @cloudfunctions_log_match['execution_id']
874
- # end
875
- #
876
- # set_payload(record, entry, is_json)
877
- # entry.metadata.labels = nil if entry.metadata.labels.empty?
878
- #
879
- # entries.push(entry)
880
- # end
881
- # # Don't send an empty request if we rejected all the entries.
882
- # next if entries.empty?
883
- #
884
- # log_name = log_name(tag, labels)
885
- #
886
- # begin
887
- # # Does the actual write to the cloud logging api.
888
- # # The URI of the write is constructed by the Google::Api request;
889
- # # it is equivalent to this URL:
890
- # # 'https://logging.googleapis.com/v1beta3/projects/' \
891
- # # "#{@project_id}/logs/#{log_name}/entries:write"
892
- #
893
- # client = api_client
894
- #
895
- # write_request = \
896
- # Google::Apis::LoggingV1beta3::WriteLogEntriesRequest.new(
897
- # common_labels: labels,
898
- # entries: entries)
899
- #
900
- # # TODO: RequestOptions
901
- # client.write_log_entries(@project_id, log_name, write_request)
902
- #
903
- # # Let the user explicitly know when the first call succeeded,
904
- # # to aid with verification and troubleshooting.
905
- # unless @successful_call
906
- # @successful_call = true
907
- # @log.info 'Successfully sent to Stackdriver Logging API.'
908
- # end
909
- #
910
- # rescue Google::Apis::ServerError => error
911
- # # Server error, so retry via re-raising the error.
912
- # raise error
913
- #
914
- # rescue Google::Apis::AuthorizationError => error
915
- # # Authorization error.
916
- # # These are usually solved via a `gcloud auth` call, or by
917
- # # modifying
918
- # # the permissions on the Google Cloud project.
919
- # dropped = entries.length
920
- # @log.warn "Dropping #{dropped} log message(s)",
921
- # error_class: error.class.to_s, error: error.to_s
922
- #
923
- # rescue Google::Apis::ClientError => error
924
- # # Most ClientErrors indicate a problem with the request itself and
925
- # # should not be retried.
926
- # dropped = entries.length
927
- # @log.warn "Dropping #{dropped} log message(s)",
928
- # error_class: error.class.to_s, error: error.to_s
929
- # end
930
- # end
931
- # end
932
- # end
933
-
934
602
  private
935
603
 
936
604
  def parse_json_or_nil(input)
@@ -1159,27 +827,32 @@ module Fluent
1159
827
  return nil unless record['httpRequest'].is_a?(Hash)
1160
828
  input = record['httpRequest']
1161
829
  output = Google::Logging::Type::HttpRequest.new
1162
- output.request_method = input.delete('requestMethod') if
1163
- input.key?('requestMethod')
1164
- output.request_url = input.delete('requestUrl') if
1165
- input.key?('requestUrl')
1166
- output.request_size = input.delete('requestSize').to_i if
1167
- input.key?('requestSize')
1168
- output.status = input.delete('status').to_i if
1169
- input.key?('status')
1170
- output.response_size = input.delete('responseSize').to_i if
1171
- input.key?('responseSize')
1172
- output.user_agent = input.delete('userAgent') if
1173
- input.key?('userAgent')
1174
- output.remote_ip = input.delete('remoteIp') if
1175
- input.key?('remoteIp')
1176
- output.referer = input.delete('referer') if
1177
- input.key?('referer')
1178
- output.cache_hit = input.delete('cacheHit') if
1179
- input.key?('cacheHit')
830
+ # We need to delete each field from 'httpRequest' even if its value is
831
+ # nil. However we do not want to assign this nil value to proto fields
832
+ # defined as strings / integers.
833
+ request_method = input.delete('requestMethod')
834
+ output.request_method = request_method unless request_method.nil?
835
+ request_url = input.delete('requestUrl')
836
+ output.request_url = request_url unless request_url.nil?
837
+ request_size = input.delete('requestSize')
838
+ output.request_size = request_size.to_i unless request_size.nil?
839
+ status = input.delete('status')
840
+ output.status = status.to_i unless status.nil?
841
+ response_size = input.delete('responseSize')
842
+ output.response_size = response_size.to_i unless response_size.nil?
843
+ user_agent = input.delete('userAgent')
844
+ output.user_agent = user_agent unless user_agent.nil?
845
+ remote_ip = input.delete('remoteIp')
846
+ output.remote_ip = remote_ip unless remote_ip.nil?
847
+ referer = input.delete('referer')
848
+ output.referer = referer unless referer.nil?
849
+ cache_hit = input.delete('cacheHit')
850
+ output.cache_hit = cache_hit unless cache_hit.nil?
851
+ cache_validated_with_origin_server = \
852
+ input.delete('cacheValidatedWithOriginServer')
1180
853
  output.cache_validated_with_origin_server = \
1181
- input.delete('cacheValidatedWithOriginServer') if
1182
- input.key?('cacheValidatedWithOriginServer')
854
+ cache_validated_with_origin_server \
855
+ unless cache_validated_with_origin_server.nil?
1183
856
  record.delete('httpRequest') if input.empty?
1184
857
  entry.http_request = output
1185
858
  end
@@ -307,6 +307,19 @@ module BaseTest
307
307
  }
308
308
  }
309
309
 
310
+ HTTP_REQUEST_MESSAGE = {
311
+ 'requestMethod' => 'POST',
312
+ 'requestUrl' => 'http://example/',
313
+ 'requestSize' => 210,
314
+ 'status' => 200,
315
+ 'responseSize' => 65,
316
+ 'userAgent' => 'USER AGENT 1.0',
317
+ 'remoteIp' => '55.55.55.55',
318
+ 'referer' => 'http://referer/',
319
+ 'cacheHit' => true,
320
+ 'cacheValidatedWithOriginServer' => true
321
+ }
322
+
310
323
  # Shared tests.
311
324
 
312
325
  def test_configure_service_account_application_default
@@ -517,15 +530,17 @@ module BaseTest
517
530
  setup_gce_metadata_stubs
518
531
  setup_logging_stubs do
519
532
  d = create_driver
520
- d.emit('msg' => log_entry(0), 'tag2' => 'test', 'data' => 5000)
533
+ d.emit('msg' => log_entry(0), 'tag2' => 'test', 'data' => 5000,
534
+ 'some_null_field' => nil)
521
535
  d.run
522
536
  end
523
537
  verify_log_entries(1, COMPUTE_PARAMS, 'structPayload') do |entry|
524
538
  fields = get_fields(entry['structPayload'])
525
- assert_equal 3, fields.size, entry
539
+ assert_equal 4, fields.size, entry
526
540
  assert_equal 'test log entry 0', get_string(fields['msg']), entry
527
541
  assert_equal 'test', get_string(fields['tag2']), entry
528
542
  assert_equal 5000, get_number(fields['data']), entry
543
+ assert_equal null_value, fields['some_null_field'], entry
529
544
  end
530
545
  end
531
546
 
@@ -550,7 +565,8 @@ module BaseTest
550
565
  setup_container_metadata_stubs
551
566
  setup_logging_stubs do
552
567
  d = create_driver(APPLICATION_DEFAULT_CONFIG, CONTAINER_TAG)
553
- json_string = '{"msg": "test log entry 0", "tag2": "test", "data": 5000}'
568
+ json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
569
+ '"data": 5000, "some_null_field": null}'
554
570
  d.emit(container_log_entry_with_metadata('notJSON' + json_string))
555
571
  d.emit(container_log_entry_with_metadata(json_string))
556
572
  d.emit(container_log_entry_with_metadata(" \r\n \t" + json_string))
@@ -565,10 +581,11 @@ module BaseTest
565
581
  else
566
582
  assert entry.key?('structPayload'), 'Entry did not have structPayload'
567
583
  fields = get_fields(entry['structPayload'])
568
- assert_equal 3, fields.size, entry
584
+ assert_equal 4, fields.size, entry
569
585
  assert_equal 'test log entry 0', get_string(fields['msg']), entry
570
586
  assert_equal 'test', get_string(fields['tag2']), entry
571
587
  assert_equal 5000, get_number(fields['data']), entry
588
+ assert_equal null_value, fields['some_null_field'], entry
572
589
  end
573
590
  end
574
591
  end
@@ -1025,20 +1042,6 @@ module BaseTest
1025
1042
  end
1026
1043
  end
1027
1044
 
1028
- def test_http_request_without_referer_from_record
1029
- setup_gce_metadata_stubs
1030
- setup_logging_stubs do
1031
- d = create_driver
1032
- d.emit('httpRequest' => http_request_message_without_referer)
1033
- d.run
1034
- end
1035
- verify_log_entries(1, COMPUTE_PARAMS, 'httpRequest') do |entry|
1036
- assert_equal http_request_message_without_referer, entry['httpRequest'],
1037
- entry
1038
- assert_nil get_fields(entry['structPayload'])['httpRequest'], entry
1039
- end
1040
- end
1041
-
1042
1045
  def test_http_request_when_not_hash
1043
1046
  setup_gce_metadata_stubs
1044
1047
  setup_logging_stubs do
@@ -1241,6 +1244,16 @@ module BaseTest
1241
1244
  assert i == n, "Number of entries #{i} does not match expected number #{n}"
1242
1245
  end
1243
1246
 
1247
+ # The http request message to test against.
1248
+ def http_request_message
1249
+ HTTP_REQUEST_MESSAGE
1250
+ end
1251
+
1252
+ # Replace the 'referer' field with nil.
1253
+ def http_request_message_with_nil_referer
1254
+ http_request_message.merge('referer' => nil)
1255
+ end
1256
+
1244
1257
  # This module expects the methods below to be overridden.
1245
1258
 
1246
1259
  # Create a Fluentd output test driver with the Google Cloud Output plugin.
@@ -1269,19 +1282,6 @@ module BaseTest
1269
1282
  _undefined
1270
1283
  end
1271
1284
 
1272
- # A wrapper around the constant HTTP_REQUEST_MESSAGE, so the definition can be
1273
- # skipped in the shared module here and defined in the test class later.
1274
- def http_request_message
1275
- _undefined
1276
- end
1277
-
1278
- # A wrapper around the constant HTTP_REQUEST_MESSAGE_WITHOUT_REFERER, so the
1279
- # definition can be skipped in the shared module and defined in the test
1280
- # classes later.
1281
- def http_request_message_without_referer
1282
- _undefined
1283
- end
1284
-
1285
1285
  # Get the fields of the struct payload.
1286
1286
  def get_fields(_struct_payload)
1287
1287
  _undefined
@@ -1302,6 +1302,11 @@ module BaseTest
1302
1302
  _undefined
1303
1303
  end
1304
1304
 
1305
+ # The null value.
1306
+ def null_value(_field)
1307
+ _undefined
1308
+ end
1309
+
1305
1310
  def _undefined
1306
1311
  fail "Method #{__callee__} is unimplemented and needs to be overridden."
1307
1312
  end
@@ -70,6 +70,24 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
70
70
  assert_equal 1, exception_count
71
71
  end
72
72
 
73
+ def test_http_request_from_record_with_referer_nil
74
+ setup_gce_metadata_stubs
75
+ setup_logging_stubs do
76
+ d = create_driver
77
+ d.emit('httpRequest' => http_request_message_with_nil_referer)
78
+ d.run
79
+ end
80
+ verify_log_entries(1, COMPUTE_PARAMS, 'httpRequest') do |entry|
81
+ # The request we send to Logging API has json like:
82
+ # "httpRequest": { "referer": null }, but eventually the stored LogEntry
83
+ # would be "httpRequest": {}, since 'referer' is defined as a string in
84
+ # the proto.
85
+ assert_equal http_request_message_with_nil_referer,
86
+ entry['httpRequest'], entry
87
+ assert_nil get_fields(entry['structPayload'])['httpRequest'], entry
88
+ end
89
+ end
90
+
73
91
  # This test looks similar between the grpc and non-grpc paths except that when
74
92
  # parsing "105", the grpc path responds with "DEBUG", while the non-grpc path
75
93
  # responds with "100".
@@ -175,25 +193,16 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
175
193
 
176
194
  private
177
195
 
178
- # The non-grpc path has a unique field 'validatedWithOriginServer', while
179
- # the grpc path has a unique field 'cacheValidatedWithOriginServer'.
180
- HTTP_REQUEST_MESSAGE = {
181
- 'requestMethod' => 'POST',
182
- 'requestUrl' => 'http://example/',
183
- 'requestSize' => 210,
184
- 'status' => 200,
185
- 'responseSize' => 65,
186
- 'userAgent' => 'USER AGENT 1.0',
187
- 'remoteIp' => '55.55.55.55',
188
- 'referer' => 'http://referer/',
189
- 'cacheHit' => false,
190
- 'validatedWithOriginServer' => true
191
- }
192
-
193
- # In the non-grpc path 'referer' is nil, while in the grpc path 'referer' is
194
- # absent.
195
- HTTP_REQUEST_MESSAGE_WITHOUT_REFERER = HTTP_REQUEST_MESSAGE.merge(
196
- 'referer' => nil)
196
+ def rename_key(hash, old_key, new_key)
197
+ hash.merge(new_key => hash[old_key]).reject { |k, _| k == old_key }
198
+ end
199
+
200
+ # The REST path uses old bindings that were generated prior to the field
201
+ # rename, and has to use the old name, which is 'validatedWithOriginServer'.
202
+ def http_request_message
203
+ rename_key(super, 'cacheValidatedWithOriginServer',
204
+ 'validatedWithOriginServer')
205
+ end
197
206
 
198
207
  # Set up http stubs to mock the external calls.
199
208
  def setup_logging_stubs
@@ -234,18 +243,6 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
234
243
  end
235
244
  end
236
245
 
237
- # A wrapper around the constant HTTP_REQUEST_MESSAGE, so the definition can be
238
- # skipped in the shared module and defined here.
239
- def http_request_message
240
- HTTP_REQUEST_MESSAGE
241
- end
242
-
243
- # A wrapper around the constant HTTP_REQUEST_MESSAGE_WITHOUT_REFERER, so the
244
- # definition can be skipped in the shared module and defined here.
245
- def http_request_message_without_referer
246
- HTTP_REQUEST_MESSAGE_WITHOUT_REFERER
247
- end
248
-
249
246
  # Get the fields of the struct payload.
250
247
  def get_fields(struct_payload)
251
248
  struct_payload
@@ -265,4 +262,9 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
265
262
  def get_number(field)
266
263
  field
267
264
  end
265
+
266
+ # The null value.
267
+ def null_value
268
+ nil
269
+ end
268
270
  end
@@ -72,6 +72,34 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
72
72
  end
73
73
  end
74
74
 
75
+ def test_http_request_from_record_with_referer_nil
76
+ setup_gce_metadata_stubs
77
+ setup_logging_stubs do
78
+ d = create_driver
79
+ d.emit('httpRequest' => http_request_message_with_nil_referer)
80
+ d.run
81
+ end
82
+ verify_log_entries(1, COMPUTE_PARAMS, 'httpRequest') do |entry|
83
+ assert_equal http_request_message_with_absent_referer,
84
+ entry['httpRequest'], entry
85
+ assert_nil get_fields(entry['structPayload'])['httpRequest'], entry
86
+ end
87
+ end
88
+
89
+ def test_http_request_from_record_with_referer_absent
90
+ setup_gce_metadata_stubs
91
+ setup_logging_stubs do
92
+ d = create_driver
93
+ d.emit('httpRequest' => http_request_message_with_absent_referer)
94
+ d.run
95
+ end
96
+ verify_log_entries(1, COMPUTE_PARAMS, 'httpRequest') do |entry|
97
+ assert_equal http_request_message_with_absent_referer,
98
+ entry['httpRequest'], entry
99
+ assert_nil get_fields(entry['structPayload'])['httpRequest'], entry
100
+ end
101
+ end
102
+
75
103
  # This test looks similar between the grpc and non-grpc paths except that when
76
104
  # parsing "105", the grpc path responds with "DEBUG", while the non-grpc path
77
105
  # responds with "100".
@@ -114,27 +142,6 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
114
142
  use_grpc true
115
143
  )
116
144
 
117
- # The non-grpc path has a unique field 'validatedWithOriginServer', while
118
- # the grpc path has a unique field 'cacheValidatedWithOriginServer'.
119
- HTTP_REQUEST_MESSAGE = {
120
- 'requestMethod' => 'POST',
121
- 'requestUrl' => 'http://example/',
122
- 'requestSize' => 210,
123
- 'status' => 200,
124
- 'responseSize' => 65,
125
- 'userAgent' => 'USER AGENT 1.0',
126
- 'remoteIp' => '55.55.55.55',
127
- 'referer' => 'http://referer/',
128
- 'cacheHit' => true,
129
- 'cacheValidatedWithOriginServer' => true
130
- }
131
-
132
- # In the non-grpc path 'referer' is nil, while in the grpc path 'referer' is
133
- # absent.
134
- HTTP_REQUEST_MESSAGE_WITHOUT_REFERER = HTTP_REQUEST_MESSAGE.reject do |k, _|
135
- k == 'referer'
136
- end
137
-
138
145
  # Create a Fluentd output test driver with the Google Cloud Output plugin with
139
146
  # grpc enabled. The signature of this method is different between the grpc
140
147
  # path and the non-grpc path. For grpc, an additional grpc stub class can be
@@ -275,16 +282,11 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
275
282
  end
276
283
  end
277
284
 
278
- # A wrapper around the constant HTTP_REQUEST_MESSAGE, so the definition can be
279
- # skipped in the shared module and defined here.
280
- def http_request_message
281
- HTTP_REQUEST_MESSAGE
282
- end
283
-
284
- # A wrapper around the constant HTTP_REQUEST_MESSAGE_WITHOUT_REFERER, so the
285
- # definition can be skipped in the shared module and defined here.
286
- def http_request_message_without_referer
287
- HTTP_REQUEST_MESSAGE_WITHOUT_REFERER
285
+ # Unset the 'referer' field.
286
+ def http_request_message_with_absent_referer
287
+ http_request_message.reject do |k, _|
288
+ k == 'referer'
289
+ end
288
290
  end
289
291
 
290
292
  # Get the fields of the struct payload.
@@ -306,4 +308,9 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
306
308
  def get_number(field)
307
309
  field['numberValue']
308
310
  end
311
+
312
+ # The null value.
313
+ def null_value
314
+ { 'nullValue' => 'NULL_VALUE' }
315
+ end
309
316
  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.5.3.grpc.alpha.4
4
+ version: 0.5.3.grpc.alpha.5
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: 2016-12-12 00:00:00.000000000 Z
12
+ date: 2016-12-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd