fluent-plugin-rewrite-tag-filter 2.0.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2644562a37644d56fa8712f13d46aa0ff42cb9ec
4
- data.tar.gz: 22ac2b253497f823babee508e41d695b9bdc8218
2
+ SHA256:
3
+ metadata.gz: a4e1ce31eba327c311153c8eb2e96b8aef667bca6b92f9695c7b5a3fb11e7d58
4
+ data.tar.gz: fc5e7682a7476dffcfdef523f06401508dcb888d3b4cff39edab742950bf9506
5
5
  SHA512:
6
- metadata.gz: eaa2ee232b41ba0b6f387adb69621e78a411919d8d074c3ce014d344b4211a1dad7d47b61a06698cbc4fa0791de55a87111bf91383c47cee3f56f71299ad53e1
7
- data.tar.gz: ff33f9efd2106fc70e85023a139563764aa8414329066459bd9dd177133ee9ff8b9bff20119a50d8621c20573f3d7cdcfc3cb37c1d67a4f6210190b9523bb878
6
+ metadata.gz: '018336a8cf161d92674c7845fc021f4b01a11ce0762ff555067707345671b7d7b40d63f84ce308493beb36ce90ed581c90788905bdb0c14dc62125349ebcdc31'
7
+ data.tar.gz: ecbd7f9591d477aba1fa776a58648e04ac085f442ec685aefbd0dc7d48160c3ca2cd819fc79bc3a59910aa8c5663d595c0339f8e7ab14f32b2d7f542667add00
data/.travis.yml CHANGED
@@ -1,10 +1,10 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.4.2
5
- - 2.3.5
6
- - 2.2
7
- - 2.1
4
+ - 2.7.0
5
+ - 2.6.5
6
+ - 2.5.7
7
+ - 2.4.9
8
8
 
9
9
  # to avoid travis-ci issue since 2015-12-25
10
10
  before_install:
data/README.md CHANGED
@@ -3,10 +3,12 @@
3
3
  ## Overview
4
4
 
5
5
  Rewrite Tag Filter for [Fluentd](http://fluentd.org). It is designed to rewrite tags like mod_rewrite.
6
- Re-emit the record with rewrited tag when a value matches/unmatches with a regular expression.
6
+ Re-emit the record with rewritten tag when a value matches/unmatches with a regular expression.
7
7
  Also you can change a tag from Apache log by domain, status code (ex. 500 error),
8
8
  user-agent, request-uri, regex-backreference and so on with regular expression.
9
9
 
10
+ This is an output plugin because fluentd's `filter` doesn't allow tag rewrite.
11
+
10
12
  ## Requirements
11
13
 
12
14
  | fluent-plugin-rewrite-tag-filter | Fluentd | Ruby |
@@ -16,33 +18,39 @@ user-agent, request-uri, regex-backreference and so on with regular expression.
16
18
 
17
19
  ## Installation
18
20
 
19
- Install with `gem`, `fluent-gem` or `td-agent-gem` command as:
21
+ Install with `gem` or `td-agent-gem` command as:
20
22
 
21
23
  ```
22
24
  # for system installed fluentd
23
25
  $ gem install fluent-plugin-rewrite-tag-filter
24
26
 
25
- # for td-agent (Legacy)
26
- $ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-rewrite-tag-filter -v 1.5.6
27
-
28
27
  # for td-agent2 (with fluentd v0.12)
29
- $ sudo td-agent-gem install fluent-plugin-rewrite-tag-filter -v 1.5.6
28
+ $ sudo td-agent-gem install fluent-plugin-rewrite-tag-filter -v 1.6.0
29
+
30
+ # for td-agent3 (with fluentd v0.14)
31
+ $ sudo td-agent-gem install fluent-plugin-rewrite-tag-filter
30
32
  ```
31
33
 
34
+ For more details, see [Plugin Management](https://docs.fluentd.org/deployment/plugin-management)
35
+
32
36
  ## Configuration
33
37
 
34
38
  * **rewriterule\<num\>** (string) (optional) \<attribute\> \<regex_pattern\> \<new_tag\>
35
- * Deprecated: Use <rule> section
39
+ * Obsoleted: Use \<rule\> section
36
40
  * **capitalize_regex_backreference** (bool) (optional): Capitalize letter for every matched regex backreference. (ex: maps -> Maps) for more details, see usage.
37
41
  * Default value: no
38
42
  * **remove_tag_prefix** (string) (optional): Remove tag prefix for tag placeholder. (see the section of "Tag placeholder")
39
43
  * **hostname_command** (string) (optional): Override hostname command for placeholder. (see the section of "Tag placeholder")
40
- * Default value: `hostname`.
44
+ * Default value: `hostname`
45
+ * **emit_mode** (enum) (required): Specify emit_mode to `batch` or `record`. `batch` will emit events per rewritten tag, and decrease IO. `record` will emit events per record.
46
+ * Default value: `batch`
41
47
 
42
48
  ### \<rule\> section (optional) (multiple)
43
49
 
44
50
  * **key** (string) (required): The field name to which the regular expression is applied
45
- * **pattern** (regexp) (required): The regular expression
51
+ * **pattern** (regexp) (required): The regular expression.
52
+ `/regexp/` is preferred because `/regexp/` style can support character classes such as `/[a-z]/`.
53
+ The pattern without slashes will cause errors if you use patterns start with character classes.
46
54
  * **tag** (string) (required): New tag
47
55
  * **invert** (bool) (optional): If true, rewrite tag when unmatch pattern
48
56
  * Default value: `false`
@@ -70,39 +78,39 @@ It's a sample to exclude some static file log before split tag by domain.
70
78
  capitalize_regex_backreference yes
71
79
  <rule>
72
80
  key path
73
- pattern \.(gif|jpe?g|png|pdf|zip)$
81
+ pattern /\.(gif|jpe?g|png|pdf|zip)$/
74
82
  tag clear
75
83
  </rule>
76
84
  <rule>
77
85
  key status
78
- pattern ^200$
86
+ pattern /^200$/
79
87
  tag clear
80
88
  invert true
81
89
  </rule>
82
90
  <rule>
83
91
  key domain
84
- pattern ^.+\.com$
92
+ pattern /^.+\.com$/
85
93
  tag clear
86
94
  invert true
87
95
  </rule>
88
96
  <rule>
89
97
  key domain
90
- pattern ^maps\.example\.com$
98
+ pattern /^maps\.example\.com$/
91
99
  tag site.ExampleMaps
92
100
  </rule>
93
101
  <rule>
94
102
  key domain
95
- pattern ^news\.example\.com$
103
+ pattern /^news\.example\.com$/
96
104
  tag site.ExampleNews
97
105
  </rule>
98
106
  <rule>
99
107
  key domain
100
- pattern ^(mail)\.(example)\.com$
108
+ pattern /^(mail)\.(example)\.com$/
101
109
  tag site.$2$1
102
110
  </rule>
103
111
  <rule>
104
112
  key domain
105
- pattern .+
113
+ pattern /.+/
106
114
  tag site.unmatched
107
115
  </rule>
108
116
  </match>
@@ -157,7 +165,11 @@ Dot notation:
157
165
  ```
158
166
  <match kubernetes.**>
159
167
  @type rewrite_tag_filter
160
- rewriterule1 $.kubernetes.namespace_name ^(.+)$ $1.${tag}
168
+ <rule>
169
+ key $.kubernetes.namespace_name
170
+ pattern ^(.+)$
171
+ tag $1.${tag}
172
+ </rule>
161
173
  </match>
162
174
  ```
163
175
 
@@ -166,7 +178,11 @@ Bracket notation:
166
178
  ```
167
179
  <match kubernetes.**>
168
180
  @type rewrite_tag_filter
169
- rewriterule1 $['kubernetes']['namespace_name'] ^(.+)$ $1.${tag}
181
+ <rule>
182
+ key $['kubernetes']['namespace_name']
183
+ pattern ^(.+)$
184
+ tag $1.${tag}
185
+ </rule>
170
186
  </match>
171
187
  ```
172
188
 
@@ -184,7 +200,7 @@ When original tag is `kubernetes.var.log`, this will be converted to `default.ku
184
200
 
185
201
  ### Tag placeholder
186
202
 
187
- It is supported these placeholder for new_tag (rewrited tag).
203
+ It is supported these placeholder for new_tag (rewritten tag).
188
204
 
189
205
  - `${tag}`
190
206
  - `__TAG__`
@@ -198,12 +214,16 @@ For example with `td.apache.access` tag, it will get `td` by `${tag_parts[0]}` a
198
214
 
199
215
  **Note** Currently, range expression ```${tag_parts[0..2]}``` is not supported.
200
216
 
201
- #### Placeholder Option
217
+ #### Placeholder Options
202
218
 
203
219
  * `remove_tag_prefix`
204
220
 
205
221
  This option adds removing tag prefix for `${tag}` or `__TAG__` in placeholder.
206
222
 
223
+ * `remove_tag_regexp`
224
+
225
+ This option adds removing tag regexp for `${tag}` or `__TAG__` in placeholder.
226
+
207
227
  * `hostname_command`
208
228
 
209
229
  By default, execute command as `hostname` to get full hostname.
@@ -215,45 +235,67 @@ It comes short hostname with `hostname_command hostname -s` configuration specif
215
235
  It's a sample to rewrite a tag with placeholder.
216
236
 
217
237
  ```
218
- # It will get "rewrited.access.ExampleMail"
238
+ # It will get "rewritten.access.ExampleMail"
219
239
  <match apache.access>
220
240
  @type rewrite_tag_filter
221
241
  remove_tag_prefix apache
222
242
  <rule>
223
243
  key domain
224
244
  pattern ^(mail)\.(example)\.com$
225
- tag rewrited.${tag}.$2$1
245
+ tag rewritten.${tag}.$2$1
246
+ </rule>
247
+ </match>
248
+
249
+ # It will get "rewritten.access.ExampleMail"
250
+ <match apache.access>
251
+ @type rewrite_tag_filter
252
+ remove_tag_regexp /^apache\./
253
+ <rule>
254
+ key domain
255
+ pattern ^(mail)\.(example)\.com$
256
+ tag rewritten.${tag}.$2$1
257
+ </rule>
258
+ </match>
259
+
260
+ # It will get "http.access.log"
261
+ <match input.{apache,nginx}.access.log>
262
+ @type rewrite_tag_filter
263
+ remove_tag_regexp /^input\.(apache|nginx)\./
264
+ <rule>
265
+ key domain
266
+ pattern ^.+$
267
+ tag http.${tag}
226
268
  </rule>
227
269
  </match>
228
270
 
229
- # It will get "rewrited.ExampleMail.app30-124.foo.com" when hostname is "app30-124.foo.com"
271
+ # It will get "rewritten.ExampleMail.app30-124.foo.com" when hostname is "app30-124.foo.com"
230
272
  <match apache.access>
231
273
  @type rewrite_tag_filter
232
274
  <rule>
233
275
  key domain
234
276
  pattern ^(mail)\.(example)\.com$
235
- tag rewrited.$2$1.${hostname}
277
+ tag rewritten.$2$1.${hostname}
236
278
  </rule>
237
279
  </match>
238
280
 
239
- # It will get "rewrited.ExampleMail.app30-124" when hostname is "app30-124.foo.com"
281
+ # It will get "rewritten.ExampleMail.app30-124" when hostname is "app30-124.foo.com"
240
282
  <match apache.access>
241
283
  @type rewrite_tag_filter
242
284
  hostname_command hostname -s
243
285
  <rule>
244
286
  key domain
245
287
  pattern ^(mail)\.(example)\.com$
246
- tag rewrited.$2$1.${hostname}
288
+ tag rewritten.$2$1.${hostname}
247
289
  </rule>
248
290
  </match>
249
291
 
250
- # It will get "rewrited.game.pool"
292
+ # It will get "rewritten.game.pool"
251
293
  <match app.game.pool.activity>
252
294
  @type rewrite_tag_filter
253
295
  <rule>
254
296
  key domain
255
297
  pattern ^.+$
256
- tag rewrited.${tag_parts[1]}.${tag_parts[2]}
298
+ tag rewritten.${tag_parts[1]}.${tag_parts[2]}
257
299
  </rule>
258
300
  </match>
259
301
  ```
data/example.conf CHANGED
@@ -2,15 +2,17 @@
2
2
 
3
3
  # appearing plugins:
4
4
  # rewrite_tag_filter: http://rubygems.org/gems/fluent-plugin-rewrite-tag-filter
5
- # forest: http://rubygems.org/gems/fluent-plugin-forest
6
5
  # datacounter: http://rubygems.org/gems/fluent-plugin-datacounter
7
6
  # growthforecast: http://rubygems.org/gems/fluent-plugin-growthforecast
8
7
 
9
8
  <source>
10
- type tail
9
+ @type tail
11
10
  path /var/log/httpd/access_log
12
- format /^(?<domain>[^ ]*) (?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<status>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<response_time>[^ ]*))?$/
13
- time_format %d/%b/%Y:%H:%M:%S %z
11
+ <parse>
12
+ @type regexp
13
+ expression /^(?<domain>[^ ]*) (?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<status>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<response_time>[^ ]*))?$/
14
+ time_format %d/%b/%Y:%H:%M:%S %z
15
+ </parse>
14
16
  tag td.apache.access
15
17
  pos_file /var/log/td-agent/apache_access.pos
16
18
  </source>
@@ -18,139 +20,173 @@
18
20
 
19
21
  # Extract specified virtual domain
20
22
  <match td.apache.access>
21
- type copy
23
+ @type copy
22
24
  <store>
23
- type rewrite_tag_filter
25
+ @type rewrite_tag_filter
24
26
  capitalize_regex_backreference yes
25
- rewriterule1 domain ^(maps|news|mail)\.google\.com$ site.Google$1
27
+ <rule>
28
+ key domain
29
+ pattern /^(maps|news|mail)\.google\.com$/
30
+ tag site.Google$1
31
+ </rule>
26
32
  </store>
27
33
  <store>
28
- type rewrite_tag_filter
34
+ @type rewrite_tag_filter
29
35
  capitalize_regex_backreference yes
30
- rewriterule1 domain ^(maps)\.google\.com$ sitepath.Google$1
36
+ <rule>
37
+ key domain
38
+ pattern /^(maps)\.google\.com$/
39
+ tag sitepath.Google$1
40
+ </rule>
31
41
  </store>
32
42
  </match>
33
43
 
34
44
 
35
45
  # Second level analyzing
36
46
  <match sitepath.GoogleMaps>
47
+ @type copy
37
48
  <store>
38
- type rewrite_tag_filter
39
- rewriterule1 path ^/labs site.GoogleMaps.Labs
40
- rewriterule2 path ^/static/\d+ site.GoogleMaps.Static
41
- rewriterule3 path ^/help/maps/(streetview|getmaps) site.GoogleMaps.Help
49
+ @type rewrite_tag_filter
50
+ <rule>
51
+ key path
52
+ pattern /^\/labs/
53
+ tag site.GoogleMaps.Labs
54
+ </rule>
55
+ <rule>
56
+ key path
57
+ pattern /^\/static/\d+/
58
+ tag site.GoogleMaps.Static
59
+ </rule>
60
+ <rule>
61
+ key path
62
+ pattern /^\/help\/maps\/(streetview|getmaps)/
63
+ tag site.GoogleMaps.Help
64
+ </rule>
42
65
  </store>
43
66
  <store>
44
- type rewrite_tag_filter
45
- rewriterule1 referer headlines\.yahoo\.co\.jp site.GoogleMaps.referer_YahooHeadlines
46
- rewriterule2 referer news\.livedoor\.com site.GoogleMaps.referer_LivedoorNews
67
+ @type rewrite_tag_filter
68
+ <rule>
69
+ key referer
70
+ pattern /headlines\.yahoo\.co\.jp/
71
+ tag site.GoogleMaps.referer_YahooHeadlines
72
+ </rule>
73
+ <rule>
74
+ key referer
75
+ pattern /news\.livedoor\.com/
76
+ tag site.GoogleMaps.referer_LivedoorNews
77
+ </rule>
47
78
  </store>
48
79
  <store>
49
- type rewrite_tag_filter
50
- rewriterule1 agent Googlebot/ site.GoogleMaps.agent_Googlebot
51
- rewriterule2 agent ^.* iPhone .+Googlebot-Mobile/.*$ site.GoogleMaps.agent_GooglebotSmartphone
52
- rewriterule3 agent Googlebot-Mobile/ site.GoogleMaps.agent_GooglebotMobile
53
- rewriterule4 agent bingbot site.GoogleMaps.agent_Bingbot
54
- rewriterule5 agent Baiduspider site.GoogleMaps.agent_Baiduspider
80
+ @type rewrite_tag_filter
81
+ <rule>
82
+ key agent
83
+ pattern /Googlebot\//
84
+ tag site.GoogleMaps.agent_Googlebot
85
+ </rule>
86
+ <rule>
87
+ key agent
88
+ pattern /^.* iPhone .+Googlebot-Mobile\/.*$/
89
+ tag site.GoogleMaps.agent_GooglebotSmartphone
90
+ </rule>
91
+ <rule>
92
+ key agent
93
+ pattern /Googlebot-Mobile\//
94
+ tag site.GoogleMaps.agent_GooglebotMobile
95
+ </rule>
96
+ <rule>
97
+ key agent
98
+ pattern /bingbot/
99
+ tag site.GoogleMaps.agent_Bingbot
100
+ </rule>
101
+ <rule>
102
+ key agent
103
+ pattern /Baiduspider/
104
+ tag site.GoogleMaps.agent_Baiduspider
105
+ </rule>
55
106
  </store>
56
107
  </match>
57
108
 
58
109
 
59
110
  # Summarize
60
111
  <match site.**>
61
- type copy
112
+ @type copy
62
113
  <store>
63
- type forest
64
- subtype datacounter
65
- <template>
66
- unit minute
67
- count_key response_time
68
- outcast_unmatched false
69
- aggregate all
70
- tag gf.responsetime.__TAG__
71
- pattern1 0-100msec ^\d{1,5}$
72
- pattern2 100-300msec ^[1-2]\d{5}$
73
- pattern3 300-600msec ^[3-5]\d{5}$
74
- pattern4 600msec-1sec ^[6-9]\d{5}$
75
- pattern5 1-2sec ^1\d{6}$
76
- pattern6 2-10sec ^[2-9]\d{6}$
77
- pattern7 10sec_over ^\d{8,}$
78
- </template>
114
+ @type datacounter
115
+ unit minute
116
+ count_key response_time
117
+ outcast_unmatched false
118
+ aggregate tag
119
+ tag_prefix gf.responsetime
120
+ output_per_tag yes
121
+ pattern1 0-100msec ^\d{1,5}$
122
+ pattern2 100-300msec ^[1-2]\d{5}$
123
+ pattern3 300-600msec ^[3-5]\d{5}$
124
+ pattern4 600msec-1sec ^[6-9]\d{5}$
125
+ pattern5 1-2sec ^1\d{6}$
126
+ pattern6 2-10sec ^[2-9]\d{6}$
127
+ pattern7 10sec_over ^\d{8,}$
79
128
  </store>
80
129
  <store>
81
- type forest
82
- subtype datacounter
83
- <template>
84
- unit minute
85
- outcast_unmatched false
86
- aggregate all
87
- tag gf.responsecode.__TAG__
88
- count_key status
89
- pattern1 200 ^200$
90
- pattern2 2xx ^2\d\d$
91
- pattern3 301 ^301$
92
- pattern4 302 ^302$
93
- pattern5 3xx ^3\d\d$
94
- pattern6 403 ^403$
95
- pattern7 404 ^404$
96
- pattern8 410 ^410$
97
- pattern9 4xx ^4\d\d$
98
- pattern10 500 ^5\d\d$
99
- </template>
130
+ @type datacounter
131
+ unit minute
132
+ outcast_unmatched false
133
+ aggregate tag
134
+ tag_prefix gf.responsecode
135
+ output_per_tag yes
136
+ count_key status
137
+ pattern1 200 ^200$
138
+ pattern2 2xx ^2\d\d$
139
+ pattern3 301 ^301$
140
+ pattern4 302 ^302$
141
+ pattern5 3xx ^3\d\d$
142
+ pattern6 403 ^403$
143
+ pattern7 404 ^404$
144
+ pattern8 410 ^410$
145
+ pattern9 4xx ^4\d\d$
146
+ pattern10 500 ^5\d\d$
100
147
  </store>
101
148
  <store>
102
- type forest
103
- subtype datacounter
104
- <template>
105
- unit minute
106
- count_key agent
107
- outcast_unmatched false
108
- aggregate all
109
- tag gf.useragent.__TAG__
110
- pattern1 api HttpRequest
111
- pattern2 robot (spider|bot|crawler|\+http\:)
112
- pattern3 smartphone (iPhone|iPod|Android|dream|CUPCAKE|blackberry|webOS|incognito|webmate|IEMobile)
113
- pattern4 mobile (^KDDI|UP.Browser|DoCoMo|Vodafone|SoftBank|WILLCOM)
114
- pattern5 pc .+
115
- </template>
149
+ @type datacounter
150
+ unit minute
151
+ count_key agent
152
+ outcast_unmatched false
153
+ aggregate tag
154
+ tag_prefix gf.useragent
155
+ output_per_tag yes
156
+ pattern1 api HttpRequest
157
+ pattern2 robot (spider|bot|crawler|\+http\:)
158
+ pattern3 smartphone (iPhone|iPod|Android|dream|CUPCAKE|blackberry|webOS|incognito|webmate|IEMobile)
159
+ pattern4 mobile (^KDDI|UP.Browser|DoCoMo|Vodafone|SoftBank|WILLCOM)
160
+ pattern5 pc .+
116
161
  </store>
117
162
  </match>
118
163
 
119
164
 
120
165
  # Graph
121
166
  <match gf.responsetime.**>
122
- type forest
123
- subtype growthforecast
167
+ @type growthforecast
124
168
  remove_prefix gf.responsetime.site
125
- <template>
126
- gfapi_url http://localhost:5125/api/
127
- service __TAG__
128
- section response_time
129
- name_keys 0-100msec_percentage,100-300msec_percentage,300-600msec_percentage,600msec-1sec_percentage,1-2sec_percentage,2-10sec_percentage,10sec_over_percentage
130
- </template>
169
+ gfapi_url http://localhost:5125/api/
170
+ tag_for service
171
+ section response_time
172
+ name_keys 0-100msec_percentage,100-300msec_percentage,300-600msec_percentage,600msec-1sec_percentage,1-2sec_percentage,2-10sec_percentage,10sec_over_percentage
131
173
  </match>
132
174
 
133
175
  <match gf.responsecode.**>
134
- type forest
135
- subtype growthforecast
176
+ @type growthforecast
136
177
  remove_prefix gf.responsecode.site
137
- <template>
138
- gfapi_url http://localhost:5125/api/
139
- service __TAG__
140
- section response_code
141
- name_keys 301_count,302_count,3xx_count,403_count,404_count,410_count,4xx_count,500_count
142
- </template>
178
+ gfapi_url http://localhost:5125/api/
179
+ tag_for service
180
+ section response_code
181
+ name_keys 301_count,302_count,3xx_count,403_count,404_count,410_count,4xx_count,500_count
143
182
  </match>
144
183
 
145
184
  <match gf.useragent.**>
146
- type forest
147
- subtype growthforecast
185
+ @type growthforecast
148
186
  remove_prefix gf.useragent.site
149
- <template>
150
- gfapi_url http://localhost:5125/api/
151
- service __TAG__
152
- section useragent
153
- name_keys pc_count,mobile_count,smartphone_count,robot_count,api_count
154
- </template>
187
+ gfapi_url http://localhost:5125/api/
188
+ tag_for service
189
+ section useragent
190
+ name_keys pc_count,mobile_count,smartphone_count,robot_count,api_count
155
191
  </match>
156
192
 
data/example2.conf CHANGED
@@ -7,10 +7,13 @@
7
7
  # growthforecast: http://rubygems.org/gems/fluent-plugin-growthforecast
8
8
 
9
9
  <source>
10
- type tail
10
+ @type tail
11
11
  path /var/log/httpd/access_log
12
- format /^(?<domain>[^ ]*) (?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<status>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<response_time>[^ ]*))?$/
13
- time_format %d/%b/%Y:%H:%M:%S %z
12
+ <parse>
13
+ @type regexp
14
+ expression /^(?<domain>[^ ]*) (?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<status>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<response_time>[^ ]*))?$/
15
+ time_format %d/%b/%Y:%H:%M:%S %z
16
+ </parse>
14
17
  tag td.apache.access
15
18
  pos_file /var/log/td-agent/apache_access.pos
16
19
  </source>
@@ -18,60 +21,83 @@
18
21
 
19
22
  # Extract specified virtual domain
20
23
  <match td.apache.access>
21
- type rewrite_tag_filter
22
- rewriterule1 domain ^maps\.google\.com$ filter.GoogleMap
24
+ @type rewrite_tag_filter
25
+ <rule>
26
+ key domain
27
+ pattern /^maps\.google\.com$/
28
+ tag filter.GoogleMap
29
+ </rule>
23
30
  </match>
24
31
 
25
32
 
26
33
  # Filtering
27
34
  <match filter.GoogleMap>
28
- type rewrite_tag_filter
29
- rewriterule1 path ^/(img|css|js|static|assets)/ clear
30
- rewriterule2 status ^(?!200)$ clear
31
- rewriterule3 method ^(?!GET)$ clear
32
- rewriterule4 agent (spider|bot|crawler|\+http\:) clear
33
- rewriterule5 path ^/(admin|api|backend) site.GoogleMap.backend
34
- rewriterule6 path .+ site.GoogleMap.front
35
+ @type rewrite_tag_filter
36
+ <rule>
37
+ key path
38
+ pattern /^\/(img|css|js|static|assets)\//
39
+ tag clear
40
+ </rule>
41
+ <rule>
42
+ key status
43
+ pattern /^(?!200)$/
44
+ tag clear
45
+ </rule>
46
+ <rule>
47
+ key method
48
+ pattern /^(?!GET)$/
49
+ tag clear
50
+ </rule>
51
+ <rule>
52
+ key agent
53
+ pattern /(spider|bot|crawler|\+http\:)/
54
+ tag clean
55
+ </rule>
56
+ <rule>
57
+ key path
58
+ pattern /^\/(admin|api|backend)/
59
+ tag site.GoogleMap.backend
60
+ </rule>
61
+ <rule>
62
+ key path
63
+ pattern /.+/
64
+ tag site.GoogleMap.front
65
+ </rule>
35
66
  </match>
36
67
 
37
68
 
38
69
  # Summarize
39
70
  <match site.**>
40
- type forest
41
- subtype datacounter
42
- <template>
43
- unit minute
44
- count_key response_time
45
- outcast_unmatched false
46
- aggregate all
47
- tag gf.responsetime.__TAG__
48
- pattern1 0-100msec ^\d{1,5}$
49
- pattern2 100-300msec ^[1-2]\d{5}$
50
- pattern3 300-600msec ^[3-5]\d{5}$
51
- pattern4 600msec-1sec ^[6-9]\d{5}$
52
- pattern5 1-2sec ^1\d{6}$
53
- pattern6 2-10sec ^[2-9]\d{6}$
54
- pattern7 10sec_over ^\d{8,}$
55
- </template>
71
+ @type datacounter
72
+ unit minute
73
+ count_key response_time
74
+ outcast_unmatched false
75
+ aggregate tag
76
+ tag_prefix gf.responsetime
77
+ output_per_tag yes
78
+ pattern1 0-100msec ^\d{1,5}$
79
+ pattern2 100-300msec ^[1-2]\d{5}$
80
+ pattern3 300-600msec ^[3-5]\d{5}$
81
+ pattern4 600msec-1sec ^[6-9]\d{5}$
82
+ pattern5 1-2sec ^1\d{6}$
83
+ pattern6 2-10sec ^[2-9]\d{6}$
84
+ pattern7 10sec_over ^\d{8,}$
56
85
  </match>
57
86
 
58
87
 
59
88
  # Graph
60
89
  <match gf.responsetime.**>
61
- type forest
62
- subtype growthforecast
90
+ @type growthforecast
63
91
  remove_prefix gf.responsetime.site
64
- <template>
65
- gfapi_url http://localhost:5125/api/
66
- service __TAG__
67
- section response_time
68
- name_keys 0-100msec_percentage,100-300msec_percentage,300-600msec_percentage,600msec-1sec_percentage,1-2sec_percentage,2-10sec_percentage,10sec_over_percentage
69
- </template>
92
+ gfapi_url http://localhost:5125/api/
93
+ tag_for service
94
+ section response_time
95
+ name_keys 0-100msec_percentage,100-300msec_percentage,300-600msec_percentage,600msec-1sec_percentage,1-2sec_percentage,2-10sec_percentage,10sec_over_percentage
70
96
  </match>
71
97
 
72
98
 
73
99
  # Clear tag
74
100
  <match clear>
75
- type null
101
+ @type null
76
102
  </match>
77
103
 
@@ -1,9 +1,8 @@
1
- # -*- encoding: utf-8 -*-
2
1
  $:.push File.expand_path("../lib", __FILE__)
3
2
 
4
3
  Gem::Specification.new do |s|
5
4
  s.name = "fluent-plugin-rewrite-tag-filter"
6
- s.version = "2.0.0"
5
+ s.version = "2.3.0"
7
6
  s.license = "Apache-2.0"
8
7
  s.authors = ["Kentaro Yoshida"]
9
8
  s.email = ["y.ken.studio@gmail.com"]
@@ -16,6 +15,8 @@ Gem::Specification.new do |s|
16
15
  s.require_paths = ["lib"]
17
16
 
18
17
  s.add_development_dependency "test-unit", ">= 3.1.0"
18
+ s.add_development_dependency "test-unit-rr"
19
19
  s.add_development_dependency "rake"
20
- s.add_runtime_dependency "fluentd", "~> 0.14.2"
20
+ s.add_runtime_dependency "fluentd", ">= 0.14.2", "< 2"
21
+ s.add_runtime_dependency "fluent-config-regexp-type"
21
22
  end
@@ -1,4 +1,5 @@
1
1
  require "fluent/plugin/output"
2
+ require "fluent/config/regexp_type"
2
3
 
3
4
  class Fluent::Plugin::RewriteTagFilterOutput < Fluent::Plugin::Output
4
5
  Fluent::Plugin.register_output('rewrite_tag_filter', self)
@@ -9,16 +10,18 @@ class Fluent::Plugin::RewriteTagFilterOutput < Fluent::Plugin::Output
9
10
  config_param :capitalize_regex_backreference, :bool, :default => false
10
11
  desc 'Remove tag prefix for tag placeholder.'
11
12
  config_param :remove_tag_prefix, :string, :default => nil
13
+ desc "Remove tag regexp for tag placeholder."
14
+ config_param :remove_tag_regexp, :regexp, default: nil
12
15
  desc 'Override hostname command for placeholder.'
13
16
  config_param :hostname_command, :string, :default => 'hostname'
17
+ desc "The emit mode. If `batch`, this plugin will emit events per rewritten tag."
18
+ config_param :emit_mode, :enum, list: [:record, :batch], default: :batch
14
19
 
15
20
  config_section :rule, param_name: :rules, multi: true do
16
21
  desc "The field name to which the regular expression is applied"
17
22
  config_param :key, :string
18
23
  desc "The regular expression"
19
- config_param :pattern do |value|
20
- Regexp.compile(value)
21
- end
24
+ config_param :pattern, :regexp
22
25
  desc "New tag"
23
26
  config_param :tag, :string
24
27
  desc "If true, rewrite tag when unmatch pattern"
@@ -57,9 +60,15 @@ class Fluent::Plugin::RewriteTagFilterOutput < Fluent::Plugin::Output
57
60
  raise Fluent::ConfigError, "duplicated rewriterules found #{@rewriterules.inspect}"
58
61
  end
59
62
 
63
+ if @remove_tag_prefix && @remove_tag_regexp
64
+ raise Fluent::ConfigError, "remove_tag_prefix and remove_tag_regexp are exclusive"
65
+ end
66
+
60
67
  unless @remove_tag_prefix.nil?
61
- @remove_tag_prefix = /^#{Regexp.escape(@remove_tag_prefix)}\.?/
68
+ @remove_tag_regexp = /^#{Regexp.escape(@remove_tag_prefix)}\.?/
62
69
  end
70
+
71
+ @batch_mode = @emit_mode == :batch
63
72
  end
64
73
 
65
74
  def multi_workers_ready?
@@ -67,15 +76,33 @@ class Fluent::Plugin::RewriteTagFilterOutput < Fluent::Plugin::Output
67
76
  end
68
77
 
69
78
  def process(tag, es)
70
- es.each do |time, record|
71
- rewrited_tag = rewrite_tag(tag, record)
72
- next if rewrited_tag.nil? || tag == rewrited_tag
73
- router.emit(rewrited_tag, time, record)
79
+ placeholder = get_placeholder(tag)
80
+ if @batch_mode
81
+ new_event_streams = Hash.new {|h, k| h[k] = Fluent::MultiEventStream.new }
82
+ es.each do |time, record|
83
+ rewrited_tag = rewrite_tag(tag, record, placeholder)
84
+ if rewrited_tag.nil? || tag == rewrited_tag
85
+ log.trace("rewrite_tag_filter: tag has not been rewritten", record)
86
+ next
87
+ end
88
+ new_event_streams[rewrited_tag].add(time, record)
89
+ end
90
+ new_event_streams.each do |rewrited_tag, new_es|
91
+ router.emit_stream(rewrited_tag, new_es)
92
+ end
93
+ else
94
+ es.each do |time, record|
95
+ rewrited_tag = rewrite_tag(tag, record, placeholder)
96
+ if rewrited_tag.nil? || tag == rewrited_tag
97
+ log.trace("rewrite_tag_filter: tag has not been rewritten", record)
98
+ next
99
+ end
100
+ router.emit(rewrited_tag, time, record)
101
+ end
74
102
  end
75
103
  end
76
104
 
77
- def rewrite_tag(tag, record)
78
- placeholder = get_placeholder(tag)
105
+ def rewrite_tag(tag, record, placeholder)
79
106
  @rewriterules.each do |record_accessor, regexp, match_operator, rewritetag|
80
107
  rewritevalue = record_accessor.call(record).to_s
81
108
  next if rewritevalue.empty? && match_operator != MATCH_OPERATOR_EXCLUDE
@@ -114,7 +141,7 @@ class Fluent::Plugin::RewriteTagFilterOutput < Fluent::Plugin::Output
114
141
  end
115
142
 
116
143
  def get_placeholder(tag)
117
- tag = tag.sub(@remove_tag_prefix, '') if @remove_tag_prefix
144
+ tag = tag.sub(@remove_tag_regexp, '') if @remove_tag_regexp
118
145
 
119
146
  result = {
120
147
  '__HOSTNAME__' => @hostname,
data/test/helper.rb CHANGED
@@ -1,9 +1,13 @@
1
1
  require 'bundler/setup'
2
2
  require 'test/unit'
3
+ require 'test/unit/rr'
3
4
 
4
5
  $LOAD_PATH.unshift(File.join(__dir__, '..', 'lib'))
5
6
  $LOAD_PATH.unshift(__dir__)
6
7
  require 'fluent/test'
7
8
  require 'fluent/test/driver/output'
9
+ require 'fluent/test/helpers'
10
+
11
+ Test::Unit::TestCase.include(Fluent::Test::Helpers)
8
12
 
9
13
  require 'fluent/plugin/out_rewrite_tag_filter'
@@ -17,6 +17,45 @@ class RewriteTagFilterOutputTest < Test::Unit::TestCase
17
17
  create_driver(conf)
18
18
  end
19
19
  end
20
+
21
+ test "pattern with character classes" do
22
+ conf = %[
23
+ <rule>
24
+ key $['email']['domain']
25
+ pattern /[sv]d[a-z]+\\d*$/
26
+ tag $2.$1
27
+ </rule>
28
+ ]
29
+ d = create_driver(conf)
30
+ assert_equal(/[sv]d[a-z]+\d*$/, d.instance.rules.first.pattern)
31
+ end
32
+
33
+ test "pattern w/o slashes" do
34
+ conf = %[
35
+ <rule>
36
+ key $['email']['domain']
37
+ pattern .+
38
+ tag $2.$1
39
+ </rule>
40
+ ]
41
+ d = create_driver(conf)
42
+ assert_equal(/.+/, d.instance.rules.first.pattern)
43
+ end
44
+
45
+ test "remove_tag_prefix and remove_tag_regexp are exclusive" do
46
+ conf = %[
47
+ remove_tag_prefix prefix
48
+ remove_tag_regexp /^prefix\./
49
+ <rule>
50
+ key message
51
+ pattern .+
52
+ tag ${tag}
53
+ </rule>
54
+ ]
55
+ assert_raise(Fluent::ConfigError) do
56
+ create_driver(conf)
57
+ end
58
+ end
20
59
  end
21
60
 
22
61
  sub_test_case "section style" do
@@ -103,6 +142,30 @@ class RewriteTagFilterOutputTest < Test::Unit::TestCase
103
142
  assert_equal 'access', events[0][0] # tag
104
143
  end
105
144
 
145
+ sub_test_case "remove_tag_regexp" do
146
+ test "plain" do
147
+ config = %[
148
+ remove_tag_regexp /^input\.(apache|nginx)\./
149
+ <rule>
150
+ key domain
151
+ pattern ^www\.google\.com$
152
+ tag rewritten.${tag}
153
+ </rule>
154
+ ]
155
+ d = create_driver(config)
156
+ d.run do
157
+ d.feed('input.apache.access', event_time, {'domain' => 'www.google.com', 'path' => '/foo/bar?key=value', 'agent' => 'Googlebot', 'response_time' => 1000000})
158
+ d.feed('input.nginx.access', event_time, {'domain' => 'www.google.com', 'path' => '/foo/bar?key=value', 'agent' => 'Googlebot', 'response_time' => 1000000})
159
+ d.feed('input.tomcat.access', event_time, {'domain' => 'www.google.com', 'path' => '/foo/bar?key=value', 'agent' => 'Googlebot', 'response_time' => 1000000})
160
+ end
161
+ events = d.events
162
+ assert_equal 3, events.length
163
+ assert_equal 'rewritten.access', events[0][0]
164
+ assert_equal 'rewritten.access', events[1][0]
165
+ assert_equal 'rewritten.input.tomcat.access', events[2][0]
166
+ end
167
+ end
168
+
106
169
  test "short hostname" do
107
170
  config = %[
108
171
  remove_tag_prefix input
@@ -260,5 +323,95 @@ class RewriteTagFilterOutputTest < Test::Unit::TestCase
260
323
  events = d.events
261
324
  assert_equal "com.example", events[0][0]
262
325
  end
326
+
327
+ test "tag has not been rewritten and log_level trace" do
328
+ conf = %[
329
+ @log_level trace
330
+ <rule>
331
+ key $['email']['domain']
332
+ pattern ^(example)\.(com)$
333
+ tag $2.$1
334
+ </rule>
335
+ ]
336
+ d = create_driver(conf)
337
+ d.run(default_tag: "input") do
338
+ d.feed({ "email" => { "localpart" => "john", "domain" => "example.com" }})
339
+ d.feed({ "email" => { "localpart" => "doe", "domain" => "example.jp" }})
340
+ end
341
+ events = d.events
342
+ assert_equal(1, events.size)
343
+ log = d.logs.grep(/\[trace\]/).first
344
+ assert_equal('rewrite_tag_filter: tag has not been rewritten email={"localpart"=>"doe", "domain"=>"example.jp"}',
345
+ log.slice(/\[trace\]: (.+)$/, 1))
346
+ assert_equal "com.example", events[0][0]
347
+ end
348
+
349
+ sub_test_case "emit_mode" do
350
+ test "record" do
351
+ conf = %[
352
+ emit_mode record
353
+ <rule>
354
+ key key
355
+ pattern /^(odd|even)$/
356
+ tag $1
357
+ </rule>
358
+ ]
359
+ time = event_time
360
+ d = create_driver(conf)
361
+ mock.proxy(d.instance.router).emit(anything, anything, anything).times(6)
362
+ mock.proxy(d.instance.router).emit_stream(anything, anything).times(0)
363
+ d.run(default_tag: "input") do
364
+ d.feed([[time, { "key" => "odd", "message" => "message-1" }],
365
+ [time, { "key" => "even", "message" => "message-2" }],
366
+ [time, { "key" => "odd", "message" => "message-3" }],
367
+ [time, { "key" => "even", "message" => "message-4" }],
368
+ [time, { "key" => "odd", "message" => "message-5" }],
369
+ [time, { "key" => "even", "message" => "message-6" }]])
370
+ end
371
+ events = d.events
372
+ expected_events = [
373
+ ["odd", time, { "key" => "odd", "message" => "message-1" }],
374
+ ["even", time, { "key" => "even", "message" => "message-2" }],
375
+ ["odd", time, { "key" => "odd", "message" => "message-3" }],
376
+ ["even", time, { "key" => "even", "message" => "message-4" }],
377
+ ["odd", time, { "key" => "odd", "message" => "message-5" }],
378
+ ["even", time, { "key" => "even", "message" => "message-6" }],
379
+ ]
380
+ assert_equal(events, expected_events)
381
+ end
382
+
383
+ test "batch" do
384
+ conf = %[
385
+ emit_mode batch
386
+ <rule>
387
+ key key
388
+ pattern /^(odd|even)$/
389
+ tag $1
390
+ </rule>
391
+ ]
392
+ time = event_time
393
+ d = create_driver(conf)
394
+ mock.proxy(d.instance.router).emit(anything, anything, anything).times(0)
395
+ mock.proxy(d.instance.router).emit_stream(anything, anything).times(2)
396
+ d.run(default_tag: "input") do
397
+ d.feed([[time, { "key" => "odd", "message" => "message-1" }],
398
+ [time, { "key" => "even", "message" => "message-2" }],
399
+ [time, { "key" => "odd", "message" => "message-3" }],
400
+ [time, { "key" => "even", "message" => "message-4" }],
401
+ [time, { "key" => "odd", "message" => "message-5" }],
402
+ [time, { "key" => "even", "message" => "message-6" }]])
403
+ end
404
+ events = d.events
405
+ expected_records = [
406
+ ["odd", time, { "key" => "odd", "message" => "message-1" }],
407
+ ["odd", time, { "key" => "odd", "message" => "message-3" }],
408
+ ["odd", time, { "key" => "odd", "message" => "message-5" }],
409
+ ["even", time, { "key" => "even", "message" => "message-2" }],
410
+ ["even", time, { "key" => "even", "message" => "message-4" }],
411
+ ["even", time, { "key" => "even", "message" => "message-6" }],
412
+ ]
413
+ assert_equal(events, expected_records)
414
+ end
415
+ end
263
416
  end
264
417
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-rewrite-tag-filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kentaro Yoshida
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-06 00:00:00.000000000 Z
11
+ date: 2020-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit-rr
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -42,16 +56,36 @@ dependencies:
42
56
  name: fluentd
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
61
  version: 0.14.2
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '2'
48
65
  type: :runtime
49
66
  prerelease: false
50
67
  version_requirements: !ruby/object:Gem::Requirement
51
68
  requirements:
52
- - - "~>"
69
+ - - ">="
53
70
  - !ruby/object:Gem::Version
54
71
  version: 0.14.2
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '2'
75
+ - !ruby/object:Gem::Dependency
76
+ name: fluent-config-regexp-type
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
55
89
  description:
56
90
  email:
57
91
  - y.ken.studio@gmail.com
@@ -90,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
124
  - !ruby/object:Gem::Version
91
125
  version: '0'
92
126
  requirements: []
93
- rubyforge_project:
94
- rubygems_version: 2.6.13
127
+ rubygems_version: 3.1.2
95
128
  signing_key:
96
129
  specification_version: 4
97
130
  summary: Fluentd Output filter plugin. It has designed to rewrite tag like mod_rewrite.