fluent-plugin-dynatrace 0.1.0

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.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # fluent-plugin-dynatrace, a plugin for [fluentd](https://www.fluentd.org/)
2
+
3
+ > This project is developed and maintained by Dynatrace R&D.
4
+ Currently, this is a prototype and not intended for production use.
5
+ It is not covered by Dynatrace support.
6
+
7
+ A fluentd output plugin for sending logs to the Dynatrace [Generic log ingest API v2](https://www.dynatrace.com/support/help/how-to-use-dynatrace/log-monitoring/log-monitoring-v2/post-log-ingest/).
8
+
9
+ ## Requirements
10
+
11
+ - An instance of fluentd from which logs should be exported
12
+ - An ActiveGate with the Generic log ingest API v2 enabled as described in the [Dynatrace documentation](https://www.dynatrace.com/support/help/how-to-use-dynatrace/log-monitoring/log-monitoring-v2/log-data-ingestion/)
13
+ - A [Dynatrace API token](https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication/) with the `Log import` permission
14
+
15
+ ## Configuration options
16
+
17
+ Below is an example configuration which sends all logs with tags starting with `dt.` to Dynatrace.
18
+
19
+ ```
20
+ <match dt.*>
21
+ @type dynatrace
22
+ active_gate_url https://abc12345.live.dynatrace.com/api/v2/logs/ingest
23
+ api_token api_token
24
+ ssl_verify_none false
25
+ </match>
26
+ ```
27
+
28
+ ### match directive
29
+
30
+ - `required`
31
+
32
+ The `match` directive is required to use an output plugin and tells fluentd which tags should be sent to the output plugin. In the above example, any tag that starts with `dt.` will be sent to Dynatrace. For more information see [how do match patterns work?](https://docs.fluentd.org/configuration/config-file#how-do-the-match-patterns-work).
33
+
34
+ ### @type
35
+
36
+ - `required`
37
+
38
+ The `@type` directive tells fluentd which plugin should be used for the corresponding match block. This should always be `dynatrace` when you want to use the Dynatrace output plugin.
39
+
40
+ ### `active_gate_url`
41
+
42
+ - `required`
43
+
44
+ This is the full URL of the [Generic log ingest API v2](https://www.dynatrace.com/support/help/how-to-use-dynatrace/log-monitoring/log-monitoring-v2/post-log-ingest/) endpoint on your ActiveGate.
45
+
46
+ ### `api_token`
47
+
48
+ - `required`
49
+
50
+ This is the [Dynatrace API token](https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication/) which will be used to authenticate log ingest requests. It should be assigned only the `Log import` permission.
51
+
52
+ ### `ssl_verify_none`
53
+
54
+ - `optional`
55
+ - `default: false`
56
+
57
+ It is recommended to leave this optional configuration set to `false` unless absolutely required. Setting `ssl_verify_none` to `true` causes the output plugin to skip certificate verification when sending log ingest requests to SSL and TLS protected HTTPS endpoints. This option may be required if you are using a self-signed certificate, an expired certificate, or a certificate which was generated for a different domain than the one in use.
58
+
59
+ ## Development
60
+
61
+ `fluent-plugin-dynatrace` supports Ruby versions `>= 2.4.0` but it is recommended that at least `2.7.2` is used for development. Ruby versions can be managed with tools like [chruby](https://github.com/postmodern/chruby) or [rbenv](https://github.com/rbenv/rbenv).
62
+
63
+ ### Install Dependencies
64
+
65
+ ```sh
66
+ bundle install
67
+ ```
68
+
69
+ ### Run All Tests
70
+
71
+ ```sh
72
+ rake test
73
+ ```
74
+
75
+ ### Run Specific Tests
76
+
77
+ ```sh
78
+ # Run one test file
79
+ rake test TEST=test/plugin/out_dynatrace_test.rb
80
+ ```
81
+
82
+ ### Code Style Checks
83
+
84
+ ```sh
85
+ # Check for code style violations
86
+ rake rubocop
87
+
88
+ # Fix auto-fixable style violations
89
+ rake rubocop:auto_correct
90
+ ```
91
+
92
+ ### Run all checks and build
93
+
94
+ ```sh
95
+ # Runs rubocop, tests, and builds the gem
96
+ rake check
97
+ ```
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright 2021 Dynatrace LLC
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'bundler/gem_tasks'
19
+ require 'rake/testtask'
20
+ require 'rubocop/rake_task'
21
+
22
+ RuboCop::RakeTask.new
23
+
24
+ Rake::TestTask.new :test do |t|
25
+ t.libs << 'test'
26
+ t.libs << 'lib'
27
+ t.test_files = FileList['test/plugin/*_test.rb']
28
+ end
29
+
30
+ Rake::TestTask.new 'test:integration' do |t|
31
+ t.test_files = FileList['test/integration/*_test.rb']
32
+ end
33
+
34
+ desc 'check for style violations and test failures and build the gem'
35
+ task check: %i[rubocop test build]
36
+
37
+ task default: :build
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/fluent/plugin/dynatrace_constants'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'fluent-plugin-dynatrace'
7
+ gem.version = Fluent::Plugin::DynatraceOutputConstants.version
8
+ gem.authors = ['Dynatrace Open Source Engineering']
9
+ gem.email = ['opensource@dynatrace.com']
10
+ gem.summary = 'A fluentd output plugin for sending logs to the Dynatrace Generic log ingest API v2'
11
+ gem.homepage = 'https://www.dynatrace.com/'
12
+ gem.licenses = ['Apache-2.0']
13
+
14
+ gem.metadata = {
15
+ 'bug_tracker_uri' => 'https://github.com/dynatrace-oss/fluent-plugin-dynatrace/issues',
16
+ 'documentation_uri' => 'https://github.com/dynatrace-oss/fluent-plugin-dynatrace',
17
+ 'source_code_uri' => 'https://github.com/dynatrace-oss/fluent-plugin-dynatrace'
18
+ }
19
+
20
+ gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
21
+ gem.require_paths = ['lib']
22
+
23
+ gem.required_ruby_version = '>= 2.4.0'
24
+
25
+ gem.add_runtime_dependency 'fluentd', ['>= 0.14.22', '< 2']
26
+ gem.add_development_dependency 'bundler', ['>= 2', '<3']
27
+ gem.add_development_dependency 'rake', '13.0.3'
28
+ gem.add_development_dependency 'rubocop', '1.9.1'
29
+ gem.add_development_dependency 'rubocop-rake', '0.5.1'
30
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Dynatrace LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Fluent
18
+ module Plugin
19
+ # Constants for use in Dynatrace output plugin
20
+ class DynatraceOutputConstants
21
+ # The version of the Dynatrace output plugin
22
+ def self.version
23
+ '0.1.0'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Dynatrace LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'fluent/plugin/output'
18
+ require 'net/http'
19
+ require_relative 'dynatrace_constants'
20
+
21
+ module Fluent
22
+ module Plugin
23
+ # Fluentd output plugin for Dynatrace
24
+ class DynatraceOutput < Output
25
+ Fluent::Plugin.register_output('dynatrace', self)
26
+
27
+ helpers :compat_parameters # add :inject if need be
28
+
29
+ # Configurations
30
+ desc 'The full URL of the Dynatrace log ingestion endpoint, e.g. https://my-active-gate.example.com/api/logs/ingest'
31
+ 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'
33
+ config_param :api_token, :string, secret: true
34
+
35
+ desc 'Disable SSL validation by setting :verify_mode OpenSSL::SSL::VERIFY_NONE'
36
+ config_param :ssl_verify_none, :bool, default: false
37
+
38
+ #############################################
39
+
40
+ config_section :buffer do
41
+ config_set_default :flush_at_shutdown, true
42
+ config_set_default :chunk_limit_size, 10 * 1024
43
+ end
44
+
45
+ # Default injection parameters.
46
+ # Requires the :inject helper to be added to the helpers above and the
47
+ # inject lines to be uncommented in the #write and #process methods
48
+ # config_section :inject do
49
+ # config_set_default :time_type, :string
50
+ # config_set_default :localtime, false
51
+ # end
52
+ #############################################
53
+
54
+ attr_accessor :uri, :agent
55
+
56
+ def configure(conf)
57
+ compat_parameters_convert(conf, :inject)
58
+ super
59
+
60
+ @uri = URI.parse(@active_gate_url)
61
+ @agent = Net::HTTP.new(@uri.host, @uri.port)
62
+
63
+ return unless uri.scheme == 'https'
64
+
65
+ @agent.use_ssl = true
66
+ @agent.verify_mode = OpenSSL::SSL::VERIFY_NONE if @ssl_verify_none
67
+ end
68
+
69
+ def shutdown
70
+ @agent.finish if @agent.started?
71
+ super
72
+ end
73
+
74
+ #############################################
75
+
76
+ def process(_tag, es)
77
+ # es = inject_values_to_event_stream(tag, es)
78
+ es.each do |_time, record|
79
+ send_to_dynatrace("#{record.to_json.chomp}\n")
80
+ end
81
+ end
82
+
83
+ 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)
88
+ end
89
+
90
+ send_to_dynatrace("#{body.to_json.chomp}\n")
91
+ end
92
+
93
+ #############################################
94
+
95
+ def prefer_buffered_processing
96
+ true
97
+ end
98
+
99
+ def multi_workers_ready?
100
+ false
101
+ end
102
+
103
+ #############################################
104
+
105
+ def user_agent
106
+ "fluent-plugin-dynatrace v#{DynatraceOutputConstants.version}"
107
+ end
108
+
109
+ def prepare_request(uri)
110
+ req = Net::HTTP::Post.new(uri, { 'User-Agent' => user_agent })
111
+ req['Content-Type'] = 'application/json; charset=utf-8'
112
+ req['Authorization'] = "Api-Token #{@api_token}"
113
+
114
+ req
115
+ end
116
+
117
+ def send_to_dynatrace(body)
118
+ agent.start unless agent.started?
119
+
120
+ req = prepare_request(@uri)
121
+ res = @agent.request(req, body)
122
+
123
+ return if res.is_a?(Net::HTTPSuccess)
124
+
125
+ raise failure_message res
126
+ end
127
+
128
+ def failure_message(res)
129
+ res_summary = if res
130
+ "#{res.code} #{res.message}"
131
+ else
132
+ 'res=nil'
133
+ end
134
+
135
+ "failed to #{req.method} #{uri} (#{res_summary})"
136
+ end
137
+ end
138
+ end
139
+ end
data/test/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ inherit_from: ../.rubocop.yml
2
+
3
+ Metrics:
4
+ Enabled: false
5
+
@@ -0,0 +1,27 @@
1
+ # Copyright 2021 Dynatrace LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ services:
16
+ fluent:
17
+ build:
18
+ context: ../../../
19
+ dockerfile: test/integration/fixtures/fluent/Dockerfile
20
+ ports:
21
+ - 8080:8080
22
+ links:
23
+ - logsink
24
+ logsink:
25
+ build: logsink
26
+ expose:
27
+ - 8080
@@ -0,0 +1,30 @@
1
+ # Copyright 2021 Dynatrace LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ FROM fluent/fluentd:edge
16
+
17
+ LABEL maintainer="Daniel Dyla <Daniel.Dyla@dynatrace.com>"
18
+ USER root
19
+
20
+ # the build context is the root of the repo to allow access to the plugin rb
21
+ COPY test/integration/fixtures/fluent/entrypoint.sh /fluentd/entrypoint.sh
22
+ RUN chmod +x /fluentd/entrypoint.sh
23
+
24
+ COPY test/integration/fixtures/fluent/fluent.conf /fluentd/etc/fluent.conf
25
+ COPY lib/fluent/plugin/out_dynatrace.rb /fluentd/plugins/
26
+ COPY lib/fluent/plugin/dynatrace_constants.rb /fluentd/plugins/
27
+
28
+ ENTRYPOINT ["tini", "--", "/fluentd/entrypoint.sh"]
29
+
30
+ USER fluent
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env sh
2
+
3
+ # Copyright 2021 Dynatrace LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ exec fluentd -c /fluentd/etc/fluent.conf -p /fluentd/plugins
@@ -0,0 +1,30 @@
1
+ # Copyright 2021 Dynatrace LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ <source>
16
+ @type http
17
+ port 8080
18
+ </source>
19
+
20
+ <match dt.*>
21
+ @type dynatrace
22
+
23
+ active_gate_url http://logsink:8080/api/v2/logs/ingest
24
+ api_token my_token
25
+
26
+ <buffer>
27
+ chunk_limit_records 5
28
+ flush_interval 5s
29
+ </buffer>
30
+ </match>