fluent-plugin-oci-logging-analytics 2.0.0 → 2.0.4

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
- SHA256:
3
- metadata.gz: dde9a7a3e6be01a2556efa148f43934c2c723ffce544d3c11af1c50fe46f06b7
4
- data.tar.gz: b442ff6c28ef6bc1c3ddc6d74c6b48e30c9921902607f9581c0aa116e5ba9db2
2
+ SHA1:
3
+ metadata.gz: b2c10b68eefbf373de236156362383500f9746a9
4
+ data.tar.gz: 6ad63e3893634f360387c68b03248291d787d33f
5
5
  SHA512:
6
- metadata.gz: a106761ec570d6c14435544617bf2357846b022869ef7c6154463b848cf72eeedbc96080a7d819911518818864379655aaa7668c4bad46d4d45a80a10dffc40f
7
- data.tar.gz: dd7fcd53fd707c1c365cd8c5cbe1f4d6612d27b0de201d9ed2e1a98235322b08cdb7c4d15f968fa3bc667175e226cae1022673c36ba6409ee73bbe0e703417aa
6
+ metadata.gz: fcb93cdf4da13e23101127320bec26bb96ac3426e2fe34402591febfc1e0ab8494a253e8c089f0bcd13aafea35b740ea353ee164213d89d415fe93a07d8764e2
7
+ data.tar.gz: 83115a796e9baf6311c3d3da4f9f137fdbd4cbb74bb52f10a3686cc8441f26315c38522bb32c1acc06652aaae92bd7a1adff643f555df91de11a4b1e84487355
@@ -1,3 +1,5 @@
1
+ ## Copyright (c) 2021, 2022 Oracle and/or its affiliates.
2
+ ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
1
3
 
2
4
  class LogEvents
3
5
  attr_accessor :entityId, :entityType, :logSourceName, :logPath, :logRecords , :metadata
@@ -1,3 +1,5 @@
1
+ ## Copyright (c) 2021, 2022 Oracle and/or its affiliates.
2
+ ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
1
3
 
2
4
  require_relative './logEvents'
3
5
 
@@ -1,11 +1,13 @@
1
1
  class MetricsLabels
2
- attr_accessor :tag, :logGroupId, :logSourceName, :logSet, :drop_reason, :records_valid
2
+ attr_accessor :tag, :logGroupId, :logSourceName, :logSet, :invalid_reason, :records_valid, :records_per_tag, :latency
3
3
  def initialize
4
4
  @tag = nil
5
5
  @logGroupId = nil
6
6
  @logSourceName = nil
7
7
  @logSet = nil
8
- @drop_reason = nil
8
+ @invalid_reason = nil
9
9
  @records_valid = 0
10
+ @records_per_tag = 0
11
+ @latency = 0
10
12
  end
11
13
  end
@@ -6,36 +6,36 @@ require 'singleton'
6
6
 
7
7
  class PrometheusMetrics
8
8
  include Singleton
9
- attr_accessor :records_received, :records_valid, :records_dropped, :records_error, :records_posted,
10
- :bytes_received, :bytes_posted, :latency_avg, :chunk_upload_time_taken
9
+ attr_accessor :records_received, :records_valid, :records_invalid, :records_error, :records_posted,
10
+ :bytes_received, :bytes_posted, :chunk_time_to_receive, :chunk_time_to_upload
11
11
  def initialize
12
12
  createMetrics
13
13
  registerMetrics
14
14
  end
15
15
  def createMetrics
16
16
  gauge = Prometheus::Client::Gauge
17
- @records_received = gauge.new(:oci_logging_analytics_records_received, docstring: '...', labels: [:tag,:logGroupId,:logSourceName,:logSet])
18
- @records_valid = gauge.new(:oci_logging_analytics_records_valid, docstring: '...', labels: [:tag,:logGroupId,:logSourceName,:logSet])
19
- @records_dropped = gauge.new(:oci_logging_analytics_records_dropped, docstring: '...', labels: [:tag,:logGroupId,:logSourceName,:logSet,:drop_reason])
20
- @records_error = gauge.new(:oci_logging_analytics_records_error, docstring: '...', labels: [:tag,:logGroupId,:logSourceName,:logSet,:error_code, :error_reason])
21
- @records_posted = gauge.new(:oci_logging_analytics_records_posted, docstring: '...', labels: [:tag,:logGroupId,:logSourceName,:logSet])
22
- @bytes_received = gauge.new(:oci_logging_analytics_bytes_received, docstring: '...', labels: [:tag])
23
- @bytes_posted = gauge.new(:oci_logging_analytics_bytes_posted, docstring: '...', labels: [:logGroupId])
17
+ @records_received = gauge.new(:oci_la_fluentd_output_plugin_records_received, docstring: 'Number of records received by the OCI Logging Analytics Fluentd output plugin.', labels: [:tag,:oci_la_log_group_id,:oci_la_log_source_name,:oci_la_log_set])
18
+ @records_valid = gauge.new(:oci_la_fluentd_output_plugin_records_valid, docstring: 'Number of valid records received by the OCI Logging Analytics Fluentd output plugin.', labels: [:tag,:oci_la_log_group_id,:oci_la_log_source_name,:oci_la_log_set])
19
+ @records_invalid = gauge.new(:oci_la_fluentd_output_plugin_records_invalid, docstring: 'Number of invalid records received by the OCI Logging Analytics Fluentd output plugin.', labels: [:tag,:oci_la_log_group_id,:oci_la_log_source_name,:oci_la_log_set,:reason])
20
+ @records_error = gauge.new(:oci_la_fluentd_output_plugin_records_post_error, docstring: 'Number of records failed posting to OCI Logging Analytics by the Fluentd output plugin.', labels: [:tag,:oci_la_log_group_id,:oci_la_log_source_name,:oci_la_log_set,:error_code, :reason])
21
+ @records_posted = gauge.new(:oci_la_fluentd_output_plugin_records_post_success, docstring: 'Number of records posted by the OCI Logging Analytics Fluentd output plugin.', labels: [:tag,:oci_la_log_group_id,:oci_la_log_source_name,:oci_la_log_set])
22
+ #@bytes_received = gauge.new(:oci_la_bytes_received, docstring: '...', labels: [:tag])
23
+ #@bytes_posted = gauge.new(:oci_la_bytes_posted, docstring: '...', labels: [:oci_la_log_group_id])
24
24
  histogram = Prometheus::Client::Histogram
25
- @latency_avg = histogram.new(:oci_logging_analytics_network_latency_avg, docstring: '...', labels: [:tag])
26
- @chunk_upload_time_taken = histogram.new(:oci_logging_analytics_chunk_upload_time_taken, docstring: '...', labels: [:logGroupId])
25
+ @chunk_time_to_receive = histogram.new(:oci_la_fluentd_output_plugin_chunk_time_to_receive, docstring: 'Average time taken by Fluentd to deliver the collected records from Input plugin to OCI Logging Analytics output plugin.', labels: [:tag])
26
+ @chunk_time_to_upload = histogram.new(:oci_la_fluentd_output_plugin_chunk_time_to_post, docstring: 'Average time taken for posting the received records to OCI Logging Analytics by the Fluentd output plugin.', labels: [:oci_la_log_group_id])
27
27
  end
28
28
 
29
29
  def registerMetrics
30
30
  registry = Prometheus::Client.registry
31
- registry.register(@records_received) unless registry.exist?('oci_logging_analytics_records_received')
32
- registry.register(@records_valid) unless registry.exist?('oci_logging_analytics_records_valid')
33
- registry.register(@records_dropped) unless registry.exist?('oci_logging_analytics_records_dropped')
34
- registry.register(@records_error) unless registry.exist?('oci_logging_analytics_records_error')
35
- registry.register(@records_posted) unless registry.exist?('oci_logging_analytics_records_posted')
36
- registry.register(@bytes_received) unless registry.exist?('oci_logging_analytics_bytes_received')
37
- registry.register(@bytes_posted) unless registry.exist?('oci_logging_analytics_bytes_valid')
38
- registry.register(@latency_avg) unless registry.exist?('oci_logging_analytics_network_latency_avg')
39
- registry.register(@chunk_upload_time_taken) unless registry.exist?('oci_logging_analytics_chunk_upload_time_taken')
31
+ registry.register(@records_received) unless registry.exist?('oci_la_fluentd_output_plugin_records_received')
32
+ registry.register(@records_valid) unless registry.exist?('oci_la_fluentd_output_plugin_records_valid')
33
+ registry.register(@records_invalid) unless registry.exist?('oci_la_fluentd_output_plugin_records_invalid')
34
+ registry.register(@records_error) unless registry.exist?('oci_la_fluentd_output_plugin_records_post_error')
35
+ registry.register(@records_posted) unless registry.exist?('oci_la_fluentd_output_plugin_records_post_success')
36
+ #registry.register(@bytes_received) unless registry.exist?('oci_la_bytes_received')
37
+ #registry.register(@bytes_posted) unless registry.exist?('oci_la_bytes_valid')
38
+ registry.register(@chunk_time_to_receive) unless registry.exist?('oci_la_fluentd_output_plugin_chunk_time_to_receive')
39
+ registry.register(@chunk_time_to_upload) unless registry.exist?('oci_la_fluentd_output_plugin_chunk_time_to_post')
40
40
  end
41
41
  end
@@ -1,13 +1,53 @@
1
- ## Copyright (c) 2021 Oracle and/or its affiliates.
1
+ ## Copyright (c) 2021, 2022 Oracle and/or its affiliates.
2
2
  ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
3
 
4
4
  require 'fluent/plugin/output'
5
5
  require "benchmark"
6
6
  require 'zip'
7
- require 'oci'
7
+
8
8
  require 'logger'
9
9
  require_relative '../dto/logEventsJson'
10
10
  require_relative '../dto/logEvents'
11
+ require_relative '../metrics/prometheusMetrics'
12
+ require_relative '../metrics/metricsLabels'
13
+
14
+ # Import only specific OCI modules to improve load times and reduce the memory requirements.
15
+ require 'oci/auth/auth'
16
+ require 'oci/log_analytics/log_analytics'
17
+ require 'oci/log_analytics/log_analytics_client'
18
+
19
+ # Workaround until OCI SDK releases a proper fix to load only specific service related modules/client.
20
+ require 'oci/api_client'
21
+ require 'oci/api_client_proxy_settings'
22
+ require 'oci/config'
23
+ require 'oci/config_file_loader'
24
+ require 'oci/errors'
25
+ require 'oci/global_context'
26
+ require 'oci/internal/internal'
27
+ require 'oci/regions'
28
+ require 'oci/regions_definitions'
29
+ require 'oci/response_headers'
30
+ require 'oci/response'
31
+ require 'oci/base_signer'
32
+ require 'oci/signer'
33
+ require 'oci/version'
34
+ require 'oci/waiter'
35
+ require 'oci/retry/retry'
36
+ require 'oci/object_storage/object_storage'
37
+
38
+ module OCI
39
+ class << self
40
+ attr_accessor :sdk_name
41
+
42
+ # Defines the logger used for debugging for the OCI module.
43
+ # For example, log to STDOUT by setting this to Logger.new(STDOUT).
44
+ #
45
+ # @return [Logger]
46
+ attr_accessor :logger
47
+ end
48
+ end
49
+
50
+ OracleBMC = OCI
11
51
 
12
52
  module Fluent::Plugin
13
53
  class OutOracleOCILogAnalytics < Output
@@ -15,8 +55,25 @@ module Fluent::Plugin
15
55
  helpers :thread, :event_emitter
16
56
 
17
57
  MAX_FILES_PER_ZIP = 100
58
+ METRICS_INVALID_REASON_MESSAGE = "MISSING_FIELD_MESSAGE"
59
+ METRICS_INVALID_REASON_LOG_GROUP_ID = "MISSING_OCI_LA_LOG_GROUP_ID_FIELD"
60
+ METRICS_INVALID_REASON_LOG_SOURCE_NAME = "MISSING_OCI_LA_LOG_SOURCE_NAME_FIELD"
61
+
62
+ METRICS_SERVICE_ERROR_REASON_400 = "INVALID_PARAMETER"
63
+ METRICS_SERVICE_ERROR_REASON_401 = "AUTHENTICATION_FAILED"
64
+ METRICS_SERVICE_ERROR_REASON_404 = "AUTHORIZATION_FAILED"
65
+ METRICS_SERVICE_ERROR_REASON_429 = "TOO_MANY_REQUESTES"
66
+ METRICS_SERVICE_ERROR_REASON_500 = "INTERNAL_SERVER_ERROR"
67
+ METRICS_SERVICE_ERROR_REASON_502 = "BAD_GATEWAY"
68
+ METRICS_SERVICE_ERROR_REASON_503 = "SERVICE_UNAVAILABLE"
69
+ METRICS_SERVICE_ERROR_REASON_504 = "GATEWAY_TIMEOUT"
70
+ METRICS_SERVICE_ERROR_REASON_505 = "HTTP_VERSION_NOT_SUPPORTED"
71
+ METRICS_SERVICE_ERROR_REASON_UNKNOWN = "UNKNOWN_ERROR"
72
+
73
+
18
74
  @@logger = nil
19
75
  @@loganalytics_client = nil
76
+ @@prometheusMetrics = nil
20
77
  @@logger_config_errors = []
21
78
 
22
79
 
@@ -214,6 +271,7 @@ module Fluent::Plugin
214
271
 
215
272
  def configure(conf)
216
273
  super
274
+ @@prometheusMetrics = PrometheusMetrics.instance
217
275
  initialize_logger
218
276
 
219
277
  initialize_loganalytics_client
@@ -466,32 +524,36 @@ module Fluent::Plugin
466
524
 
467
525
  def is_valid_record(record_hash,record)
468
526
  begin
527
+ invalid_reason = nil
469
528
  if !record_hash.has_key?("message")
529
+ invalid_reason = OutOracleOCILogAnalytics::METRICS_INVALID_REASON_MESSAGE
470
530
  if record_hash.has_key?("tag")
471
531
  @@logger.warn {"Invalid records associated with tag : #{record["tag"]}. 'message' field is not present in the record."}
472
532
  else
473
533
  @@logger.info {"InvalidRecord: #{record}"}
474
534
  @@logger.warn {"Invalid record. 'message' field is not present in the record."}
475
535
  end
476
- return false
536
+ return false,invalid_reason
477
537
  elsif !record_hash.has_key?("oci_la_log_group_id") || !is_valid(record["oci_la_log_group_id"])
538
+ invalid_reason = OutOracleOCILogAnalytics::METRICS_INVALID_REASON_LOG_GROUP_ID
478
539
  if record_hash.has_key?("tag")
479
540
  @@logger.warn {"Invalid records associated with tag : #{record["tag"]}.'oci_la_log_group_id' must not be empty.
480
541
  Skipping all the records associated with the tag"}
481
542
  else
482
543
  @@logger.warn {"Invalid record.'oci_la_log_group_id' must not be empty"}
483
544
  end
484
- return false
545
+ return false,invalid_reason
485
546
  elsif !record_hash.has_key?("oci_la_log_source_name") || !is_valid(record["oci_la_log_source_name"])
547
+ invalid_reason = OutOracleOCILogAnalytics::METRICS_INVALID_REASON_LOG_SOURCE_NAME
486
548
  if record_hash.has_key?("tag")
487
549
  @@logger.warn {"Invalid records associated with tag : #{record["tag"]}.'oci_la_log_source_name' must not be empty.
488
550
  Skipping all the records associated with the tag"}
489
551
  else
490
552
  @@logger.warn {"Invalid record.'oci_la_log_source_name' must not be empty"}
491
553
  end
492
- return false
554
+ return false,invalid_reason
493
555
  else
494
- return true
556
+ return true,invalid_reason
495
557
  end
496
558
  end
497
559
  end
@@ -542,6 +604,11 @@ module Fluent::Plugin
542
604
  current_f, current_s = current.to_f, current.strftime("%Y%m%dT%H%M%S%9NZ")
543
605
  records = []
544
606
  count = 0
607
+ latency = 0
608
+ records_per_tag = 0
609
+
610
+ tag_metrics_set = Hash.new
611
+ logGroup_labels_set = Hash.new
545
612
 
546
613
  invalid_tag_set = Set.new
547
614
  incoming_records_per_tag = Hash.new
@@ -549,130 +616,166 @@ module Fluent::Plugin
549
616
  tags_per_logGroupId = Hash.new
550
617
  tag_logSet_map = Hash.new
551
618
  tag_metadata_map = Hash.new
619
+ incoming_records = 0
552
620
 
553
621
  chunk.each do |time, record|
554
-
622
+ incoming_records += 1
623
+ metricsLabels = MetricsLabels.new
555
624
  if !record.nil?
556
- record_hash = record.keys.map {|x| [x,true]}.to_h
557
- is_tag_exists = false
558
- if record_hash.has_key?("tag") && is_valid(record["tag"])
559
- is_tag_exists = true
560
- end
625
+ begin
626
+ record_hash = record.keys.map {|x| [x,true]}.to_h
627
+ is_tag_exists = false
628
+ if record_hash.has_key?("tag") && is_valid(record["tag"])
629
+ is_tag_exists = true
630
+ metricsLabels.tag = record["tag"]
631
+ end
561
632
 
562
- if is_tag_exists && incoming_records_per_tag.has_key?(record["tag"])
563
- incoming_records_per_tag[record["tag"]] += 1
564
- elsif is_tag_exists
565
- incoming_records_per_tag[record["tag"]] = 1
566
- end
567
- #For any given tag, if one record fails (mandatory fields validation) then all the records from that source will be ignored
568
- if is_tag_exists && invalid_tag_set.include?(record["tag"])
569
- invalid_records_per_tag[record["tag"]] += 1
570
- next #This tag is already present in the invalid_tag_set, so ignoring the message.
571
- end
572
- #Setting tag/default value for oci_la_log_path, when not provided in config file.
573
- if !record_hash.has_key?("oci_la_log_path") || !is_valid(record["oci_la_log_path"])
574
- if is_tag_exists
575
- record["oci_la_log_path"] = record["tag"]
576
- else
577
- record["oci_la_log_path"] = 'UNDEFINED'
633
+ if is_tag_exists && incoming_records_per_tag.has_key?(record["tag"])
634
+ incoming_records_per_tag[record["tag"]] += 1
635
+ elsif is_tag_exists
636
+ incoming_records_per_tag[record["tag"]] = 1
578
637
  end
579
- end
638
+ #For any given tag, if one record fails (mandatory fields validation) then all the records from that source will be ignored
639
+ if is_tag_exists && invalid_tag_set.include?(record["tag"])
640
+ invalid_records_per_tag[record["tag"]] += 1
641
+ next #This tag is already present in the invalid_tag_set, so ignoring the message.
642
+ end
643
+ #Setting tag/default value for oci_la_log_path, when not provided in config file.
644
+ if !record_hash.has_key?("oci_la_log_path") || !is_valid(record["oci_la_log_path"])
645
+ if is_tag_exists
646
+ record["oci_la_log_path"] = record["tag"]
647
+ else
648
+ record["oci_la_log_path"] = 'UNDEFINED'
649
+ end
650
+ end
580
651
 
581
- #Extracting oci_la_log_set when oci_la_log_set_key and oci_la_log_set_ext_regex is provided.
582
- #1) oci_la_log_set param is not provided in config file and above logic not executed.
583
- #2) Valid oci_la_log_set_key + No oci_la_log_set_ext_regex
584
- #a) Valid key available in record with oci_la_log_set_key corresponding value (oci_la_log_set_key is a key in config file) --> oci_la_log_set
585
- #b) No Valid key available in record with oci_la_log_set_key corresponding value --> nil
586
- #3) Valid key available in record with oci_la_log_set_key corresponding value + Valid oci_la_log_set_ext_regex
587
- #a) Parse success --> parsed oci_la_log_set
588
- #b) Parse failure --> nil (as oci_la_log_set value)
589
- #4) No oci_la_log_set_key --> do nothing --> nil
590
-
591
- #Extracting oci_la_log_set when oci_la_log_set and oci_la_log_set_ext_regex is provided.
592
- #1) Valid oci_la_log_set + No oci_la_log_set_ext_regex --> oci_la_log_set
593
- #2) Valid oci_la_log_set + Valid oci_la_log_set_ext_regex
594
- #a) Parse success --> parsed oci_la_log_set
595
- #b) Parse failure --> nil (as oci_la_log_set value)
596
- #3) No oci_la_log_set --> do nothing --> nil
597
-
598
- unparsed_logSet = nil
599
- processed_logSet = nil
600
- if is_tag_exists && tag_logSet_map.has_key?(record["tag"])
601
- record["oci_la_log_set"] = tag_logSet_map[record["tag"]]
602
- else
603
- if record_hash.has_key?("oci_la_log_set_key")
604
- if is_valid(record["oci_la_log_set_key"]) && record_hash.has_key?(record["oci_la_log_set_key"])
605
- if is_valid(record[record["oci_la_log_set_key"]])
606
- unparsed_logSet = record[record["oci_la_log_set_key"]]
607
- processed_logSet = get_or_parse_logSet(unparsed_logSet,record, record_hash,is_tag_exists)
652
+ #Extracting oci_la_log_set when oci_la_log_set_key and oci_la_log_set_ext_regex is provided.
653
+ #1) oci_la_log_set param is not provided in config file and above logic not executed.
654
+ #2) Valid oci_la_log_set_key + No oci_la_log_set_ext_regex
655
+ #a) Valid key available in record with oci_la_log_set_key corresponding value (oci_la_log_set_key is a key in config file) --> oci_la_log_set
656
+ #b) No Valid key available in record with oci_la_log_set_key corresponding value --> nil
657
+ #3) Valid key available in record with oci_la_log_set_key corresponding value + Valid oci_la_log_set_ext_regex
658
+ #a) Parse success --> parsed oci_la_log_set
659
+ #b) Parse failure --> nil (as oci_la_log_set value)
660
+ #4) No oci_la_log_set_key --> do nothing --> nil
661
+
662
+ #Extracting oci_la_log_set when oci_la_log_set and oci_la_log_set_ext_regex is provided.
663
+ #1) Valid oci_la_log_set + No oci_la_log_set_ext_regex --> oci_la_log_set
664
+ #2) Valid oci_la_log_set + Valid oci_la_log_set_ext_regex
665
+ #a) Parse success --> parsed oci_la_log_set
666
+ #b) Parse failure --> nil (as oci_la_log_set value)
667
+ #3) No oci_la_log_set --> do nothing --> nil
668
+
669
+ unparsed_logSet = nil
670
+ processed_logSet = nil
671
+ if is_tag_exists && tag_logSet_map.has_key?(record["tag"])
672
+ record["oci_la_log_set"] = tag_logSet_map[record["tag"]]
673
+ else
674
+ if record_hash.has_key?("oci_la_log_set_key")
675
+ if is_valid(record["oci_la_log_set_key"]) && record_hash.has_key?(record["oci_la_log_set_key"])
676
+ if is_valid(record[record["oci_la_log_set_key"]])
677
+ unparsed_logSet = record[record["oci_la_log_set_key"]]
678
+ processed_logSet = get_or_parse_logSet(unparsed_logSet,record, record_hash,is_tag_exists)
679
+ end
608
680
  end
609
681
  end
610
- end
611
- if !is_valid(processed_logSet) && record_hash.has_key?("oci_la_log_set")
612
- if is_valid(record["oci_la_log_set"])
613
- unparsed_logSet = record["oci_la_log_set"]
614
- processed_logSet = get_or_parse_logSet(unparsed_logSet,record, record_hash,is_tag_exists)
682
+ if !is_valid(processed_logSet) && record_hash.has_key?("oci_la_log_set")
683
+ if is_valid(record["oci_la_log_set"])
684
+ unparsed_logSet = record["oci_la_log_set"]
685
+ processed_logSet = get_or_parse_logSet(unparsed_logSet,record, record_hash,is_tag_exists)
686
+ end
615
687
  end
616
- end
617
- record["oci_la_log_set"] = processed_logSet
618
- tag_logSet_map[record["tag"]] = processed_logSet
619
- end
688
+ record["oci_la_log_set"] = processed_logSet
689
+ tag_logSet_map[record["tag"]] = processed_logSet
690
+ end
691
+ is_valid, metricsLabels.invalid_reason = is_valid_record(record_hash,record)
620
692
 
621
- unless is_valid_record(record_hash,record)
622
- if is_tag_exists
623
- invalid_tag_set.add(record["tag"])
624
- invalid_records_per_tag[record["tag"]] = 1
625
- end
626
- next
627
- end
628
- #This will check for null or empty messages and only that record will be ignored.
629
- if !is_valid(record["message"])
630
- if is_tag_exists
631
- @@logger.warn {"'message' field has empty value, Skipping records associated with tag : #{record["tag"]}."}
632
- if invalid_records_per_tag.has_key?(record["tag"])
633
- invalid_records_per_tag[record["tag"]] += 1
634
- else
693
+ unless is_valid
694
+ if is_tag_exists
695
+ invalid_tag_set.add(record["tag"])
635
696
  invalid_records_per_tag[record["tag"]] = 1
636
697
  end
698
+ next
699
+ end
700
+ metricsLabels.logGroupId = record["oci_la_log_group_id"]
701
+ metricsLabels.logSourceName = record["oci_la_log_source_name"]
702
+ if record["oci_la_log_set"] != nil
703
+ metricsLabels.logSet = record["oci_la_log_set"]
704
+ end
705
+ #This will check for null or empty messages and only that record will be ignored.
706
+ if !is_valid(record["message"])
707
+ metricsLabels.invalid_reason = OutOracleOCILogAnalytics::METRICS_INVALID_REASON_MESSAGE
708
+ if is_tag_exists
709
+ @@logger.warn {"'message' field has empty value, Skipping records associated with tag : #{record["tag"]}."}
710
+ if invalid_records_per_tag.has_key?(record["tag"])
711
+ invalid_records_per_tag[record["tag"]] += 1
712
+ else
713
+ invalid_records_per_tag[record["tag"]] = 1
714
+ end
715
+ else
716
+ @@logger.warn {"'message' field has empty value, Skipping record."}
717
+ end
718
+ next
637
719
  else
638
- @@logger.warn {"'message' field has empty value, Skipping record."}
720
+ record["message"] = json_message_handler(record["message"])
639
721
  end
640
- next
641
- else
642
- record["message"] = json_message_handler(record["message"])
643
- end
644
722
 
645
- if record_hash.has_key?("kubernetes")
646
- record["oci_la_metadata"] = get_kubernetes_metadata(record["oci_la_metadata"],record)
647
- end
723
+ if record_hash.has_key?("kubernetes")
724
+ record["oci_la_metadata"] = get_kubernetes_metadata(record["oci_la_metadata"],record)
725
+ end
648
726
 
649
- if tag_metadata_map.has_key?(record["tag"])
650
- record["oci_la_metadata"] = tag_metadata_map[record["tag"]]
651
- else
652
- if record_hash.has_key?("oci_la_metadata")
653
- record["oci_la_metadata"] = get_valid_metadata(record["oci_la_metadata"])
654
- tags_per_logGroupId[record["tag"]] = record["oci_la_metadata"]
655
- else
656
- tags_per_logGroupId[record["tag"]] = nil
657
- end
658
- end
727
+ if tag_metadata_map.has_key?(record["tag"])
728
+ record["oci_la_metadata"] = tag_metadata_map[record["tag"]]
729
+ else
730
+ if record_hash.has_key?("oci_la_metadata")
731
+ record["oci_la_metadata"] = get_valid_metadata(record["oci_la_metadata"])
732
+ tags_per_logGroupId[record["tag"]] = record["oci_la_metadata"]
733
+ else
734
+ tags_per_logGroupId[record["tag"]] = nil
735
+ end
736
+ end
659
737
 
660
- if is_tag_exists
661
- if tags_per_logGroupId.has_key?(record["oci_la_log_group_id"])
662
- if !tags_per_logGroupId[record["oci_la_log_group_id"]].include?(record["tag"])
663
- tags_per_logGroupId[record["oci_la_log_group_id"]] += ", "+record["tag"]
738
+ if is_tag_exists
739
+ if tags_per_logGroupId.has_key?(record["oci_la_log_group_id"])
740
+ if !tags_per_logGroupId[record["oci_la_log_group_id"]].include?(record["tag"])
741
+ tags_per_logGroupId[record["oci_la_log_group_id"]] += ", "+record["tag"]
742
+ end
743
+ else
744
+ tags_per_logGroupId[record["oci_la_log_group_id"]] = record["tag"]
745
+ end
664
746
  end
665
- else
666
- tags_per_logGroupId[record["oci_la_log_group_id"]] = record["tag"]
667
- end
668
- end
669
747
 
670
- records << record
748
+ records << record
749
+ ensure
750
+ # To get chunk_time_to_receive metrics per tag, corresponding latency and total records are calculated
751
+ if tag_metrics_set.has_key?(record["tag"])
752
+ metricsLabels = tag_metrics_set[record["tag"]]
753
+ latency = metricsLabels.latency
754
+ records_per_tag = metricsLabels.records_per_tag
755
+ else
756
+ latency = 0
757
+ records_per_tag = 0
758
+ end
759
+ latency += (current_f - time)
760
+ records_per_tag += 1
761
+ metricsLabels.latency = latency
762
+ metricsLabels.records_per_tag = records_per_tag
763
+ tag_metrics_set[record["tag"]] = metricsLabels
764
+ if record["oci_la_log_group_id"] != nil && !logGroup_labels_set.has_key?(record["oci_la_log_group_id"])
765
+ logGroup_labels_set[record["oci_la_log_group_id"]] = metricsLabels
766
+ end
767
+ end
671
768
  else
672
769
  @@logger.trace {"Record is nil, ignoring the record"}
673
770
  end
674
771
  end
675
772
  @@logger.debug {"records.length:#{records.length}"}
773
+
774
+ tag_metrics_set.each do |tag,metricsLabels|
775
+ latency_avg = (metricsLabels.latency / metricsLabels.records_per_tag).round(3)
776
+ @@prometheusMetrics.chunk_time_to_receive.observe(latency_avg, labels: { tag: tag})
777
+ end
778
+
676
779
  lrpes_for_logGroupId = {}
677
780
  records.group_by{|record|
678
781
  oci_la_log_group_id = record['oci_la_log_group_id']
@@ -683,29 +786,62 @@ module Fluent::Plugin
683
786
  rescue => ex
684
787
  @@logger.error {"Error occurred while grouping records by oci_la_log_group_id:#{ex.inspect}"}
685
788
  end
686
- return incoming_records_per_tag,invalid_records_per_tag,tags_per_logGroupId,lrpes_for_logGroupId
789
+ return incoming_records_per_tag,invalid_records_per_tag,tag_metrics_set,logGroup_labels_set,tags_per_logGroupId,lrpes_for_logGroupId
687
790
  end
688
791
  # main entry point for FluentD's flush_threads, which get invoked
689
792
  # when a chunk is ready for flushing (see chunk limits and flush_intervals)
690
793
  def write(chunk)
691
794
  @@logger.info {"Received new chunk, started processing ..."}
692
- metrics = Hash.new
693
- metrics["count"] = 0
694
- metrics["event"] = "zipping"
695
- metrics["bytes_in"] = chunk.bytesize
696
- metrics['records_dropped'] = 0
795
+ #@@prometheusMetrics.bytes_received.set(chunk.bytesize, labels: { tag: nil})
697
796
  begin
698
797
  # 1) Create an in-memory zipfile for the given FluentD chunk
699
798
  # 2) Synchronization has been removed. See EMCLAS-28675
700
799
 
701
800
  begin
702
801
  lrpes_for_logGroupId = {}
703
- incoming_records_per_tag,invalid_records_per_tag,tags_per_logGroupId,lrpes_for_logGroupId = group_by_logGroupId(chunk)
802
+ incoming_records_per_tag,invalid_records_per_tag,tag_metrics_set,logGroup_labels_set,tags_per_logGroupId,lrpes_for_logGroupId = group_by_logGroupId(chunk)
704
803
  valid_message_per_tag = Hash.new
804
+ logGroup_metrics_map = Hash.new
805
+ metricsLabels_array = []
806
+
705
807
  incoming_records_per_tag.each do |key,value|
706
808
  dropped_messages = (invalid_records_per_tag.has_key?(key)) ? invalid_records_per_tag[key].to_i : 0
707
809
  valid_messages = value.to_i - dropped_messages
708
810
  valid_message_per_tag[key] = valid_messages
811
+
812
+ metricsLabels = tag_metrics_set[key]
813
+ if metricsLabels == nil
814
+ metricsLabels = MetricsLabels.new
815
+ end
816
+ metricsLabels.records_valid = valid_messages
817
+ # logGroup_metrics_map will have logGroupId as key and metricsLabels_array as value.
818
+ # In a chunk we can have different logGroupIds but we are creating payloads based on logGroupId and that can internally have different logSourceName and tag data.
819
+ # Using logGroup_metrics_map, for a given chunk, we can produce the metrics with proper logGroupId and its corresponding values.
820
+ if metricsLabels.logGroupId != nil
821
+ if logGroup_metrics_map.has_key?(metricsLabels.logGroupId)
822
+ metricsLabels_array = logGroup_metrics_map[metricsLabels.logGroupId]
823
+ else
824
+ metricsLabels_array = []
825
+ end
826
+ metricsLabels_array.push(metricsLabels)
827
+ logGroup_metrics_map[metricsLabels.logGroupId] = metricsLabels_array
828
+ end
829
+
830
+ @@prometheusMetrics.records_received.set(value.to_i, labels: { tag: key,
831
+ oci_la_log_group_id: metricsLabels.logGroupId,
832
+ oci_la_log_source_name: metricsLabels.logSourceName,
833
+ oci_la_log_set: metricsLabels.logSet})
834
+
835
+ @@prometheusMetrics.records_invalid.set(dropped_messages, labels: { tag: key,
836
+ oci_la_log_group_id: metricsLabels.logGroupId,
837
+ oci_la_log_source_name: metricsLabels.logSourceName,
838
+ oci_la_log_set: metricsLabels.logSet,
839
+ reason: metricsLabels.invalid_reason})
840
+ @@prometheusMetrics.records_valid.set(valid_messages, labels: { tag: key,
841
+ oci_la_log_group_id: metricsLabels.logGroupId,
842
+ oci_la_log_source_name: metricsLabels.logSourceName,
843
+ oci_la_log_set: metricsLabels.logSet})
844
+
709
845
  if dropped_messages > 0
710
846
  @@logger.info {"Messages: #{value.to_i} \t Valid: #{valid_messages} \t Invalid: #{dropped_messages} \t tag:#{key}"}
711
847
  end
@@ -720,17 +856,27 @@ module Fluent::Plugin
720
856
  zippedstream = nil
721
857
  oci_la_log_set = nil
722
858
  logSets_per_logGroupId_map = Hash.new
859
+
860
+ metricsLabels_array = logGroup_metrics_map[oci_la_log_group_id]
861
+
723
862
  # Only MAX_FILES_PER_ZIP (100) files are allowed, which will be grouped and zipped.
724
863
  # Due to MAX_FILES_PER_ZIP constraint, for a oci_la_log_group_id, we can get more than one zip file and those many api calls will be made.
725
864
  logSets_per_logGroupId_map, oci_la_global_metadata = get_logSets_map_per_logGroupId(oci_la_log_group_id,records_per_logGroupId)
726
865
  if logSets_per_logGroupId_map != nil
727
- logSets_per_logGroupId_map.each do |file_count,records_per_logSet_map|
728
- zippedstream,number_of_records = get_zipped_stream(oci_la_log_group_id,oci_la_global_metadata,records_per_logSet_map)
729
- if zippedstream != nil
730
- zippedstream.rewind #reposition buffer pointer to the beginning
731
- upload_to_oci(oci_la_log_group_id, number_of_records, zippedstream)
732
- end
733
- end
866
+ bytes_out = 0
867
+ records_out = 0
868
+ chunk_upload_time_taken = nil
869
+ chunk_upload_time_taken = Benchmark.measure {
870
+ logSets_per_logGroupId_map.each do |file_count,records_per_logSet_map|
871
+ zippedstream,number_of_records = get_zipped_stream(oci_la_log_group_id,oci_la_global_metadata,records_per_logSet_map)
872
+ if zippedstream != nil
873
+ zippedstream.rewind #reposition buffer pointer to the beginning
874
+ upload_to_oci(oci_la_log_group_id, number_of_records, zippedstream, metricsLabels_array)
875
+ end
876
+ end
877
+ }.real.round(3)
878
+ @@prometheusMetrics.chunk_time_to_upload.observe(chunk_upload_time_taken, labels: { oci_la_log_group_id: oci_la_log_group_id})
879
+
734
880
  end
735
881
  ensure
736
882
  zippedstream&.close
@@ -844,8 +990,10 @@ module Fluent::Plugin
844
990
  end
845
991
 
846
992
  # upload zipped stream to oci
847
- def upload_to_oci(oci_la_log_group_id, number_of_records, zippedstream)
993
+ def upload_to_oci(oci_la_log_group_id, number_of_records, zippedstream, metricsLabels_array)
848
994
  begin
995
+ error_reason = nil
996
+ error_code = nil
849
997
  opts = {payload_type: "ZIP"}
850
998
 
851
999
  response = @@loganalytics_client.upload_log_events_file(namespace_name=@namespace,
@@ -854,6 +1002,19 @@ module Fluent::Plugin
854
1002
  opts)
855
1003
  if !response.nil? && response.status == 200 then
856
1004
  headers = response.headers
1005
+
1006
+ metricsLabels_array.each { |metricsLabels|
1007
+ @@prometheusMetrics.records_posted.set(metricsLabels.records_valid, labels: { tag: metricsLabels.tag,
1008
+ oci_la_log_group_id: metricsLabels.logGroupId,
1009
+ oci_la_log_source_name: metricsLabels.logSourceName,
1010
+ oci_la_log_set: metricsLabels.logSet})
1011
+ }
1012
+
1013
+ #zippedstream.rewind #reposition buffer pointer to the beginning
1014
+ #zipfile = zippedstream&.sysread&.dup
1015
+ #bytes_out = zipfile&.length
1016
+ #@@prometheusMetrics.bytes_posted.set(bytes_out, labels: { oci_la_log_group_id: oci_la_log_group_id})
1017
+
857
1018
  @@logger.info {"The payload has been successfully uploaded to logAnalytics -
858
1019
  oci_la_log_group_id: #{oci_la_log_group_id},
859
1020
  ConsumedRecords: #{number_of_records},
@@ -863,13 +1024,16 @@ module Fluent::Plugin
863
1024
  opc-object-id: #{headers['opc-object-id']}"}
864
1025
  end
865
1026
  rescue OCI::Errors::ServiceError => serviceError
1027
+ error_code = serviceError.status_code
866
1028
  case serviceError.status_code
867
1029
  when 400
1030
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_400
868
1031
  @@logger.error {"oci upload exception : Error while uploading the payload. Invalid/Incorrect/missing Parameter - opc-request-id:#{serviceError.request_id}"}
869
1032
  if plugin_retry_on_4xx
870
1033
  raise serviceError
871
1034
  end
872
1035
  when 401
1036
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_401
873
1037
  @@logger.error {"oci upload exception : Error while uploading the payload. Not Authenticated.
874
1038
  opc-request-id:#{serviceError.request_id}
875
1039
  message: #{serviceError.message}"}
@@ -877,6 +1041,7 @@ module Fluent::Plugin
877
1041
  raise serviceError
878
1042
  end
879
1043
  when 404
1044
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_404
880
1045
  @@logger.error {"oci upload exception : Error while uploading the payload. Authorization failed for given oci_la_log_group_id against given Tenancy Namespace.
881
1046
  oci_la_log_group_id: #{oci_la_log_group_id}
882
1047
  Namespace: #{@namespace}
@@ -886,34 +1051,53 @@ module Fluent::Plugin
886
1051
  raise serviceError
887
1052
  end
888
1053
  when 429
1054
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_429
889
1055
  @@logger.error {"oci upload exception : Error while uploading the payload. Too Many Requests - opc-request-id:#{serviceError.request_id}"}
890
1056
  raise serviceError
891
1057
  when 500
1058
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_500
892
1059
  @@logger.error {"oci upload exception : Error while uploading the payload. Internal Server Error - opc-request-id:#{serviceError.request_id}"}
893
1060
  raise serviceError
894
1061
 
895
1062
  when 502
1063
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_502
896
1064
  @@logger.error {"oci upload exception : Error while uploading the payload. Bad Gateway - opc-request-id:#{serviceError.request_id}"}
897
1065
  raise serviceError
898
1066
 
899
1067
  when 503
1068
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_503
900
1069
  @@logger.error {"oci upload exception : Error while uploading the payload. Service unavailable - opc-request-id:#{serviceError.request_id}"}
901
1070
  raise serviceError
902
1071
 
903
1072
  when 504
1073
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_504
904
1074
  @@logger.error {"oci upload exception : Error while uploading the payload. Gateway Timeout - opc-request-id:#{serviceError.request_id}"}
905
1075
  raise serviceError
906
1076
 
907
1077
  when 505
1078
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_505
908
1079
  @@logger.error {"oci upload exception : Error while uploading the payload. HTTP Version Not Supported - opc-request-id:#{serviceError.request_id}"}
909
1080
  raise serviceError
910
1081
  else
1082
+ error_reason = OutOracleOCILogAnalytics::METRICS_SERVICE_ERROR_REASON_UNKNOWN
911
1083
  @@logger.error {"oci upload exception : Error while uploading the payload #{serviceError.message}"}
912
1084
  raise serviceError
913
1085
  end
914
1086
  rescue => ex
1087
+ error_reason = ex
915
1088
  @@logger.error {"oci upload exception : Error while uploading the payload. #{ex}"}
1089
+ ensure
1090
+ if error_reason != nil
1091
+ metricsLabels_array.each { |metricsLabels|
1092
+ @@prometheusMetrics.records_error.set(metricsLabels.records_valid, labels: { tag: metricsLabels.tag,
1093
+ oci_la_log_group_id: metricsLabels.logGroupId,
1094
+ oci_la_log_source_name: metricsLabels.logSourceName,
1095
+ oci_la_log_set: metricsLabels.logSet,
1096
+ error_code: error_code,
1097
+ reason: error_reason})
1098
+ }
1099
+ end
916
1100
  end
917
1101
  end
918
1102
  end
919
- end
1103
+ end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-oci-logging-analytics
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
- - OCI Logging Analytics Team
7
+ - Oracle
8
+ - 'OCI Observability: Logging Analytics'
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2022-01-14 00:00:00.000000000 Z
12
+ date: 2022-06-20 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rake
@@ -78,17 +79,32 @@ dependencies:
78
79
  requirements:
79
80
  - - "~>"
80
81
  - !ruby/object:Gem::Version
81
- version: '2.13'
82
+ version: '2.16'
82
83
  type: :runtime
83
84
  prerelease: false
84
85
  version_requirements: !ruby/object:Gem::Requirement
85
86
  requirements:
86
87
  - - "~>"
87
88
  - !ruby/object:Gem::Version
88
- version: '2.13'
89
- description: Fluentd Output plugin to ship logs/events to OCI Logging Analytics.
89
+ version: '2.16'
90
+ - !ruby/object:Gem::Dependency
91
+ name: prometheus-client
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 4.0.0
97
+ type: :runtime
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 4.0.0
104
+ description: OCI Logging Analytics Fluentd output plugin for ingesting the collected
105
+ log events to OCI Logging Analytics.
90
106
  email:
91
- - oci_la_plugins@oracle.com
107
+ - oci_la_plugins_grp@oracle.com
92
108
  executables: []
93
109
  extensions: []
94
110
  extra_rdoc_files: []
@@ -101,7 +117,10 @@ files:
101
117
  homepage:
102
118
  licenses:
103
119
  - UPL-1.0
104
- metadata: {}
120
+ metadata:
121
+ documentation_uri: https://docs.oracle.com/en/learn/oci_logging_analytics_fluentd/
122
+ source_code_uri: https://github.com/oracle-quickstart/oci-logan-fluentd-output-plugin
123
+ changelog_uri: https://github.com/oracle-quickstart/oci-logan-fluentd-output-plugin/blob/main/CHANGELOG.md
105
124
  post_install_message:
106
125
  rdoc_options: []
107
126
  require_paths:
@@ -110,15 +129,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
129
  requirements:
111
130
  - - ">="
112
131
  - !ruby/object:Gem::Version
113
- version: '0'
132
+ version: 2.6.0
114
133
  required_rubygems_version: !ruby/object:Gem::Requirement
115
134
  requirements:
116
135
  - - ">="
117
136
  - !ruby/object:Gem::Version
118
137
  version: '0'
119
138
  requirements: []
120
- rubygems_version: 3.0.8
139
+ rubyforge_project:
140
+ rubygems_version: 2.6.13
121
141
  signing_key:
122
142
  specification_version: 4
123
- summary: Fluentd Output plugin to ship logs/events to OCI Logging Analytics.
143
+ summary: Fluentd output plugin for OCI Logging Analytics.
124
144
  test_files: []