fluent-plugin-aggregate 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b58e7447b1b2957f0bc50b0f1266a0773b9865e894a7c0ec7284adf8f1755ed9
4
+ data.tar.gz: 42692ba88949646f48152a22d2f83155df34f5af9e90dd446c7796acbeb082ea
5
+ SHA512:
6
+ metadata.gz: f1b7d30f0c24d17a3f9a73deb82bc17fe9b476d6e55346795b4dc2f7f90859b0365b05c1f1be1d7439887d0a926904dce4fd2f6a27af9642b395ae1700fdac2a
7
+ data.tar.gz: c2110a4e5a2917041ae110f88a079f9b4cd4f4131a5fb08614bbf2aa0a3a05d0601931fdea64a1f062c63df22e9b5b675edba03b2c1e8ffcdc243c7551e15c01
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 superguillen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,65 @@
1
+ # fluent-plugin-aggregate , a plugin for [Fluentd](http://fluentd.org)
2
+
3
+ A fluentd plugin to aggregate events by fields over time.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'fluent-plugin-aggregate'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install fluent-plugin-aggregate --no-document
18
+
19
+ ## Requirements
20
+
21
+ - Ruby 2.1 or later
22
+ - fluentd v0.12 or later
23
+ - aggregate v0.0.1 or later
24
+
25
+ ## Usage
26
+ ### Filter plugin (@type 'aggregate')
27
+
28
+ Aggregate events grouping by fields over time.
29
+
30
+ ```
31
+ <filter>
32
+ @type aggregate
33
+ intervals 5s
34
+ keep_interval 1s
35
+ group_fields field_group1,field_group2
36
+ aggregate_fields numeric_field1, numeric_field2
37
+ aggregations mean,median
38
+ </filter>
39
+ ```
40
+ ### Common parameters
41
+ ### intervals
42
+ Intervals for the aggregatios, this plugin support multi interval aggregatios
43
+ ```
44
+ intervals 5s,10s,20s
45
+ ```
46
+ ### keep_interval
47
+ Additional time to wait fof arrive events (used when events has a delay in the origin)
48
+ ```
49
+ keep_interval 5s
50
+ ```
51
+ ### group_fields
52
+ Fields to group events (like group by in SQL)
53
+ ```
54
+ group_fields tx,region
55
+ ```
56
+ ### aggregate_fields
57
+ Fields to apply aggregation funtions (like mean, median, sum, etc), this plugin support multiple aggregations fields.
58
+ ```
59
+ aggregate_fields response_time,pressure
60
+ ```
61
+ ### aggregations
62
+ Aggregate funtions to apply, this plugin support multiple aggregations fields.
63
+ ```
64
+ aggregations sum,min,max,mean,median,variance,standard_deviation
65
+ ```
@@ -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,176 @@
1
+ module Fluent
2
+ class FilterAggregate < Filter
3
+ Fluent::Plugin.register_filter('aggregate', self)
4
+ config_param :aggregator_suffix_name, :string, :default => nil
5
+ config_param :time_format, :string, :default =>'%Y-%m-%dT%H:%M:%S.%L%:z'
6
+ config_param :output_time_format, :string, :default =>'%Y-%m-%dT%H:%M:%S.%L%z'
7
+ config_param :intervals, :array, :default =>[5], value_type: :time,
8
+ :desc => 'Interval for accumulative aggregation'
9
+ config_param :flush_interval, :time, :default =>5,
10
+ :desc => 'Interval for emmit aggregation events'
11
+ config_param :keep_interval, :time, :default =>10,
12
+ :desc => 'Interval to wait for events to aggregate'
13
+ config_param :group_fields, :string, :default =>'field1,field2'
14
+ config_param :aggregate_fields, :string, :default =>'aggregate_field1,aggregate_field2'
15
+ config_param :time_field, :string, :default =>'timestamp'
16
+ config_param :field_no_data_value, :string, :default =>'no_data'
17
+ config_param :emit_original_message, :bool, :default => true
18
+ config_param :aggregate_event_tag, :string, :default => 'aggregate'
19
+ config_param :aggregations, :string, :default => 'sum,min,max,mean,median,variance,standard_deviation'
20
+ config_param :temporary_status_file_path, :string, :default => nil, :desc => 'File to store aggregate information when the agent down'
21
+ config_param :load_temporarystatus_file_enabled, :bool, :default => true, :desc => 'Enable load saved data from file (if exist status file)'
22
+
23
+ VALID_AGGREGATIONS = ['sum','min','max','mean','median','variance','standard_deviation']
24
+
25
+ def initialize
26
+ super
27
+ end
28
+
29
+ def configure(conf)
30
+ super
31
+
32
+ require 'dataoperations-aggregate'
33
+
34
+ @hash_time_format = "%Y-%m-%dT%H"
35
+ @interval_seconds = 3600
36
+ @intervals[1..-1].each{|interval|
37
+ case interval
38
+ when 1,5,10,20,30,60,120,180,240,300,600,900,1200,1800,3600
39
+ if ! (interval % @intervals[0]) == 0
40
+ raise Fluent::ConfigError, "interval must be multiple of default_aggregate_interval(#{@default_aggregate_interval}s)"
41
+ end
42
+ else
43
+ raise Fluent::ConfigError, "interval must set to 1s,5s,10s,20s,30s,1m,5m,10m"
44
+ end
45
+ }
46
+
47
+ @group_field_names = @group_fields.split(",")
48
+ @aggregate_field_names = @aggregate_fields.split(",")
49
+ @aggregation_names = @aggregations.split(",")
50
+ @aggregator_name = "#{Socket.gethostname}"
51
+ @aggregator_name = "#{@aggregator_name}-#{@aggregator_suffix_name}" unless @aggregator_suffix_name.nil?
52
+
53
+ @aggregation_names.each {|operation|
54
+ if ! VALID_AGGREGATIONS.include?(operation)
55
+ raise Fluent::ConfigError, "aggregations must set any combination of sum,min,max,mean,median,variance,standard_deviation "
56
+ end
57
+ }
58
+
59
+ @aggregator = {}
60
+ if load_temporarystatus_file_enabled && ! @temporary_status_file_path.nil? && File.exist?(@temporary_status_file_path) && file_status = File.open(@temporary_status_file_path,'r')
61
+ begin
62
+ @aggregator=eval(file_status.read)
63
+ file_status.close
64
+ File.delete(@temporary_status_file_path)
65
+ log.info "Temporary information loaded from temporary_status_file_path:#{@temporary_status_file_path} before startup"
66
+ rescue Exception => e
67
+ log.warn "Failed to load temporary_status_file_path:#{@temporary_status_file_path}"
68
+ log.warn e.message
69
+ log.warn e.backtrace.inspect
70
+ end
71
+ end
72
+
73
+ @aggregator = {} unless @aggregator.is_a?(Hash)
74
+
75
+ log.warn "temporary_status_file_path is empty, is recomended using to avoid lost statistic information beetween restarts." if @temporary_status_file_path.nil?
76
+ @aggregator_mutex = Mutex.new
77
+ @data_operations = DataOperations::Aggregate.new(aggregator: @aggregator,
78
+ time_format: @time_format,
79
+ time_field: @time_field,
80
+ output_time_format: @output_time_format,
81
+ intervals: @intervals,
82
+ flush_interval: @flush_interval,
83
+ keep_interval: @keep_interval,
84
+ field_no_data_value: @field_no_data_value,
85
+ processing_mode: :online,
86
+ log: log,
87
+ aggregation_names: @aggregation_names,
88
+ group_field_names: @group_field_names,
89
+ aggregate_field_names: @aggregate_field_names)
90
+ end
91
+
92
+ def filter(tag, time, record)
93
+ result = nil
94
+ begin
95
+ result = record unless ! emit_original_message
96
+
97
+ @data_operations.add_events(result)
98
+ result
99
+ rescue => e
100
+ log.warn "failed to filter events", :error_class => e.class, :error => e.message
101
+ log.warn_backtrace
102
+ end
103
+ result
104
+ end
105
+
106
+ def start
107
+ super
108
+ @loop = Coolio::Loop.new
109
+ tw = TimerWatcher.new(@flush_interval, true, @log, &method(:aggregate_events))
110
+ tw.attach(@loop)
111
+ @thread = Thread.new(&method(:run))
112
+ end
113
+
114
+ def run
115
+ @loop.run
116
+ rescue
117
+ log.error "unexpected error", :error=>$!.to_s
118
+ log.error_backtrace
119
+ end
120
+
121
+ def shutdown
122
+ @loop.stop
123
+ @thread.join
124
+
125
+ if load_temporarystatus_file_enabled && ! @temporary_status_file_path.nil? && file_status = File.open(@temporary_status_file_path,'w')
126
+ begin
127
+ file_status.write @aggregator
128
+ file_status.close
129
+ log.info "Temporary information stored in temporary_status_file_path:#{@temporary_status_file_path} before shutdown"
130
+ rescue Exception => e
131
+ log.warn "Failed to load temporary_status_file_path:#{@temporary_status_file_path}"
132
+ log.warn e.message
133
+ log.warn e.backtrace.inspect
134
+ end
135
+ end
136
+
137
+ super
138
+ end
139
+
140
+ def aggregate_events
141
+
142
+ #log.trace @aggregator
143
+ @aggregator_mutex.synchronize do
144
+ data_aggregated = @data_operations.aggregate_events
145
+ data_aggregated.each{|s_interval,data_aggregated|
146
+ #log.trace data_aggregated
147
+ es = MultiEventStream.new
148
+ data_aggregated.each {|item|
149
+ es.add(item['time'], item)
150
+ }
151
+ unless es.empty?
152
+ tag="#{@aggregate_event_tag}.#{s_interval}"
153
+ router.emit_stream(tag, es)
154
+ end
155
+ } if data_aggregated
156
+ end
157
+
158
+ #rescue Exception => e
159
+ # $log.error e
160
+ end
161
+
162
+ class TimerWatcher < Coolio::TimerWatcher
163
+ def initialize(interval, repeat, log, &callback)
164
+ @callback = callback
165
+ @log = log
166
+ super(interval, repeat)
167
+ end
168
+ def on_timer
169
+ @callback.call
170
+ rescue
171
+ @log.error $!.to_s
172
+ @log.error_backtrace
173
+ end
174
+ end
175
+ end
176
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-aggregate
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - superguillen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-16 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.10.58
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.10.58
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: dataoperations-aggregate
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.0.1
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.0.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.9.2
61
+ description: Filter aggregtation plugin for Fluent
62
+ email: superguillen.public@gmail.com
63
+ executables: []
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - lib/fluent/plugin/filter_aggregate.rb
71
+ homepage: https://github.com/superguillen/fluent-plugin-aggregate
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.0.3
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Filter aggregtation plugin for Fluent
94
+ test_files: []