fluent-plugin-gimbal-out-http 1.1.5.pre.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f82ebc471a2855aed2ad3462e5df3a6ceac5656
4
+ data.tar.gz: a85ae2faa3b718edd6002b3b27aaa7d3ffd20fcc
5
+ SHA512:
6
+ metadata.gz: 5eb1ae203708cf68069d06a88a0dc7a10b9d3f76265d90613552551e0731f577ae41525e394a17d87fcc5479b868015a3b42c48488a28b190f2315034a3e557f
7
+ data.tar.gz: 1e3e5bb18dde2371a9883d814d765b52a3fe2cdf8ee8966d10cc9ec7bf296f839367d13b45a0934fe88d281999cf497b1ac87fe95491380c6afa3f43da571575
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *~
2
+ \#*
3
+ .\#*
4
+ *.gem
5
+ .bundle
6
+ .ruby-version
7
+ Gemfile.lock
8
+ vendor
data/.travis.yml ADDED
@@ -0,0 +1,25 @@
1
+ rvm:
2
+ - 2.2
3
+ - 2.3
4
+ - 2.4.5
5
+ - 2.5.3
6
+ - 2.6.0
7
+ - ruby-head
8
+
9
+ os:
10
+ - linux
11
+ - osx
12
+
13
+ dist: trusty
14
+
15
+ gemfile:
16
+ - Gemfile
17
+
18
+ before_install:
19
+ - gem update --system=2.7.8
20
+
21
+ script: bundle exec rake test
22
+
23
+ matrix:
24
+ allow_failures:
25
+ - rvm: ruby-head
data/CHANGELOG.md ADDED
@@ -0,0 +1,58 @@
1
+ # Changelog
2
+
3
+ ### 1.1.5
4
+ * Add :raw serializer
5
+
6
+ ### 1.1.4
7
+ * Add custom formatter feature
8
+ * Tweak Travis CI tasks
9
+
10
+ ### 1.1.3
11
+ * Send query_string to endpoint_url
12
+
13
+ ### 1.1.2
14
+ * Added custom headers feature
15
+
16
+ ## 1.1.1
17
+ * Added plain text transport capability
18
+ * Added specify cacert file for ssl verify
19
+
20
+ ## 1.1.0
21
+ * Support for jwt token authentication
22
+
23
+ ## 1.0.1
24
+ * Added endpoint_url placeholder support
25
+
26
+ ## 1.0.0
27
+ * Use Fluentd v1 API
28
+
29
+ ## 0.2.0
30
+ ### Added
31
+ * SSL is now supported if `endpoint_url` uses the `https` scheme (uses ruby-2.1 syntax internally)
32
+ * New config: set `ssl_no_verify` to `true` to bypass SSL certificate verification.
33
+ Use at your own risk.
34
+ ### Changed
35
+ * Fixed tests:
36
+ * Removed some warnings
37
+ * Fixed failing binary test to use UTF-8
38
+ ### Removed
39
+ * Dropped support of Ruby 1.9-2.0
40
+
41
+ ## 0.1.4
42
+ * #11 Updated Fluentd dependency to: [">= 0.10.0", "< 2"]
43
+ * #10 `password` is now marked as a [secret option](https://github.com/fluent/fluentd/pull/604)
44
+
45
+ ## 0.1.3
46
+ * Added a new configuration option: `raise_on_error` (default: true)
47
+ * In order to let the plugin raise exceptions like it did in 0.1.1: keep using your configuration as-is
48
+ * In order to suppress all exceptions: add `raise_on_error false` to your configuration
49
+
50
+ ## 0.1.2
51
+ * #6 Catch all `StandardError`s during HTTP request to prevent td-agent from freezing
52
+
53
+ ## 0.1.1
54
+ * #2 Use yajl instead of json as json serializer
55
+ * #1 Fix a bug where a nil HTTP response caused the plugin to stop working
56
+
57
+ ## 0.1.0
58
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-out-http.gemspec
4
+ gemspec
data/ISSUE_TEMPLATE.md ADDED
@@ -0,0 +1,21 @@
1
+ #### Problem
2
+
3
+ ...
4
+
5
+ #### Steps to replicate
6
+
7
+ Provide example config and message
8
+
9
+ #### Expected Behavior or What you need to ask
10
+
11
+ ...
12
+
13
+ #### Using Fluentd and out_http plugin versions
14
+
15
+ * OS version
16
+ * Fluentd v0.12 or v0.14/v1.0
17
+ * paste result of ``fluentd --version`` or ``td-agent --version``
18
+ * out_http plugin 1.x.y or 0.x.y
19
+ * paste boot log of fluentd or td-agent
20
+ * paste result of ``fluent-gem list``, ``td-agent-gem list`` or your Gemfile.lock
21
+ * Bear Metal or Within Docker or Kubernetes or others? (optional)
data/LICENSE.txt ADDED
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # fluent-plugin-out-http, a plugin for [Fluentd](http://fluentd.org)
2
+
3
+ A generic [fluentd][1] output plugin for sending logs to an HTTP endpoint.
4
+
5
+ [![Build Status](https://travis-ci.org/fluent-plugins-nursery/fluent-plugin-out-http.svg?branch=master)](https://travis-ci.org/fluent-plugins-nursery/fluent-plugin-out-http)
6
+
7
+ ## Configuration options
8
+
9
+ <match *>
10
+ @type http
11
+ endpoint_url http://localhost.local/api/
12
+ http_method put # default: post
13
+ serializer json # default: form
14
+ rate_limit_msec 100 # default: 0 = no rate limiting
15
+ raise_on_error false # default: true
16
+ authentication basic # default: none
17
+ username alice # default: ''
18
+ password bobpop # default: '', secret: true
19
+ buffered true # default: false. Switch non-buffered/buffered mode
20
+ cacert_file /etc/ssl/endpoint1.cert # default: ''
21
+ token tokent # default: ''
22
+ custom_headers {"token":"arbitrary"} # default: nil
23
+ </match>
24
+
25
+ ## Usage notes
26
+
27
+ If you'd like to retry failed requests, consider using [fluent-plugin-bufferize][3].
28
+
29
+ ----
30
+
31
+ Heavily based on [fluent-plugin-growthforecast][2]
32
+
33
+ [1]: http://fluentd.org/
34
+ [2]: https://github.com/tagomoris/fluent-plugin-growthforecast
35
+ [3]: https://github.com/sabottenda/fluent-plugin-bufferize
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "fluent-plugin-gimbal-out-http"
5
+ gem.version = "1.1.5-1"
6
+ gem.authors = ["Marica Odagaki"]
7
+ gem.email = ["ento.entotto@gmail.com"]
8
+ gem.summary = %q{A generic Fluentd output plugin to send logs to an HTTP endpoint forked from fluent-plugin-out-http}
9
+ gem.description = gem.summary
10
+ gem.homepage = "https://github.com/PaeDae/fluent-plugin-gimbal-out-http"
11
+ gem.licenses = ["Apache-2.0"]
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ["lib"]
17
+
18
+ gem.required_ruby_version = '>= 2.1.0'
19
+
20
+ gem.add_runtime_dependency "yajl-ruby", "~> 1.0"
21
+ gem.add_runtime_dependency "fluentd", [">= 0.14.15", "< 2"]
22
+ gem.add_runtime_dependency "faraday", "0.15.4"
23
+ gem.add_runtime_dependency "net-http-persistent", "2.9.4"
24
+ gem.add_development_dependency "bundler"
25
+ gem.add_development_dependency "rake"
26
+ gem.add_development_dependency "test-unit", ">= 3.1.0"
27
+ end
@@ -0,0 +1,229 @@
1
+ require 'net/http/persistent'
2
+ require 'uri'
3
+ require 'yajl'
4
+ require 'fluent/plugin/output'
5
+ require 'faraday'
6
+
7
+ class Fluent::Plugin::HTTPOutput < Fluent::Plugin::Output
8
+ Fluent::Plugin.register_output('http', self)
9
+
10
+ helpers :compat_parameters, :formatter
11
+
12
+ DEFAULT_BUFFER_TYPE = "memory"
13
+ DEFAULT_FORMATTER = "json"
14
+
15
+ def initialize
16
+ super
17
+ end
18
+
19
+ # Endpoint URL ex. http://localhost.local/api/
20
+ config_param :endpoint_url, :string
21
+
22
+ # Set Net::HTTP.verify_mode to `OpenSSL::SSL::VERIFY_NONE`
23
+ config_param :ssl_no_verify, :bool, :default => false
24
+
25
+ # HTTP method
26
+ config_param :http_method, :enum, list: [:get, :put, :post, :delete], :default => :post
27
+
28
+ # form | json | text | raw
29
+ config_param :serializer, :enum, list: [:json, :form, :text, :raw], :default => :form
30
+
31
+ # Simple rate limiting: ignore any records within `rate_limit_msec`
32
+ # since the last one.
33
+ config_param :rate_limit_msec, :integer, :default => 0
34
+
35
+ # Raise errors that were rescued during HTTP requests?
36
+ config_param :raise_on_error, :bool, :default => true
37
+
38
+ # ca file to use for https request
39
+ config_param :cacert_file, :string, :default => ''
40
+
41
+ # custom headers
42
+ config_param :custom_headers, :hash, :default => nil
43
+
44
+ # 'none' | 'basic' | 'jwt' | 'bearer'
45
+ config_param :authentication, :enum, list: [:none, :basic, :jwt, :bearer], :default => :none
46
+ config_param :username, :string, :default => ''
47
+ config_param :password, :string, :default => '', :secret => true
48
+ config_param :token, :string, :default => ''
49
+ # Switch non-buffered/buffered plugin
50
+ config_param :buffered, :bool, :default => false
51
+
52
+ config_section :buffer do
53
+ config_set_default :@type, DEFAULT_BUFFER_TYPE
54
+ config_set_default :chunk_keys, ['tag']
55
+ end
56
+
57
+ config_section :format do
58
+ config_set_default :@type, DEFAULT_FORMATTER
59
+ end
60
+
61
+ def configure(conf)
62
+ compat_parameters_convert(conf, :buffer, :formatter)
63
+ super
64
+
65
+ @ssl_verify_mode = if @ssl_no_verify
66
+ OpenSSL::SSL::VERIFY_NONE
67
+ else
68
+ OpenSSL::SSL::VERIFY_PEER
69
+ end
70
+
71
+ @ca_file = @cacert_file
72
+ @last_request_time = nil
73
+ raise Fluent::ConfigError, "'tag' in chunk_keys is required." if !@chunk_key_tag && @buffered
74
+
75
+ http_methods = [:get, :put, :post, :delete]
76
+ @http_method = if http_methods.include? @http_method.intern
77
+ @http_method.intern
78
+ else
79
+ :post
80
+ end
81
+ puts @endpoint_url
82
+ @uri = URI.parse(@endpoint_url)
83
+ # ssl_verify = @ssl_no_verify
84
+ url = @uri.scheme + "://" + @uri.host + ":" + @uri.port.to_s
85
+ @adapter = Faraday.new(url: url, ssl: {verify:false} ) do |f|
86
+ f.request :retry, max: 5,
87
+ interval: 1,
88
+ interval_randomness: 0.5,
89
+ backoff_factor: 2,
90
+ methods: @http_method,
91
+ exceptions: %w(Errno::ETIMEDOUT
92
+ Faraday::TimeoutError
93
+ Faraday::Error::TimeoutError
94
+ Net::ReadTimeout).freeze
95
+
96
+ f.adapter :net_http_persistent
97
+ end
98
+
99
+ if @formatter_config = conf.elements('format').first
100
+ @formatter = formatter_create
101
+ end
102
+ end
103
+
104
+ def start
105
+ super
106
+ end
107
+
108
+ def shutdown
109
+ super
110
+ end
111
+
112
+ def format_url(tag, time, record)
113
+ @endpoint_url
114
+ end
115
+
116
+ def set_body(req, tag, time, record)
117
+ if @serializer == :json
118
+ set_json_body(req, record)
119
+ elsif @serializer == :text
120
+ set_text_body(req, record)
121
+ elsif @serializer == :raw
122
+ set_raw_body(req, record)
123
+ else
124
+ req.set_form_data(record)
125
+ end
126
+ req
127
+ end
128
+
129
+ def set_header(req, tag, time, record)
130
+ if @custom_headers
131
+ @custom_headers.each do |k,v|
132
+ req[k] = v
133
+ end
134
+ req
135
+ else
136
+ req
137
+ end
138
+ end
139
+
140
+ def set_json_body(req, data)
141
+ req.body = Yajl.dump(data)
142
+ req['Content-Type'] = 'application/json'
143
+ end
144
+
145
+ def set_text_body(req, data)
146
+ req.body = data["message"]
147
+ req['Content-Type'] = 'text/plain'
148
+ end
149
+
150
+ def set_raw_body(req, data)
151
+ req.body = data.to_s
152
+ req['Content-Type'] = 'application/octet-stream'
153
+ end
154
+
155
+ def create_request(tag, time, record)
156
+ url = format_url(tag, time, record)
157
+ uri = URI.parse(url)
158
+ req = Net::HTTP.const_get(@http_method.to_s.capitalize).new(uri.request_uri)
159
+ set_body(req, tag, time, record)
160
+ set_header(req, tag, time, record)
161
+ return req, uri
162
+ end
163
+
164
+ def http_opts(uri)
165
+ opts = {
166
+ :use_ssl => uri.scheme == 'https'
167
+ }
168
+ opts[:verify_mode] = @ssl_verify_mode if opts[:use_ssl]
169
+ opts[:ca_file] = File.join(@ca_file) if File.file?(@ca_file)
170
+ opts
171
+ end
172
+
173
+ def proxies
174
+ ENV['HTTPS_PROXY'] || ENV['HTTP_PROXY'] || ENV['http_proxy'] || ENV['https_proxy']
175
+ end
176
+
177
+ def send_request(record)
178
+ is_rate_limited = (@rate_limit_msec != 0 and not @last_request_time.nil?)
179
+ if is_rate_limited and ((Time.now.to_f - @last_request_time) * 1000.0 < @rate_limit_msec)
180
+ log.info('Dropped request due to rate limiting')
181
+ return
182
+ end
183
+
184
+ _ = @adapter.post(@uri.path) do |request|
185
+ request.headers['Content-Type'] = 'application/json'
186
+ request.body = Yajl.dump(record)
187
+ request.options.timeout = 60
188
+ request.options.open_timeout = 60
189
+ end
190
+ end # end send_request
191
+
192
+ def handle_record(tag, time, record)
193
+ if @formatter_config
194
+ record = @formatter.format(tag, time, record)
195
+ end
196
+ # req, uri = create_request(tag, time, record)
197
+ send_request(record)
198
+ end
199
+
200
+ def prefer_buffered_processing
201
+ @buffered
202
+ end
203
+
204
+ def format(tag, time, record)
205
+ [time, record].to_msgpack
206
+ end
207
+
208
+ def formatted_to_msgpack_binary?
209
+ true
210
+ end
211
+
212
+ def multi_workers_ready?
213
+ true
214
+ end
215
+
216
+ def process(tag, es)
217
+ es.each do |time, record|
218
+ handle_record(tag, time, record)
219
+ end
220
+ end
221
+
222
+ def write(chunk)
223
+ tag = chunk.metadata.tag
224
+ @endpoint_url = extract_placeholders(@endpoint_url, chunk.metadata)
225
+ chunk.msgpack_each do |time, record|
226
+ handle_record(tag, time, record)
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+
17
+ require 'fluent/test'
18
+
19
+ unless ENV.has_key?('VERBOSE')
20
+ nulllogger = Object.new
21
+ nulllogger.instance_eval {|obj|
22
+ def method_missing(method, *args)
23
+ # pass
24
+ end
25
+ }
26
+ $log = nulllogger
27
+ end
28
+
29
+ class Test::Unit::TestCase
30
+ end
31
+
32
+ require 'webrick'
33
+ require 'webrick/https'
34
+
35
+ # to handle POST/PUT/DELETE ...
36
+ module WEBrick::HTTPServlet
37
+ class ProcHandler < AbstractServlet
38
+ alias do_POST do_GET
39
+ alias do_PUT do_GET
40
+ alias do_DELETE do_GET
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ require 'fluent/plugin/formatter'
2
+
3
+ module Fluent
4
+ module Plugin
5
+ class TestFormatter < Formatter
6
+ Fluent::Plugin.register_formatter('test', self)
7
+
8
+ def configure(conf)
9
+ super
10
+ end
11
+
12
+ def format(tag, time, record)
13
+ output = {
14
+ "wrapped" => true,
15
+ "record" => record
16
+ }
17
+ output
18
+ end
19
+ end
20
+ end
21
+ end