fluent-plugin-slack-stakater 0.6.8

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 96ca178e4ae8555e05a0fdd6466c04c637a42c6d
4
+ data.tar.gz: 7288a88ed3aa6501568d18ca3af72e34bb9bfae7
5
+ SHA512:
6
+ metadata.gz: 02ae31e51c9d21408f1278a96dc109be007a122e34a8322bb91cac8ea180558258a5b54f975b9f6135cf1a7748439617cf976e9568650705aa398bc85ea68d0f
7
+ data.tar.gz: 14174efe5615240505d66269a5343a0602d1e1625c8ac24521608cbc8be7523dd01a9b02deac6bf377796f0a1dc75c0e279fb7998edf0f2c8397e907c5704bdf
@@ -0,0 +1,8 @@
1
+ /fluent/
2
+ /pkg/
3
+ /coverage/
4
+ /vendor/
5
+ Gemfile.lock
6
+ tmp/
7
+ .ruby-version
8
+ .env
@@ -0,0 +1,11 @@
1
+ sudo: false
2
+ rvm:
3
+ - 2.1.*
4
+ - 2.2.*
5
+ - 2.3.*
6
+ - 2.4.*
7
+ gemfile:
8
+ - Gemfile
9
+ - Gemfile.fluentd.0.12
10
+ before_install:
11
+ - gem update bundler
@@ -0,0 +1,95 @@
1
+ ## 0.6.7 (2017/05/23)
2
+
3
+ Enhancements:
4
+
5
+ * Allow channel @username (DM)
6
+
7
+ ## 0.6.6 (2017/05/23)
8
+
9
+ Enhancements:
10
+
11
+ * Make channel config optional on webhook because webhook has its defaul channel setting (thanks to @hirakiuc)
12
+
13
+ ## 0.6.5 (2017/05/20)
14
+
15
+ Enhancements:
16
+
17
+ * Avoid Encoding::UndefinedConversionError from ASCII-8BIT to UTF-8 on to_json by doing String#scrub! (thanks @yoheimuta)
18
+
19
+ ## 0.6.4 (2016/07/07)
20
+
21
+ Enhancements:
22
+
23
+ * Add `as_user` option (thanks @yacchin1205)
24
+
25
+ ## 0.6.3 (2016/05/11)
26
+
27
+ Enhancements:
28
+
29
+ * Add `verbose_fallback` option to show fallback (popup) verbosely (thanks @eisuke)
30
+
31
+ ## 0.6.2 (2015/12/17)
32
+
33
+ Fixes:
34
+
35
+ * escape special characters in message (thanks @fujiwara)
36
+
37
+ ## 0.6.1 (2015/05/17)
38
+
39
+ Fixes:
40
+
41
+ * Support ruby 1.9.3
42
+
43
+ ## 0.6.0 (2015/04/02)
44
+
45
+ This version has impcompatibility with previous versions in default option values
46
+
47
+ Enhancements:
48
+
49
+ * Support `link_names` and `parse` option. `link_names` option is `true` as default
50
+
51
+ Changes:
52
+
53
+ * the default payload of Incoming Webhook was changed
54
+ * `color` is `nil` as default
55
+ * `icon_emoji` is `nil` as default
56
+ * `username` is `nil` as default
57
+ * `mrkdwn` is `true` as default
58
+
59
+ ## 0.5.5 (2015/04/01)
60
+
61
+ Enhancements:
62
+
63
+ * Support Slackbot Remote Control API
64
+
65
+ ## 0.5.4 (2015/03/31)
66
+
67
+ Enhancements:
68
+
69
+ * Support `mrkdwn` option
70
+
71
+ ## 0.5.3 (2015/03/29)
72
+
73
+ Enhancements:
74
+
75
+ * Support `https_proxy` option
76
+
77
+ ## 0.5.2 (2015/03/29)
78
+
79
+ Enhancements:
80
+
81
+ * Support `icon_url` option (thanks to @jwyjoy)
82
+
83
+ ## 0.5.1 (2015/03/27)
84
+
85
+ Enhancements:
86
+
87
+ * Support `auto_channels_create` option to automatically create channels.
88
+
89
+ ## 0.5.0 (2015/03/22)
90
+
91
+ Enhancements:
92
+
93
+ * Support `message` and `message_keys` options
94
+ * Support `title` and `title_keys` options
95
+ * Support `channel_keys` options to dynamically change channels
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'fluentd', '~> 0.12.0'
@@ -0,0 +1,126 @@
1
+ # fluent-plugin-slack [![Build Status](https://travis-ci.org/sowawa/fluent-plugin-slack.svg)](https://travis-ci.org/sowawa/fluent-plugin-slack)
2
+
3
+ # Installation
4
+
5
+ ```
6
+ $ fluent-gem install fluent-plugin-slack
7
+ ```
8
+
9
+ # Usage (Incoming Webhook)
10
+
11
+ ```apache
12
+ <match slack>
13
+ @type slack
14
+ webhook_url https://hooks.slack.com/services/XXX/XXX/XXX
15
+ channel general
16
+ username sowasowa
17
+ icon_emoji :ghost:
18
+ flush_interval 60s
19
+ </match>
20
+ ```
21
+
22
+ ```ruby
23
+ fluent_logger.post('slack', {
24
+ :message => 'Hello<br>World!'
25
+ })
26
+ ```
27
+
28
+ # Usage (Slackbot)
29
+
30
+ ```apache
31
+ <match slack>
32
+ @type slack
33
+ slackbot_url https://xxxx.slack.com/services/hooks/slackbot?token=XXXXXXXXX
34
+ channel general
35
+ flush_interval 60s
36
+ </match>
37
+ ```
38
+
39
+ ```ruby
40
+ fluent_logger.post('slack', {
41
+ :message => 'Hello<br>World!'
42
+ })
43
+ ```
44
+
45
+ # Usage (Web API a.k.a. Bots)
46
+
47
+ ```apache
48
+ <match slack>
49
+ @type slack
50
+ token xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX
51
+ channel C061EG9SL
52
+ username sowasowa
53
+ icon_emoji :ghost:
54
+ flush_interval 60s
55
+ </match>
56
+ ```
57
+
58
+ ```ruby
59
+ fluent_logger.post('slack', {
60
+ :message => 'Hello<br>World!'
61
+ })
62
+ ```
63
+
64
+ ### Parameter
65
+
66
+ |parameter|description|default|
67
+ |---|---|---|
68
+ |webhook_url|Incoming Webhook URI (Required for Incoming Webhook mode). See https://api.slack.com/incoming-webhooks||
69
+ |slackbot_url|Slackbot URI (Required for Slackbot mode). See https://api.slack.com/slackbot. NOTE: most of optional parameters such as `username`, `color`, `icon_emoji`, `icon_url`, and `title` are not available for this mode, but Desktop Notification via Highlight Words works with only this mode||
70
+ |token|Token for Web API (Required for Web API mode). See https://api.slack.com/web||
71
+ |as_user|post messages as a bot user. See https://api.slack.com/bot-users#post_messages_and_react_to_users. NOTE: This parameter is only enabled if you use the Web API with your bot token. You cannot use both of `username` and `icon_emoji`(`icon_url`) when you set this parameter to `true`.|nil|
72
+ |username|name of bot|nil|
73
+ |color|color to use such as `good` or `bad`. See `Color` section of https://api.slack.com/docs/attachments. NOTE: This parameter must **not** be specified to receive Desktop Notification via Mentions in cases of Incoming Webhook and Slack Web API|nil|
74
+ |icon_emoji|emoji to use as the icon. either of `icon_emoji` or `icon_url` can be specified|nil|
75
+ |icon_url|url to an image to use as the icon. either of `icon_emoji` or `icon_url` can be specified|nil|
76
+ |mrkdwn|enable formatting. see https://api.slack.com/docs/formatting|true|
77
+ |link_names|find and link channel names and usernames. NOTE: This parameter must be `true` to receive Desktop Notification via Mentions in cases of Incoming Webhook and Slack Web API|true|
78
+ |parse|change how messages are treated. `none` or `full` can be specified. See `Parsing mode` section of https://api.slack.com/docs/formatting|nil|
79
+ |channel|Channel name or id to send messages (without first '#'). Channel ID is recommended because it is unchanged even if a channel is renamed||
80
+ |channel_keys|keys used to format channel. %s will be replaced with value specified by channel_keys if this option is used|nil|
81
+ |title|title format. %s will be replaced with value specified by title_keys. title is created from the first appeared record on each tag. NOTE: This parameter must **not** be specified to receive Desktop Notification via Mentions in cases of Incoming Webhook and Slack Web API|nil|
82
+ |title_keys|keys used to format the title|nil|
83
+ |message|message format. %s will be replaced with value specified by message_keys|%s|
84
+ |message_keys|keys used to format messages|message|
85
+ |auto_channels_create|Create channels if not exist. Not available for Incoming Webhook mode (since Incoming Webhook is specific to a channel). A web api `token` for Normal User is required (Bot User can not create channels. See https://api.slack.com/bot-users)|false|
86
+ |https_proxy|https proxy url such as `https://proxy.foo.bar:443`|nil|
87
+ |verbose_fallback|Originally, only `title` is used for the fallback which is the message shown on popup if `title` is given. If this option is set to be `true`, messages are also included to the fallback attribute|false|
88
+
89
+ `fluent-plugin-slack` uses `SetTimeKeyMixin` and `SetTagKeyMixin`, so you can also use:
90
+
91
+ |parameter|description|default|
92
+ |---|---|---|
93
+ |timezone|timezone such as `Asia/Tokyo`||
94
+ |localtime|use localtime as timezone|true|
95
+ |utc|use utc as timezone||
96
+ |time_key|key name for time used in xxx_keys|time|
97
+ |time_format|time format. This will be formatted with Time#strftime.|%H:%M:%S|
98
+ |tag_key|key name for tag used in xxx_keys|tag|
99
+
100
+ `fluent-plugin-slack` is a kind of BufferedOutput plugin, so you can also use [Buffer Parameters](http://docs.fluentd.org/articles/out_exec#buffer-parameters).
101
+
102
+ ## FAQ
103
+
104
+ ### Desktop Notification seems not working?
105
+
106
+ Currently, slack.com has following limitations:
107
+
108
+ 1. Desktop Notification via both Highlight Words and Mentions works only with Slackbot Remote Control
109
+ 2. Desktop Notification via Mentions works for the `text` field if `link_names` parameter is specified in cases of Incoming Webhook and Slack Web API, that is,
110
+ * Desktop Notification does not work for the `attachments` filed (used in `color` and `title`)
111
+ * Desktop Notification via Highlight Words does not work for Incoming Webhook and Slack Web API anyway
112
+
113
+ ## ChangeLog
114
+
115
+ See [CHANGELOG.md](CHANGELOG.md) for details.
116
+
117
+ # Contributors
118
+
119
+ - [@sonots](https://github.com/sonots)
120
+ - [@kenjiskywalker](https://github.com/kenjiskywalker)
121
+
122
+ # Copyright
123
+
124
+ * Copyright:: Copyright (c) 2014- Keisuke SOGAWA
125
+ * License:: Apache License, Version 2.0
126
+
@@ -0,0 +1,16 @@
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
+ task :default => :test
11
+
12
+ desc 'Open an irb session preloaded with the gem library'
13
+ task :console do
14
+ sh 'irb -rubygems -I lib'
15
+ end
16
+ task :c => :console
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.8
@@ -0,0 +1,18 @@
1
+ <source>
2
+ @type forward
3
+ </source>
4
+
5
+ <match tag>
6
+ @type slack
7
+ token "#{ENV['TOKEN']}"
8
+ username fluentd
9
+ color good
10
+ icon_emoji :ghost: # if you want to use icon_url, delete this param.
11
+ #icon_url http://www.google.com/s2/favicons?domain=www.google.de
12
+ channel general
13
+ message %s %s
14
+ message_keys tag,message
15
+ title %s %s
16
+ title_keys tag,message
17
+ flush_interval 1s # slack API has limit as a post / sec
18
+ </match>
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "fluent-plugin-slack-stakater"
6
+ gem.description = "fluent Slack plugin"
7
+ gem.homepage = "https://github.com/stakater/fluent-plugin-slack"
8
+ gem.license = "Apache-2.0"
9
+ gem.summary = gem.description
10
+ gem.version = File.read("VERSION").strip
11
+ gem.authors = ["Keisuke SOGAWA", "Naotoshi Seo", "stakater"]
12
+ gem.email = ["hello@stakater.com"]
13
+ gem.has_rdoc = false
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ gem.require_paths = ['lib']
18
+
19
+ gem.add_dependency "fluentd", ">= 0.12.0"
20
+
21
+ gem.add_development_dependency "rake", ">= 10.1.1"
22
+ gem.add_development_dependency "rr", ">= 1.0.0"
23
+ gem.add_development_dependency "pry"
24
+ gem.add_development_dependency "pry-nav"
25
+ gem.add_development_dependency "test-unit", "~> 3.0.2"
26
+ gem.add_development_dependency "test-unit-rr", "~> 1.0.3"
27
+ gem.add_development_dependency "dotenv"
28
+ end
@@ -0,0 +1 @@
1
+ out_slack.rb
@@ -0,0 +1,382 @@
1
+ require_relative 'slack_client'
2
+
3
+ module Fluent
4
+ class SlackOutput < Fluent::BufferedOutput
5
+ Fluent::Plugin.register_output('buffered_slack', self) # old version compatiblity
6
+ Fluent::Plugin.register_output('slack', self)
7
+
8
+ helpers :record_accessor
9
+
10
+ # For fluentd v0.12.16 or earlier
11
+ class << self
12
+ unless method_defined?(:desc)
13
+ def desc(description)
14
+ end
15
+ end
16
+ end
17
+
18
+ include SetTimeKeyMixin
19
+ include SetTagKeyMixin
20
+
21
+ config_set_default :include_time_key, true
22
+ config_set_default :include_tag_key, true
23
+
24
+ desc <<-DESC
25
+ Incoming Webhook URI (Required for Incoming Webhook mode).
26
+ See: https://api.slack.com/incoming-webhooks
27
+ DESC
28
+ config_param :webhook_url, :string, default: nil
29
+ desc <<-DESC
30
+ Slackbot URI (Required for Slackbot mode).
31
+ See https://api.slack.com/slackbot.
32
+ NOTE: most of optional parameters such as `username`, `color`, `icon_emoji`,
33
+ `icon_url`, and `title` are not available for this mode, but Desktop Notification
34
+ via Highlight Words works with only this mode.
35
+ DESC
36
+ config_param :slackbot_url, :string, default: nil
37
+ desc <<-DESC
38
+ Token for Web API (Required for Web API mode). See: https://api.slack.com/web.
39
+ DESC
40
+ config_param :token, :string, default: nil
41
+ desc "Name of bot."
42
+ config_param :username, :string, default: nil
43
+ desc <<-DESC
44
+ Color to use such as `good` or `bad`.
45
+ See Color section of https://api.slack.com/docs/attachments.
46
+ NOTE: This parameter must not be specified to receive Desktop Notification
47
+ via Mentions in cases of Incoming Webhook and Slack Web API.
48
+ DESC
49
+ config_param :color, :string, default: nil
50
+ desc <<-DESC
51
+ Emoji to use as the icon.
52
+ Either of `icon_emoji` or `icon_url` can be specified.
53
+ DESC
54
+ config_param :as_user, :bool, default: nil
55
+ desc <<-DESC
56
+ Post message as the authenticated user.
57
+ NOTE: This parameter is only enabled if you use the Web API with your bot token.
58
+ You cannot use both of `username` and `icon_emoji`(`icon_url`) when
59
+ you set this parameter to `true`.
60
+ DESC
61
+ config_param :icon_emoji, :string, default: nil
62
+ desc <<-DESC
63
+ Url to an image to use as the icon.
64
+ Either of `icon_emoji` or `icon_url` can be specified.
65
+ DESC
66
+ config_param :icon_url, :string, default: nil
67
+ desc "Enable formatting. See: https://api.slack.com/docs/formatting."
68
+ config_param :mrkdwn, :bool, default: true
69
+ desc <<-DESC
70
+ Find and link channel names and usernames.
71
+ NOTE: This parameter must be `true` to receive Desktop Notification
72
+ via Mentions in cases of Incoming Webhook and Slack Web API.
73
+ DESC
74
+ config_param :link_names, :bool, default: true
75
+ desc <<-DESC
76
+ Change how messages are treated. `none` or `full` can be specified.
77
+ See Parsing mode section of https://api.slack.com/docs/formatting.
78
+ DESC
79
+ config_param :parse, :string, default: nil
80
+ desc <<-DESC
81
+ Create channels if not exist. Not available for Incoming Webhook mode
82
+ (since Incoming Webhook is specific to a channel).
83
+ A web api token for Normal User is required.
84
+ (Bot User can not create channels. See https://api.slack.com/bot-users)
85
+ DESC
86
+ config_param :auto_channels_create, :bool, default: false
87
+ desc "https proxy url such as https://proxy.foo.bar:443"
88
+ config_param :https_proxy, :string, default: nil
89
+
90
+ desc "channel to send messages (without first '#')."
91
+ config_param :channel, :string, default: nil
92
+ desc <<-DESC
93
+ Keys used to format channel.
94
+ %s will be replaced with value specified by channel_keys if this option is used.
95
+ DESC
96
+ config_param :channel_keys, default: nil do |val|
97
+ val.split(',')
98
+ end
99
+ desc <<-DESC
100
+ Title format.
101
+ %s will be replaced with value specified by title_keys.
102
+ Title is created from the first appeared record on each tag.
103
+ NOTE: This parameter must **not** be specified to receive Desktop Notification
104
+ via Mentions in cases of Incoming Webhook and Slack Web API.
105
+ DESC
106
+ config_param :title, :string, default: nil
107
+ desc "Keys used to format the title."
108
+ config_param :title_keys, default: nil do |val|
109
+ val.split(',')
110
+ end
111
+ desc <<-DESC
112
+ Message format.
113
+ %s will be replaced with value specified by message_keys.
114
+ DESC
115
+ config_param :message, :string, default: nil
116
+ desc "Keys used to format messages."
117
+ config_param :message_keys, default: nil do |val|
118
+ val.split(',')
119
+ end
120
+
121
+ desc "Include messages to the fallback attributes"
122
+ config_param :verbose_fallback, :bool, default: false
123
+
124
+ # for test
125
+ attr_reader :slack, :time_format, :localtime, :timef, :mrkdwn_in, :post_message_opts
126
+
127
+ def initialize
128
+ super
129
+ require 'uri'
130
+ end
131
+
132
+ def configure(conf)
133
+ conf['time_format'] ||= '%H:%M:%S' # old version compatiblity
134
+ conf['localtime'] ||= true unless conf['utc']
135
+
136
+ super
137
+
138
+ if @channel
139
+ @channel = URI.unescape(@channel) # old version compatibility
140
+ if !@channel.start_with?('#') and !@channel.start_with?('@')
141
+ @channel = '#' + @channel # Add # since `#` is handled as a comment in fluentd conf
142
+ end
143
+ end
144
+
145
+ if @webhook_url
146
+ if @webhook_url.empty?
147
+ raise Fluent::ConfigError.new("`webhook_url` is an empty string")
148
+ end
149
+ unless @as_user.nil?
150
+ log.warn "out_slack: `as_user` parameter are not available for Incoming Webhook"
151
+ end
152
+ @slack = Fluent::SlackClient::IncomingWebhook.new(@webhook_url)
153
+ elsif @slackbot_url
154
+ if @slackbot_url.empty?
155
+ raise Fluent::ConfigError.new("`slackbot_url` is an empty string")
156
+ end
157
+ if @channel.nil?
158
+ raise Fluent::ConfigError.new("`channel` parameter required for Slackbot Remote Control")
159
+ end
160
+
161
+ if @username or @color or @icon_emoji or @icon_url
162
+ log.warn "out_slack: `username`, `color`, `icon_emoji`, `icon_url` parameters are not available for Slackbot Remote Control"
163
+ end
164
+ unless @as_user.nil?
165
+ log.warn "out_slack: `as_user` parameter are not available for Slackbot Remote Control"
166
+ end
167
+ @slack = Fluent::SlackClient::Slackbot.new(@slackbot_url)
168
+ elsif @token
169
+ if @token.empty?
170
+ raise Fluent::ConfigError.new("`token` is an empty string")
171
+ end
172
+ if @channel.nil?
173
+ raise Fluent::ConfigError.new("`channel` parameter required for Slack WebApi")
174
+ end
175
+
176
+ @slack = Fluent::SlackClient::WebApi.new
177
+ else
178
+ raise Fluent::ConfigError.new("One of `webhook_url` or `slackbot_url`, or `token` is required")
179
+ end
180
+ @slack.log = log
181
+ @slack.debug_dev = log.out if log.level <= Fluent::Log::LEVEL_TRACE
182
+
183
+ if @https_proxy
184
+ @slack.https_proxy = @https_proxy
185
+ end
186
+
187
+ @message ||= '%s'
188
+ @message_keys ||= %w[message]
189
+ begin
190
+ @message % (['1'] * @message_keys.length)
191
+ rescue ArgumentError
192
+ raise Fluent::ConfigError, "string specifier '%s' for `message` and `message_keys` specification mismatch"
193
+ end
194
+ if @title and @title_keys
195
+ begin
196
+ @title % (['1'] * @title_keys.length)
197
+ rescue ArgumentError
198
+ raise Fluent::ConfigError, "string specifier '%s' for `title` and `title_keys` specification mismatch"
199
+ end
200
+ end
201
+ if @channel && @channel_keys
202
+ begin
203
+ @channel % (['1'] * @channel_keys.length)
204
+ rescue ArgumentError
205
+ raise Fluent::ConfigError, "string specifier '%s' for `channel` and `channel_keys` specification mismatch"
206
+ end
207
+ end
208
+
209
+ if @icon_emoji and @icon_url
210
+ raise Fluent::ConfigError, "either of `icon_emoji` or `icon_url` can be specified"
211
+ end
212
+
213
+ if @as_user and (@icon_emoji or @icon_url or @username)
214
+ raise Fluent::ConfigError, "`username`, `icon_emoji` and `icon_url` cannot be specified when `as_user` is set to true"
215
+ end
216
+
217
+ if @mrkdwn
218
+ # Enable markdown for attachments. See https://api.slack.com/docs/formatting
219
+ @mrkdwn_in = %w[text fields]
220
+ end
221
+
222
+ if @parse and !%w[none full].include?(@parse)
223
+ raise Fluent::ConfigError, "`parse` must be either of `none` or `full`"
224
+ end
225
+
226
+ @post_message_opts = {}
227
+ if @auto_channels_create
228
+ raise Fluent::ConfigError, "`token` parameter is required to use `auto_channels_create`" unless @token
229
+ @post_message_opts = {auto_channels_create: true}
230
+ end
231
+ end
232
+
233
+ def format(tag, time, record)
234
+ [tag, time, record].to_msgpack
235
+ end
236
+
237
+ def write(chunk)
238
+ begin
239
+ payloads = build_payloads(chunk)
240
+ payloads.each {|payload| @slack.post_message(payload, @post_message_opts) }
241
+ rescue Timeout::Error => e
242
+ log.warn "out_slack:", :error => e.to_s, :error_class => e.class.to_s
243
+ raise e # let Fluentd retry
244
+ rescue => e
245
+ log.error "out_slack:", :error => e.to_s, :error_class => e.class.to_s
246
+ log.warn_backtrace e.backtrace
247
+ # discard. @todo: add more retriable errors
248
+ end
249
+ end
250
+
251
+ private
252
+
253
+ def build_payloads(chunk)
254
+ if @title
255
+ build_title_payloads(chunk)
256
+ elsif @color
257
+ build_color_payloads(chunk)
258
+ else
259
+ build_plain_payloads(chunk)
260
+ end
261
+ end
262
+
263
+ def common_payload
264
+ return @common_payload if @common_payload
265
+ @common_payload = {}
266
+ @common_payload[:as_user] = @as_user unless @as_user.nil?
267
+ @common_payload[:username] = @username if @username
268
+ @common_payload[:icon_emoji] = @icon_emoji if @icon_emoji
269
+ @common_payload[:icon_url] = @icon_url if @icon_url
270
+ @common_payload[:mrkdwn] = @mrkdwn if @mrkdwn
271
+ @common_payload[:link_names] = @link_names if @link_names
272
+ @common_payload[:parse] = @parse if @parse
273
+ @common_payload[:token] = @token if @token
274
+ @common_payload
275
+ end
276
+
277
+ def common_attachment
278
+ return @common_attachment if @common_attachment
279
+ @common_attachment = {}
280
+ @common_attachment[:color] = @color if @color
281
+ @common_attachment[:mrkdwn_in] = @mrkdwn_in if @mrkdwn_in
282
+ @common_attachment
283
+ end
284
+
285
+ Field = Struct.new("Field", :title, :value)
286
+ # ruby 1.9.x does not provide #to_h
287
+ Field.send(:define_method, :to_h) { {title: title, value: value} }
288
+
289
+ def build_title_payloads(chunk)
290
+ ch_fields = {}
291
+ chunk.msgpack_each do |tag, time, record|
292
+ channel = build_channel(record)
293
+ per = tag # title per tag
294
+ ch_fields[channel] ||= {}
295
+ ch_fields[channel][per] ||= Field.new(build_title(record), '')
296
+ ch_fields[channel][per].value << "#{build_message(record)}\n"
297
+ end
298
+ ch_fields.map do |channel, fields|
299
+ fallback_text = if @verbose_fallback
300
+ fields.values.map { |f| "#{f.title} #{f.value}" }.join(' ')
301
+ else
302
+ fields.values.map(&:title).join(' ')
303
+ end
304
+
305
+ msg = {
306
+ attachments: [{
307
+ :fallback => fallback_text, # fallback is the message shown on popup
308
+ :fields => fields.values.map(&:to_h)
309
+ }.merge(common_attachment)],
310
+ }
311
+ msg.merge!(channel: channel) if channel
312
+ msg.merge!(common_payload)
313
+ end
314
+ end
315
+
316
+ def build_color_payloads(chunk)
317
+ messages = {}
318
+ chunk.msgpack_each do |tag, time, record|
319
+ channel = build_channel(record)
320
+ messages[channel] ||= ''
321
+ messages[channel] << "#{build_message(record)}\n"
322
+ end
323
+ messages.map do |channel, text|
324
+ msg = {
325
+ attachments: [{
326
+ :fallback => text,
327
+ :text => text,
328
+ }.merge(common_attachment)],
329
+ }
330
+ msg.merge!(channel: channel) if channel
331
+ msg.merge!(common_payload)
332
+ end
333
+ end
334
+
335
+ def build_plain_payloads(chunk)
336
+ messages = {}
337
+ chunk.msgpack_each do |tag, time, record|
338
+ channel = build_channel(record)
339
+ messages[channel] ||= ''
340
+ messages[channel] << "#{build_message(record)}\n"
341
+ end
342
+ messages.map do |channel, text|
343
+ msg = {text: text}
344
+ msg.merge!(channel: channel) if channel
345
+ msg.merge!(common_payload)
346
+ end
347
+ end
348
+
349
+ def build_message(record)
350
+ values = fetch_keys(record, @message_keys)
351
+ @message % values
352
+ end
353
+
354
+ def build_title(record)
355
+ return @title unless @title_keys
356
+
357
+ values = fetch_keys(record, @title_keys)
358
+ @title % values
359
+ end
360
+
361
+ def build_channel(record)
362
+ return nil if @channel.nil?
363
+ return @channel unless @channel_keys
364
+
365
+ values = fetch_keys(record, @channel_keys)
366
+ @channel % values
367
+ end
368
+
369
+ def fetch_keys(record, keys)
370
+ Array(keys).map do |key|
371
+ begin
372
+ accessor = record_accessor_create(key)
373
+ accessor.call(record).to_s
374
+ #record.fetch(key).to_s
375
+ rescue KeyError
376
+ log.warn "out_slack: the specified key '#{key}' not found in record. [#{record}]"
377
+ ''
378
+ end
379
+ end
380
+ end
381
+ end
382
+ end