fluent-output-router 0.9.1

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.
Files changed (3) hide show
  1. checksums.yaml +15 -0
  2. data/lib/fluent/plugin/out_router.rb +152 -0
  3. metadata +62 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2I3MzMzMDk2OWQ0MjIwZGQxZTFhOTcwNDE0YmJlZTA4ZjZkNjczZQ==
5
+ data.tar.gz: !binary |-
6
+ MDUzODc1NjM2MTEzMTA5MTM3OTQ0NzRlY2UxZjY3ZjVlN2ZhMDE1Zg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTQ5NGM1YTU0ODYxNDJiMmQ2YjU1MDM4NWM5ODQxNTBiYWUzYTNhNTU1MDZm
10
+ ODZlYjdkOWU2MTVmZWMxZjBkMDhhZTUwYmQ0ZGJkNzEzMTQxNmExOTMwMDBl
11
+ YTQwYTYxODhkNDgyYTg5OWFlZWFhNWM2NzNmZWMzNWNlMDA5YjA=
12
+ data.tar.gz: !binary |-
13
+ MDg1OTVhZDA1YTg0Zjk1OWExZWNhNGQyODEwOGFhYjlkZTYxYmZkMjhlZTdh
14
+ YjFlZjFjNzJlNjYwZjE2MDgyNmVlMWMxMmFmY2NkOGY4ZWZhYzc1MjYzYTBl
15
+ MWViNDJiMGUzZGZiOGYwNzVhYzkyZGE4YTU1M2NmZDNjOTYyMWY=
@@ -0,0 +1,152 @@
1
+ require 'erb'
2
+ require 'rubygems'
3
+ require 'json'
4
+
5
+ module Fluent
6
+ class RouterOutput < Fluent::Output
7
+
8
+ Fluent::Plugin.register_output('router', self)
9
+ MIN_REAPER_INTERVAL = 5 #sec
10
+ ROUTER_STATE_FILE = "router_state.json"
11
+
12
+ def initialize
13
+ super
14
+ @outputs = {}
15
+ @last_used_time = {}
16
+ @last_reaper_run = Time.now
17
+ end
18
+
19
+ def configure(conf)
20
+ super
21
+ log "Starting the out_router plugin"
22
+ @inactivity_timeout = conf['inactivity_timeout'].to_i
23
+ @output_config = conf.elements.select { |e| e.name == 'config' }.first
24
+ mark_used @output_config
25
+ filename = File.join(File.dirname(Fluent::DEFAULT_CONFIG_PATH),
26
+ ROUTER_STATE_FILE)
27
+ @state_serializer = ConsistentArrayStorage.new(filename)
28
+ output_keys = @state_serializer.load
29
+
30
+ # Restarts all output plugins for each stored key after a crash
31
+ # or a stop.
32
+ # This way we ensure every needed buffered output plugin, like
33
+ # the s3 plugin, will start after a crash and flush its buffer
34
+ # files to s3.
35
+ log "Reading file " + filename +
36
+ " and found output keys: " + output_keys.to_json
37
+ output_keys.each do |key|
38
+ start_output(key)
39
+ end
40
+ end
41
+
42
+ def emit(tag, es, chain)
43
+ # This is the router logic. Splitting tag on character '.'
44
+ # uses the value after '.' as the router key.
45
+ key = tag.split(/\./)[1]
46
+ out = @outputs[key]
47
+ unless out
48
+ out = start_output(key)
49
+ end
50
+ out.emit tag, es, chain
51
+ now = Time.now
52
+ @last_used_time[key] = now
53
+ run_reaper(now)
54
+ end
55
+
56
+ private
57
+
58
+ def start_output(key)
59
+ log "Starting a new output of type " + @output_config['type'] +
60
+ " for key #{key}"
61
+ @outputs[key] = Fluent::Plugin.new_output @output_config['type']
62
+ @last_used_time[key] = Time.now
63
+ config = @output_config.clone
64
+ template! config, :key => key
65
+ out = @outputs[key]
66
+ out.configure config
67
+ out.start
68
+ @state_serializer.store(@outputs.keys)
69
+ out
70
+ end
71
+
72
+ def stop_output(key)
73
+ log "Stopping output of type " + @output_config['type'] +
74
+ " for key #{key} due to inactivity (no data comming in)"
75
+ out = @outputs.delete(key)
76
+ @last_used_time.delete(key)
77
+ out.shutdown
78
+ @state_serializer.store(@outputs.keys)
79
+ end
80
+
81
+ def mark_used(conf)
82
+ conf.used = conf.keys
83
+ conf.elements.each { |e| mark_used e }
84
+ end
85
+
86
+ # MUTABLE. WHICH ALSO MEANS IT IS TERRIBLE.
87
+ def template!(conf, keys)
88
+ conf.each do |k,v|
89
+ case v
90
+ when Hash
91
+ conf[k] = template v, keys
92
+ when String
93
+ conf[k] = ERB.new(v).result(binding)
94
+ else
95
+ $log.error "Template error #{v.inspect}"
96
+ $log.error_backtrace
97
+ end
98
+ end
99
+ end
100
+
101
+ def log(string)
102
+ $log.info "out_router: " + string
103
+ end
104
+
105
+ # This is the reaper that is used to avoids resource leaks
106
+ # It will stop any active output plugin that does not get any input
107
+ def run_reaper(now)
108
+ if now - @last_reaper_run > MIN_REAPER_INTERVAL then
109
+ @last_used_time.each {|key, stored_time|
110
+ if now - stored_time > @inactivity_timeout then
111
+ stop_output(key)
112
+ end }
113
+ @last_reaper_run = now
114
+ end
115
+ end
116
+ end
117
+
118
+ # ConsistentArrayStorage serializes/deserializes an array to disc.
119
+ # It uses two files.
120
+ # First it writes the serialized array into a tmp file and then renames
121
+ # the tmp file to the correct filename.
122
+ # The rename action is fast and Linux gives a guarantee that
123
+ # the rename operation is atomic (on local discs). This removes the risk
124
+ # of any kind of crash leaving the @store_file file in a bad state.
125
+ class ConsistentArrayStorage
126
+ def initialize(filename)
127
+ @store_file = filename
128
+ @temp_file = filename + ".tmp"
129
+ end
130
+
131
+ def store(array)
132
+ file = File.open(@temp_file, 'w')
133
+ file << array.to_json
134
+ file.close
135
+ File.rename(@temp_file, @store_file)
136
+ end
137
+
138
+ #Returns the array stored on disc.
139
+ #Returns an empty array if the file does not exist
140
+ def load
141
+ if File.exists?(@store_file) then
142
+ file = File.open(@store_file, 'r')
143
+ json_string = file.read
144
+ file.close
145
+ JSON.parse(json_string)
146
+ else
147
+ []
148
+ end
149
+ end
150
+ end
151
+
152
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-output-router
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - David Almroth
8
+ - Torbjörn Norinder
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 0.10.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 0.10.0
28
+ description: Depending on the message tag, this fluent plugin can start new instances
29
+ of any other available output plugins for fluent (for example the fluent-plugin-s3).
30
+ This way it is possible to have one fluent input get split into separate (s3) output
31
+ instances. The output instances will be shut down individually when there is no
32
+ traffic to an instance.
33
+ email: david@campanja.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/fluent/plugin/out_router.rb
39
+ homepage: https://github.com/campanja/fluent-output-router
40
+ licenses: []
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.0.7
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: Can dynamically route fluentd messages based on the tag content
62
+ test_files: []