fluent-plugin-http_forward 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d17721c462207dd57050c8f0549ca074ad1ca630
4
+ data.tar.gz: 2232c90bdb2fee35784415dcfa506c0707de10f2
5
+ SHA512:
6
+ metadata.gz: 9e31ea459957415c2f87a9097c5ca052b6fb21d558344e0384b861c53e05b297f54d261e8516a0b9dc8f7ac4e048e6205d91fd7f0c69e81e167fb0c71fe410fd
7
+ data.tar.gz: f42b9ea013bd072c3150f1f84f251d4cc69127c6ce5ca789f9ee5fc0f67973bc796788d4283bfe0d0b2c22372505fd0b70f92ad4813725d076133bd93f33399d
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
data/CHANGELOG.txt ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ v0.1.0
4
+ ---------------
5
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-http_batch.gemspec
4
+ gemspec
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,43 @@
1
+ # Fluent::Plugin::HttpForward
2
+
3
+ This gem provides a buffered HTTP output plugin for Fluentd which also optionally supports authentication.
4
+
5
+ ## Requirements
6
+
7
+ * Fluetnd v0.14+
8
+
9
+ ## Installation
10
+
11
+ ```ruby
12
+ gem 'fluent-plugin-http_forward'
13
+ ```
14
+
15
+ ## Configuration Options
16
+
17
+ ```
18
+ <match **>
19
+ @type http_forward
20
+ url http://remote.example.com/%{tag}
21
+ verb post
22
+ content_type application/json # optional override
23
+ <authentication>
24
+ method basic
25
+ username user
26
+ password pass
27
+ </authentication>
28
+ <format>
29
+ @type json
30
+ </format>
31
+ <buffer tag> # if buffering, specify tag for in_http compat
32
+ chunk_limit_size 8388608 # optional, maximum chunk size, default 8MB
33
+ total_limit_size 536760912 # optional, maximum buffer size, default 512M
34
+ chunk_records_limit 10 # optional, maximum records per chunk
35
+ flush_interval 60 # optional, maximum time between flush
36
+ flush_thread_count 1 # optional, async threads to flush buffer
37
+ </buffer>
38
+ ```
39
+
40
+ ## Status
41
+
42
+ At present, only the JSON format has been tested. There's an optional msgpack format available that is as of yet untested because in_http does not currently support it.
43
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fluent/plugin/http_batch"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/examples/data.sh ADDED
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+
3
+ for x in `seq 1 10000`; do
4
+ echo "RPUSH test \"{ \\\"message\\\": \\\"${x}\\\" }\""
5
+ done | redis-cli --pipe
6
+
@@ -0,0 +1,36 @@
1
+ <source>
2
+ @type redis_list_poller
3
+ tag redis.content
4
+ host 127.0.0.1
5
+ key test
6
+ batch_size 1
7
+ poll_interval 0.1
8
+ <parse>
9
+ @type json
10
+ </parse>
11
+ </source>
12
+
13
+ <source>
14
+ @type http
15
+ bind 127.0.0.1
16
+ format json
17
+ </source>
18
+
19
+ <match redis.content>
20
+ @type http_forward
21
+ url http://127.0.0.1:9880/dummy_tag
22
+ flush_thread_count 2
23
+ <format>
24
+ @type json
25
+ </format>
26
+ <buffer tag>
27
+ @type memory
28
+ chunk_records_limit 10
29
+ </buffer>
30
+ flush_interval 1
31
+ </match>
32
+
33
+ <match dummy_tag>
34
+ @type flowcounter_simple
35
+ unit second
36
+ </match>
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "fluent-plugin-http_forward"
5
+ spec.version = "0.1.0"
6
+ spec.authors = ["Jonathan Serafini"]
7
+ spec.email = ["jonathan@serafini.ca"]
8
+
9
+ spec.summary = %q{A buffered HTTP batching output for Fluentd}
10
+ spec.description = spec.summary
11
+ spec.homepage = "https://github.com/JonathanSerafini/fluent-plugin-http_forward"
12
+
13
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
14
+ spec.executables = []
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_development_dependency "bundler", "~> 1.11"
18
+ spec.add_development_dependency "rake", "~> 10.0"
19
+
20
+ spec.add_runtime_dependency "fluentd", [">= 0.14.0", "< 2"]
21
+ spec.add_runtime_dependency "http", [">= 2.0.0", "< 3.0.0"]
22
+ end
@@ -0,0 +1,181 @@
1
+ require 'fluent/plugin/output'
2
+ require 'fluent/plugin_mixin/chunk_json_streamer'
3
+
4
+ module Fluent
5
+ module Plugin
6
+ class HttpForwardOutput < Output
7
+ Fluent::Plugin.register_output('http_forward', self)
8
+ helpers :timer
9
+
10
+ # http target parameters
11
+ # - url: the URL to upload to, ex.: http://iamateacup:8080/path/%{tag}
12
+ # the URI may contain the %{tag} pattern which will be replaced
13
+ # - verb: the HTTP verb to use
14
+ config_param :url, :string
15
+ config_param :verb, :string, :default => :post,
16
+ :list => %w(put post)
17
+
18
+ # an optional Content-Type header override, this may be unset and will be
19
+ # automatically detected based on the serializing format
20
+ config_param :content_type, :string, :default => nil
21
+
22
+ # http authentication parameters
23
+ config_section :authentication, :init => true, :multi => false do
24
+ config_param :method, :string, :default => nil, :list => %(basic)
25
+ config_param :username, :string, :default => nil
26
+ config_param :password, :string, :default => nil, :secret => true
27
+ end
28
+
29
+ # output serializing format
30
+ config_section :format, :init => true, :multi => false do
31
+ config_param :@type, :string, :default => "json",
32
+ :list => %w(msgpack json)
33
+ end
34
+
35
+ # Initialize new output plugin
36
+ # @since 0.1.0
37
+ # @return [NilClass]
38
+ def initialize
39
+ super
40
+ require 'http'
41
+ end
42
+
43
+ # Initialize attributes and parameters
44
+ # @since 0.1.0
45
+ # @return [NilClass]
46
+ def configure(config)
47
+ super
48
+
49
+ configure_params(config)
50
+ end
51
+
52
+ # Configure plugin parameters
53
+ # @since 0.1.0
54
+ # @return [NilClass]
55
+ def configure_params(config)
56
+ unless config.key?("content_type")
57
+ @content_type = case @format['@type']
58
+ when 'json' then 'application/json'
59
+ when 'msgpack' then 'application/x-msgpack'
60
+ else nil
61
+ end
62
+ end
63
+ end
64
+
65
+ # Prepare the plugin event loop
66
+ # @since 0.1.0
67
+ # @return [NilClass]
68
+ def start
69
+ super
70
+ start_connection
71
+ end
72
+
73
+ # Prepare the HTTP client object which provides a baseline for future
74
+ # request objects.
75
+ # @since 0.1.0
76
+ # @return [HTTP::Client]
77
+ def start_connection
78
+ @connection = HTTP::Client.new(
79
+ :headers => @headers
80
+ )
81
+
82
+ if @authentication['method']
83
+ @connection = @connection.basic_auth(
84
+ :user => @authentication['username'],
85
+ :pass => @authentication['password']
86
+ )
87
+ end
88
+
89
+ if @content_type
90
+ @connection = @connection.headers(
91
+ 'Content-Type' => @content_type
92
+ )
93
+ end
94
+
95
+ @connection
96
+ end
97
+
98
+ # Tear down the plugin
99
+ # @since 0.1.0
100
+ # @return [NilClass]
101
+ def shutdown
102
+ @connection.close
103
+ super
104
+ end
105
+
106
+ # Enforce the usage of the MsgPack streaming method internally so as to
107
+ # ensure that we have a consistent buffering mechanism.
108
+ # @since 0.1.0
109
+ # @return [NilClass]
110
+ def execute_chunking(tag, es, enqueue: false)
111
+ return handle_stream_with_standard_format(tag, es, enqueue: enqueue)
112
+ end
113
+
114
+ # Format the URL for a given request, and optionally replace the tag
115
+ # placerholder in the URI.
116
+ # @since 0.1.0
117
+ # @return [String] the url
118
+ def format_url(tag, time, data)
119
+ @url.sub(/%{tag}/, tag)
120
+ end
121
+
122
+ # Format the Headers for a given request.
123
+ # @since 0.1.0
124
+ # @return [Hash] the header hash
125
+ def format_headers(tag, time, data)
126
+ @headers
127
+ end
128
+
129
+ # Format the Body for a given request depending on the Serializing
130
+ # format.
131
+ # @since 0.1.0
132
+ # @return [String] the request body
133
+ def format_body(tag, time, chunk)
134
+ case @format["@type"]
135
+ when "json"
136
+ chunk.extend Fluent::PluginMixin::ChunkJsonStreamer
137
+ serializer_proc = chunk.method(:to_json_stream)
138
+ else
139
+ serializer_proc = chunk.method(:to_msgpack_stream)
140
+ end
141
+
142
+ body = serializer_proc.call
143
+ end
144
+
145
+ # Upload the request body to the remote end point
146
+ # @since 0.1.0
147
+ # @return [Response] the HTTP response object
148
+ def upload(tag, time, content)
149
+ headers = format_headers(tag, nil, content)
150
+ url = format_url(tag, nil, content)
151
+
152
+ @connection.request(@verb, url, body: content, headers: headers)
153
+ end
154
+
155
+ # Process a chunk of records synchronously, committing successful
156
+ # uploads and re-queueing failures.
157
+ # @since 0.1.0
158
+ # @return [Nil]
159
+ def write(chunk)
160
+ tag = chunk.metadata.tag
161
+ content = format_body(tag, nil, chunk)
162
+
163
+ response = upload(tag, nil, content)
164
+
165
+ if response.code <= 299
166
+ commit_write(chunk.unique_id)
167
+ else
168
+ @log.warn "failed to flush buffer", code: response.code
169
+ end
170
+ end
171
+
172
+ # Process a chunk of records asynchronously, committing successful
173
+ # uploads and re-queueing failures.
174
+ # @since 0.1.0
175
+ # @return [Nil]
176
+ def try_write(chunk)
177
+ write(chunk)
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,38 @@
1
+ module Fluent
2
+ module PluginMixin
3
+ module ChunkJsonStreamer
4
+ # Iterate over records in chunk
5
+ # @since 0.1.0
6
+ # @returns [Array] an array of record objects
7
+ def records
8
+ records = []
9
+ each do |time, record|
10
+ records << record
11
+ end
12
+ records
13
+ end
14
+
15
+ # Serialize the chunk to a Json object
16
+ # @since 0.1.0
17
+ # @returns [String] the serialized object
18
+ def to_json_stream
19
+ json_serializer_proc.call(records)
20
+ end
21
+
22
+ private
23
+
24
+ # Load relevant Json modules and cache the serializing method
25
+ # @since 0.1.0
26
+ # @returns [Method] a proc which serializes to json
27
+ def json_serializer_proc
28
+ @json_packer ||= begin
29
+ require 'oj'
30
+ Oj.default_options = { mode: :compat }
31
+ Oj.method(:dump)
32
+ rescue LoadError
33
+ Yajl.method(:dump)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-http_forward
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Serafini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fluentd
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.14.0
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '2'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.14.0
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '2'
61
+ - !ruby/object:Gem::Dependency
62
+ name: http
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.0.0
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: 3.0.0
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.0.0
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: 3.0.0
81
+ description: A buffered HTTP batching output for Fluentd
82
+ email:
83
+ - jonathan@serafini.ca
84
+ executables: []
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - ".gitignore"
89
+ - CHANGELOG.txt
90
+ - Gemfile
91
+ - LICENSE.txt
92
+ - README.md
93
+ - Rakefile
94
+ - bin/console
95
+ - bin/setup
96
+ - examples/data.sh
97
+ - examples/standalone.conf
98
+ - flunt-plugin-http_forward.gemspec
99
+ - lib/fluent/plugin/out_http_forward.rb
100
+ - lib/fluent/plugin_mixin/chunk_json_streamer.rb
101
+ homepage: https://github.com/JonathanSerafini/fluent-plugin-http_forward
102
+ licenses: []
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.5.2
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: A buffered HTTP batching output for Fluentd
124
+ test_files: []
125
+ has_rdoc: