fluent-plugin-dynatrace 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
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 node:lts-alpine
16
+ COPY server.js /logsink/server.js
17
+
18
+ CMD node /logsink/server.js
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Copyright 2021 Dynatrace LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ const http = require("http");
18
+
19
+ process.on('SIGINT', () => {
20
+ process.exit(0)
21
+ });
22
+
23
+ process.on('SIGTERM', () => {
24
+ process.exit(0)
25
+ });
26
+
27
+ const server = http.createServer((req, res) => {
28
+ const ua = req.headers['user-agent'];
29
+ if (typeof ua != 'string') {
30
+ process.stdout.write("Missing user agent header");
31
+ }
32
+
33
+ if (!ua.match(/^fluent-plugin-dynatrace v\d+\.\d+\.\d+$/)) {
34
+ process.stdout.write("Invalid user agent header");
35
+ }
36
+
37
+ req.on('data', (chunk) => {
38
+ process.stdout.write(chunk);
39
+ });
40
+
41
+ req.on("end", () => {
42
+ res.end();
43
+ });
44
+ })
45
+
46
+ server.listen(8080);
@@ -0,0 +1,50 @@
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 'test/unit'
18
+ require 'net/http'
19
+
20
+ class TestFluentIntegration < Test::Unit::TestCase
21
+ def setup
22
+ puts `cd test/integration/fixtures && docker-compose up -d --force-recreate --build`
23
+ puts 'waiting 5s for integration test to start'
24
+ sleep 5
25
+ end
26
+
27
+ def teardown
28
+ puts `cd test/integration/fixtures && docker-compose down`
29
+ end
30
+
31
+ def test_integration
32
+ puts 'sending logs'
33
+ uri = URI.parse('http://localhost:8080/dt.match')
34
+ http = Net::HTTP.new(uri.host, uri.port)
35
+
36
+ req = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json' })
37
+
38
+ req.body = '[{"foo":"bar"},{"abc":"def"},{"xyz":"123"},{"abc":"def"},{"xyz":"123"},{"abc":"def"},{"xyz":"123"}]'
39
+ http.request(req)
40
+
41
+ puts 'waiting 10s for output plugin to flush'
42
+ sleep 10
43
+
44
+ logs = `docker logs fixtures_logsink_1`
45
+
46
+ line1 = '[{"foo":"bar"},{"abc":"def"},{"xyz":"123"},{"abc":"def"},{"xyz":"123"}]'
47
+ line2 = '[{"abc":"def"},{"xyz":"123"}]'
48
+ assert_equal("#{line1}\n#{line2}\n", logs)
49
+ end
50
+ end
@@ -0,0 +1,152 @@
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/test'
18
+ require 'fluent/test/helpers'
19
+ require 'fluent/test/driver/output'
20
+ require 'fluent/plugin/out_dynatrace'
21
+ require 'fluent/plugin/dynatrace_constants'
22
+ require 'webrick'
23
+
24
+ class FakeAgent
25
+ Result = Struct.new('Result', :data, :headers)
26
+
27
+ attr_reader :result, :original_agent
28
+ attr_accessor :use_ssl, :verify_mode
29
+
30
+ def initialize(original_agent)
31
+ @result = Result.new(nil, {})
32
+ @started = false
33
+ @original_agent = original_agent
34
+ end
35
+
36
+ def started?
37
+ @started
38
+ end
39
+
40
+ def start
41
+ raise 'already started' if @started
42
+
43
+ @started = true
44
+ end
45
+
46
+ def finish; end
47
+
48
+ def request(req, body)
49
+ raise 'expected POST' unless req.method == 'POST'
50
+ raise 'expected application/json' unless req.content_type == 'application/json'
51
+
52
+ req.each do |key, value|
53
+ @result.headers[key] = value
54
+ end
55
+
56
+ @result.data = JSON.parse(body)
57
+ end
58
+ end
59
+
60
+ class MyOutputTest < Test::Unit::TestCase
61
+ include Fluent::Test::Helpers
62
+
63
+ DEFAULT_LOGGER = ::WEBrick::Log.new($stdout, ::WEBrick::BasicLog::FATAL)
64
+
65
+ def server_port
66
+ 19_881
67
+ end
68
+
69
+ def base_endpoint
70
+ "http://127.0.0.1:#{server_port}"
71
+ end
72
+
73
+ def setup
74
+ Fluent::Test.setup
75
+ end
76
+
77
+ # default configuration for tests
78
+ def config
79
+ %(
80
+ active_gate_url #{base_endpoint}/logs
81
+ api_token secret
82
+ )
83
+ end
84
+
85
+ def events
86
+ [
87
+ { 'message' => 'hello', 'num' => 10, 'bool' => true },
88
+ { 'message' => 'hello', 'num' => 11, 'bool' => false }
89
+ ]
90
+ end
91
+
92
+ def create_driver(conf = config)
93
+ d = Fluent::Test::Driver::Output.new(Fluent::Plugin::DynatraceOutput).configure(conf)
94
+ @agent = FakeAgent.new(d.instance.agent)
95
+ d.instance.agent = @agent
96
+ d
97
+ end
98
+
99
+ sub_test_case 'configuration' do
100
+ test 'required configurations are applied' do
101
+ d = create_driver
102
+ assert_equal "http://127.0.0.1:#{server_port}/logs", d.instance.active_gate_url
103
+ assert_equal 'secret', d.instance.api_token
104
+ end
105
+
106
+ test 'ssl_verify_none false by default' do
107
+ d = create_driver
108
+ assert_equal false, d.instance.ssl_verify_none
109
+ end
110
+
111
+ test 'use ssl and verify certificates if https endpoint provided' do
112
+ d = create_driver(%(
113
+ active_gate_url https://example.dynatrace.com/logs
114
+ api_token secret
115
+ ))
116
+
117
+ assert_equal true, d.instance.agent.original_agent.use_ssl?
118
+ assert_nil d.instance.agent.original_agent.verify_mode
119
+ end
120
+
121
+ test 'use ssl and skip verification if https endpoint and ssl_verify_none' do
122
+ d = create_driver(%(
123
+ active_gate_url https://example.dynatrace.com/logs
124
+ api_token secret
125
+ ssl_verify_none true
126
+ ))
127
+
128
+ assert_equal true, d.instance.agent.original_agent.use_ssl?
129
+ assert_equal OpenSSL::SSL::VERIFY_NONE, d.instance.agent.original_agent.verify_mode
130
+ end
131
+ end
132
+
133
+ sub_test_case 'tests for #write' do
134
+ test 'Write all records as a JSON array' do
135
+ d = create_driver
136
+ t = event_time('2016-06-10 19:46:32 +0900')
137
+ d.run do
138
+ d.feed('tag', t, { 'message' => 'this is a test message', 'amount' => 53 })
139
+ d.feed('tag', t, { 'message' => 'this is a second test message', 'amount' => 54 })
140
+ end
141
+
142
+ assert_equal 2, d.instance.agent.result.data.length
143
+
144
+ content = d.instance.agent.result.data[0]
145
+
146
+ assert_equal "fluent-plugin-dynatrace v#{Fluent::Plugin::DynatraceOutputConstants.version}",
147
+ d.instance.agent.result.headers['user-agent']
148
+ assert_equal content['message'], 'this is a test message'
149
+ assert_equal content['amount'], 53
150
+ end
151
+ end
152
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-dynatrace
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dynatrace Open Source Engineering
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.22
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.22
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '3'
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '2'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '3'
53
+ - !ruby/object:Gem::Dependency
54
+ name: rake
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - '='
58
+ - !ruby/object:Gem::Version
59
+ version: 13.0.3
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '='
65
+ - !ruby/object:Gem::Version
66
+ version: 13.0.3
67
+ - !ruby/object:Gem::Dependency
68
+ name: rubocop
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '='
72
+ - !ruby/object:Gem::Version
73
+ version: 1.9.1
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '='
79
+ - !ruby/object:Gem::Version
80
+ version: 1.9.1
81
+ - !ruby/object:Gem::Dependency
82
+ name: rubocop-rake
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '='
86
+ - !ruby/object:Gem::Version
87
+ version: 0.5.1
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '='
93
+ - !ruby/object:Gem::Version
94
+ version: 0.5.1
95
+ description:
96
+ email:
97
+ - opensource@dynatrace.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - ".github/workflows/integration.yaml"
103
+ - ".github/workflows/lint.yaml"
104
+ - ".github/workflows/release.yaml"
105
+ - ".github/workflows/unit.yaml"
106
+ - ".gitignore"
107
+ - ".rubocop.yml"
108
+ - CODE_OF_CONDUCT.md
109
+ - Gemfile
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - fluent-plugin-dynatrace.gemspec
114
+ - lib/fluent/plugin/dynatrace_constants.rb
115
+ - lib/fluent/plugin/out_dynatrace.rb
116
+ - test/.rubocop.yml
117
+ - test/integration/fixtures/docker-compose.yaml
118
+ - test/integration/fixtures/fluent/Dockerfile
119
+ - test/integration/fixtures/fluent/entrypoint.sh
120
+ - test/integration/fixtures/fluent/fluent.conf
121
+ - test/integration/fixtures/logsink/Dockerfile
122
+ - test/integration/fixtures/logsink/server.js
123
+ - test/integration/integration_test.rb
124
+ - test/plugin/out_dynatrace_test.rb
125
+ homepage: https://www.dynatrace.com/
126
+ licenses:
127
+ - Apache-2.0
128
+ metadata:
129
+ bug_tracker_uri: https://github.com/dynatrace-oss/fluent-plugin-dynatrace/issues
130
+ documentation_uri: https://github.com/dynatrace-oss/fluent-plugin-dynatrace
131
+ source_code_uri: https://github.com/dynatrace-oss/fluent-plugin-dynatrace
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: 2.4.0
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.1.4
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: A fluentd output plugin for sending logs to the Dynatrace Generic log ingest
151
+ API v2
152
+ test_files: []