fluent-plugin-dynatrace 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/integration.yaml +50 -0
- data/.github/workflows/lint.yaml +21 -0
- data/.github/workflows/release.yaml +28 -0
- data/.github/workflows/unit.yaml +24 -0
- data/.gitignore +63 -0
- data/.rubocop.yml +8 -0
- data/CODE_OF_CONDUCT.md +76 -0
- data/Gemfile +5 -0
- data/LICENSE +201 -0
- data/README.md +97 -0
- data/Rakefile +37 -0
- data/fluent-plugin-dynatrace.gemspec +30 -0
- data/lib/fluent/plugin/dynatrace_constants.rb +27 -0
- data/lib/fluent/plugin/out_dynatrace.rb +139 -0
- data/test/.rubocop.yml +5 -0
- data/test/integration/fixtures/docker-compose.yaml +27 -0
- data/test/integration/fixtures/fluent/Dockerfile +30 -0
- data/test/integration/fixtures/fluent/entrypoint.sh +17 -0
- data/test/integration/fixtures/fluent/fluent.conf +30 -0
- data/test/integration/fixtures/logsink/Dockerfile +18 -0
- data/test/integration/fixtures/logsink/server.js +46 -0
- data/test/integration/integration_test.rb +50 -0
- data/test/plugin/out_dynatrace_test.rb +152 -0
- metadata +152 -0
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,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>
|