fluent-plugin-dynatrace 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11015b23549401ef5812fbc636a3da5a2dc1ff200fad51a1c972f9d9cf54d2e1
4
- data.tar.gz: 87a353d50119fe09e3d11a9ce23f6c20c282b31c4a930dba5336a3c05e95e5f4
3
+ metadata.gz: b25942088d9fc1e97ab3e9c5ee2cfec5baca12f39744bb09012e5f5238522dd9
4
+ data.tar.gz: d942be9cfa1215746fcf513a629d09986d5996ba8a0401622b6d0cf5cdf93cf2
5
5
  SHA512:
6
- metadata.gz: 9d8ea643ef564a15584364fcdb28aabf2118cf145f6d4c82301b7441e7986a9f3c7e7e4f4beb93ccdcc7164f60621b96ad238f56531274f72cf5df84dbd74a19
7
- data.tar.gz: cd0ac68b36280801f40da7de3363bb5e0051ff697870fc6cb4390f7100f22dfadf417c0cb6c5be6641fa79f01a8ba5434e01bae21fb43e78bd8d2fb6a81cbd89
6
+ metadata.gz: 63ca8a3ab6b1e22d7d6e4c29bdcba35e33b145b494f6e736b5cd117feb5af22e647262d0477d9eb72ab316550af2a1469cc7459f0730f3a36fceee79d4834cf0
7
+ data.tar.gz: 9c9532efc4215183ee632ea51a30c27b630b5a239b9fc548e499446fb2dd819ec6c00753e0b3756d435b8625148b59fa1e2c05ad3579d3de5b909fe1c92aa4f7
@@ -20,7 +20,7 @@ module Fluent
20
20
  class DynatraceOutputConstants
21
21
  # The version of the Dynatrace output plugin
22
22
  def self.version
23
- '0.1.3'
23
+ '0.2.0'
24
24
  end
25
25
  end
26
26
  end
@@ -24,17 +24,24 @@ module Fluent
24
24
  class DynatraceOutput < Output
25
25
  Fluent::Plugin.register_output('dynatrace', self)
26
26
 
27
+ HTTP_REQUEST_LOCK = Mutex.new
28
+
27
29
  helpers :compat_parameters # add :inject if need be
28
30
 
29
31
  # Configurations
30
32
  desc 'The full URL of the Dynatrace log ingestion endpoint, e.g. https://my-active-gate.example.com/api/logs/ingest'
31
33
  config_param :active_gate_url, :string
32
- desc 'The API token to use to authenticate requests to the log ingestion endpoint. Must have TODO scope'
34
+ desc 'The API token to use to authenticate requests to the log ingestion endpoint. '\
35
+ 'Must have logs.ingest (Ingest Logs) scope. '\
36
+ 'It is recommended to limit scope to only this one.'
33
37
  config_param :api_token, :string, secret: true
34
38
 
35
39
  desc 'Disable SSL validation by setting :verify_mode OpenSSL::SSL::VERIFY_NONE'
36
40
  config_param :ssl_verify_none, :bool, default: false
37
41
 
42
+ desc 'Inject timestamp into each log message'
43
+ config_param :inject_timestamp, :bool, default: false
44
+
38
45
  #############################################
39
46
 
40
47
  config_section :buffer do
@@ -57,7 +64,10 @@ module Fluent
57
64
  compat_parameters_convert(conf, :inject)
58
65
  super
59
66
 
60
- @uri = URI.parse(@active_gate_url)
67
+ raise Fluent::ConfigError, 'api_token is empty' if @api_token.empty?
68
+
69
+ @uri = parse_and_validate_uri(@active_gate_url)
70
+
61
71
  @agent = Net::HTTP.new(@uri.host, @uri.port)
62
72
 
63
73
  return unless uri.scheme == 'https'
@@ -74,20 +84,29 @@ module Fluent
74
84
  #############################################
75
85
 
76
86
  def process(_tag, es)
87
+ log.on_trace { log.trace('#process') }
88
+ records = 0
77
89
  # es = inject_values_to_event_stream(tag, es)
78
- es.each do |_time, record|
79
- send_to_dynatrace("#{record.to_json.chomp}\n")
90
+ es.each do |time, record|
91
+ records += 1
92
+ log.on_trace { log.trace("#process Processing record #{records}") }
93
+ record['@timestamp'] = time * 1000 if @inject_timestamp
94
+ synchronized_send_records(record)
80
95
  end
96
+ log.on_trace { log.trace("#process Processed #{records} records") }
81
97
  end
82
98
 
83
99
  def write(chunk)
84
- body = []
85
- chunk.each do |_time, record|
86
- # body.push(inject_values_to_record(chunk.metadata.tag, time, record))
87
- body.push(record)
100
+ log.on_trace { log.trace('#write') }
101
+ records = []
102
+ chunk.each do |time, record|
103
+ # records.push(inject_values_to_record(chunk.metadata.tag, time, record))
104
+ record['@timestamp'] = time * 1000 if @inject_timestamp
105
+ records.push(record)
88
106
  end
89
107
 
90
- send_to_dynatrace("#{body.to_json.chomp}\n")
108
+ log.on_trace { log.trace("#write sent #{records.length} records") }
109
+ synchronized_send_records(records) unless records.empty?
91
110
  end
92
111
 
93
112
  #############################################
@@ -106,7 +125,8 @@ module Fluent
106
125
  "fluent-plugin-dynatrace v#{DynatraceOutputConstants.version}"
107
126
  end
108
127
 
109
- def prepare_request(uri)
128
+ def prepare_request
129
+ log.on_trace { log.trace('#prepare_request') }
110
130
  req = Net::HTTP::Post.new(uri, { 'User-Agent' => user_agent })
111
131
  req['Content-Type'] = 'application/json; charset=utf-8'
112
132
  req['Authorization'] = "Api-Token #{@api_token}"
@@ -114,15 +134,37 @@ module Fluent
114
134
  req
115
135
  end
116
136
 
117
- def send_to_dynatrace(body)
137
+ def synchronized_send_records(records)
138
+ log.on_trace { log.trace('#synchronized_send_records') }
139
+ HTTP_REQUEST_LOCK.synchronize do
140
+ send_records(records)
141
+ end
142
+ end
143
+
144
+ def send_records(records)
145
+ log.on_trace { log.trace('#send_records') }
146
+
118
147
  agent.start unless agent.started?
119
148
 
120
- req = prepare_request(@uri)
121
- res = @agent.request(req, body)
149
+ response = send_request(serialize(records))
150
+
151
+ return if response.is_a?(Net::HTTPSuccess)
152
+
153
+ raise failure_message response
154
+ end
122
155
 
123
- return if res.is_a?(Net::HTTPSuccess)
156
+ def serialize(records)
157
+ log.on_trace { log.trace('#serialize') }
158
+ body = "#{records.to_json.chomp}\n"
159
+ log.on_trace { log.trace("#serialize body length #{body.length}") }
160
+ body
161
+ end
124
162
 
125
- raise failure_message res
163
+ def send_request(body)
164
+ log.on_trace { log.trace('#send_request') }
165
+ response = @agent.request(prepare_request, body)
166
+ log.on_trace { log.trace("#send_request response #{response}") }
167
+ response
126
168
  end
127
169
 
128
170
  def failure_message(res)
@@ -134,6 +176,22 @@ module Fluent
134
176
 
135
177
  "failed to request #{uri} (#{res_summary})"
136
178
  end
179
+
180
+ #############################################
181
+
182
+ private
183
+
184
+ def parse_and_validate_uri(uri_string)
185
+ raise Fluent::ConfigError, 'active_gate_url is empty' if uri_string.empty?
186
+
187
+ uri = URI.parse(uri_string)
188
+ raise Fluent::ConfigError, 'active_gate_url scheme must be http or https' unless
189
+ %w[http https].include?(uri.scheme)
190
+
191
+ raise Fluent::ConfigError, 'active_gate_url must include an authority' if uri.host.nil?
192
+
193
+ uri
194
+ end
137
195
  end
138
196
  end
139
197
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-dynatrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dynatrace Open Source Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-08 00:00:00.000000000 Z
11
+ date: 2022-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  requirements: []
127
- rubygems_version: 3.1.4
127
+ rubygems_version: 3.1.6
128
128
  signing_key:
129
129
  specification_version: 4
130
130
  summary: A fluentd output plugin for sending logs to the Dynatrace Generic log ingest