class Fluent::SlackOutput
Constants
- Field
Attributes
localtime[R]
for test
mrkdwn_in[R]
for test
post_message_opts[R]
for test
slack[R]
for test
time_format[R]
for test
timef[R]
for test
Public Class Methods
desc(description)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 13 def desc(description) end
new()
click to toggle source
Calls superclass method
# File lib/fluent/plugin/out_buffered_slack.rb, line 127 def initialize super require 'uri' end
Public Instance Methods
configure(conf)
click to toggle source
Calls superclass method
# File lib/fluent/plugin/out_buffered_slack.rb, line 132 def configure(conf) conf['time_format'] ||= '%H:%M:%S' # old version compatiblity conf['localtime'] ||= true unless conf['utc'] super if @channel @channel = URI.unescape(@channel) # old version compatibility if !@channel.start_with?('#') and !@channel.start_with?('@') @channel = '#' + @channel # Add # since `#` is handled as a comment in fluentd conf end end if @webhook_url if @webhook_url.empty? raise Fluent::ConfigError.new("`webhook_url` is an empty string") end unless @as_user.nil? log.warn "out_slack: `as_user` parameter are not available for Incoming Webhook" end @slack = Fluent::SlackClient::IncomingWebhook.new(@webhook_url) elsif @slackbot_url if @slackbot_url.empty? raise Fluent::ConfigError.new("`slackbot_url` is an empty string") end if @channel.nil? raise Fluent::ConfigError.new("`channel` parameter required for Slackbot Remote Control") end if @username or @color or @icon_emoji or @icon_url log.warn "out_slack: `username`, `color`, `icon_emoji`, `icon_url` parameters are not available for Slackbot Remote Control" end unless @as_user.nil? log.warn "out_slack: `as_user` parameter are not available for Slackbot Remote Control" end @slack = Fluent::SlackClient::Slackbot.new(@slackbot_url) elsif @token if @token.empty? raise Fluent::ConfigError.new("`token` is an empty string") end if @channel.nil? raise Fluent::ConfigError.new("`channel` parameter required for Slack WebApi") end @slack = Fluent::SlackClient::WebApi.new else raise Fluent::ConfigError.new("One of `webhook_url` or `slackbot_url`, or `token` is required") end @slack.log = log @slack.debug_dev = log.out if log.level <= Fluent::Log::LEVEL_TRACE if @https_proxy @slack.https_proxy = @https_proxy end @message ||= '%s' @message_keys ||= %w[message] begin @message % (['1'] * @message_keys.length) rescue ArgumentError raise Fluent::ConfigError, "string specifier '%s' for `message` and `message_keys` specification mismatch" end if @title and @title_keys begin @title % (['1'] * @title_keys.length) rescue ArgumentError raise Fluent::ConfigError, "string specifier '%s' for `title` and `title_keys` specification mismatch" end end if @channel && @channel_keys begin @channel % (['1'] * @channel_keys.length) rescue ArgumentError raise Fluent::ConfigError, "string specifier '%s' for `channel` and `channel_keys` specification mismatch" end end if @icon_emoji and @icon_url raise Fluent::ConfigError, "either of `icon_emoji` or `icon_url` can be specified" end if @as_user and (@icon_emoji or @icon_url or @username) raise Fluent::ConfigError, "`username`, `icon_emoji` and `icon_url` cannot be specified when `as_user` is set to true" end if @mrkdwn # Enable markdown for attachments. See https://api.slack.com/docs/formatting @mrkdwn_in = %w[text fields] end if @parse and !%w[none full].include?(@parse) raise Fluent::ConfigError, "`parse` must be either of `none` or `full`" end @post_message_opts = {} if @auto_channels_create raise Fluent::ConfigError, "`token` parameter is required to use `auto_channels_create`" unless @token @post_message_opts = {auto_channels_create: true} end end
format(tag, time, record)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 233 def format(tag, time, record) [tag, time, record].to_msgpack end
write(chunk)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 237 def write(chunk) begin payloads = build_payloads(chunk) payloads.each {|payload| @slack.post_message(payload, @post_message_opts) } rescue Timeout::Error => e log.warn "out_slack:", :error => e.to_s, :error_class => e.class.to_s raise e # let Fluentd retry rescue => e log.error "out_slack:", :error => e.to_s, :error_class => e.class.to_s log.warn_backtrace e.backtrace # discard. @todo: add more retriable errors end end
Private Instance Methods
build_channel(record)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 361 def build_channel(record) return nil if @channel.nil? return @channel unless @channel_keys values = fetch_keys(record, @channel_keys) @channel % values end
build_color_payloads(chunk)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 316 def build_color_payloads(chunk) messages = {} chunk.msgpack_each do |tag, time, record| channel = build_channel(record) messages[channel] ||= '' messages[channel] << "#{build_message(record)}\n" end messages.map do |channel, text| msg = { attachments: [{ :fallback => text, :text => text, }.merge(common_attachment)], } msg.merge!(channel: channel) if channel msg.merge!(common_payload) end end
build_message(record)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 349 def build_message(record) values = fetch_keys(record, @message_keys) @message % values end
build_payloads(chunk)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 253 def build_payloads(chunk) if @title build_title_payloads(chunk) elsif @color build_color_payloads(chunk) else build_plain_payloads(chunk) end end
build_plain_payloads(chunk)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 335 def build_plain_payloads(chunk) messages = {} chunk.msgpack_each do |tag, time, record| channel = build_channel(record) messages[channel] ||= '' messages[channel] << "#{build_message(record)}\n" end messages.map do |channel, text| msg = {text: text} msg.merge!(channel: channel) if channel msg.merge!(common_payload) end end
build_title(record)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 354 def build_title(record) return @title unless @title_keys values = fetch_keys(record, @title_keys) @title % values end
build_title_payloads(chunk)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 289 def build_title_payloads(chunk) ch_fields = {} chunk.msgpack_each do |tag, time, record| channel = build_channel(record) per = tag # title per tag ch_fields[channel] ||= {} ch_fields[channel][per] ||= Field.new(build_title(record), '') ch_fields[channel][per].value << "#{build_message(record)}\n" end ch_fields.map do |channel, fields| fallback_text = if @verbose_fallback fields.values.map { |f| "#{f.title} #{f.value}" }.join(' ') else fields.values.map(&:title).join(' ') end msg = { attachments: [{ :fallback => fallback_text, # fallback is the message shown on popup :fields => fields.values.map(&:to_h) }.merge(common_attachment)], } msg.merge!(channel: channel) if channel msg.merge!(common_payload) end end
common_attachment()
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 277 def common_attachment return @common_attachment if @common_attachment @common_attachment = {} @common_attachment[:color] = @color if @color @common_attachment[:mrkdwn_in] = @mrkdwn_in if @mrkdwn_in @common_attachment end
common_payload()
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 263 def common_payload return @common_payload if @common_payload @common_payload = {} @common_payload[:as_user] = @as_user unless @as_user.nil? @common_payload[:username] = @username if @username @common_payload[:icon_emoji] = @icon_emoji if @icon_emoji @common_payload[:icon_url] = @icon_url if @icon_url @common_payload[:mrkdwn] = @mrkdwn if @mrkdwn @common_payload[:link_names] = @link_names if @link_names @common_payload[:parse] = @parse if @parse @common_payload[:token] = @token if @token @common_payload end
fetch_keys(record, keys)
click to toggle source
# File lib/fluent/plugin/out_buffered_slack.rb, line 369 def fetch_keys(record, keys) Array(keys).map do |key| begin accessor = record_accessor_create(key) accessor.call(record).to_s #record.fetch(key).to_s rescue KeyError log.warn "out_slack: the specified key '#{key}' not found in record. [#{record}]" '' end end end