fluent-plugin-aggregate 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 +7 -0
- data/LICENSE +21 -0
- data/README.md +65 -0
- data/Rakefile +11 -0
- data/lib/fluent/plugin/filter_aggregate.rb +176 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
+
```
|
data/Rakefile
ADDED
@@ -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: []
|