fluent-plugin-http_forward 0.1.0

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: 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: