class Fluent::SpectrumInput
Constants
- INTERVAL_MIN
Configurations
Public Class Methods
new()
click to toggle source
Calls superclass method
# File lib/fluent/plugin/in_spectrum.rb, line 53 def initialize require 'rest-client' require 'json' require 'highwatermark' require 'yaml' super end
Public Instance Methods
configure(conf)
click to toggle source
Calls superclass method
# File lib/fluent/plugin/in_spectrum.rb, line 61 def configure(conf) super @conf = conf # Verify configs # Stop if required fields are not set unless @endpoint && @username && @password raise ConfigError, "Spectrum :: ConfigError 'endpoint' and 'username' and 'password' must be all specified." end # Enforce min interval if @interval.to_i < INTERVAL_MIN raise ConfigError, "Spectrum :: ConfigError 'interval' must be #{INTERVAL_MIN} or over." end # Warn about optional state file unless @state_type == "file" || @state_type =="redis" $log.warn "Spectrum :: 'state_type' is not set to file or redis" $log.warn "Spectrum :: state file or redis are recommended to save the last known good timestamp to resume event consuming" end @highwatermark_parameters={ "state_tag" => @state_tag, "state_type" => @state_type, "state_file" => @state_file, "redis_host" => @redis_host, "redis_port" => @redis_port } $log.info "highwatermark_parameters: #{@highwatermark_parameters}" # default setting for @spectrum_access_code @spectrum_access_code={ "0x11f9c" => "ALARM_ID", "0x11f4e" => "CREATION_DATE", "0x11f56" => "SEVERITY", "0x12b4c" => "ALARM_TITLE", "0x1006e" => "HOSTNAME", "0x12d7f" => "IP_ADDRESS", "0x1296e" => "ORIGINATING_EVENT_ATTR", "0x10000" => "MODEL_STRING", "0x11f4d" => "ACKNOWLEDGED", "0x11f4f" => "ALARM_STATUS", "0x11fc5" => "OCCURRENCES", "0x11f57" => "TROUBLE_SHOOTER", "0x11f9b" => "USER_CLEARABLE", "0x12022" => "TROUBLE_TICKET_ID", "0x12942" => "PERSISTENT", "0x12adb" => "GC_NAME", "0x57f0105" => "CUSTOM_PROJECT", "0x11f51" => "CLEARED_BY_USER_NAME", "0x11f52" => "EVENT_ID_LIST", "0x11f53" => "MODEL_HANDLE", "0x11f54" => "PRIMARY_ALARM", "0x11fc4" => "ALARM_SOURCE", "0x11fc6" => "TROUBLE_SHOOTER_MH", "0x12a6c" => "TROUBLE_SHOOTER_EMAIL", "0x1290d" => "IMPACT_SEVERITY", "0x1290e" => "IMPACT_SCOPE", "0x1298a" => "IMPACT_TYPE_LIST", "0x12948" => "DIAGNOSIS_LOG", "0x129aa" => "MODEL_ID", "0x129ab" => "MODEL_TYPE_ID", "0x129af" => "CLEAR_DATE", "0x12a04" => "SYMPTOM_LIST_ATTR", "0x12a6f" => "EVENT_SYMPTOM_LIST_ATTR", "0x12a05" => "CAUSE_LIST_ATTR", "0x12a06" => "SYMPTOM_COUNT_ATTR", "0x12a70" => "EVENT_SYMPTOM_COUNT_ATTR", "0x12a07" => "CAUSE_COUNT_ATTR", "0x12a63" => "WEB_CONTEXT_URL", "0x12a6b" => "COMBINED_IMPACT_TYPE_LIST", "0x11f50" => "CAUSE_CODE", "0x10009" => "SECURITY_STRING" } # Create XML chunk for attributes we care about @attr_of_interest="" if(@attributes.upcase === "__ALL__") $log.info "all attributes" @spectrum_access_code.each do |key, value| $log.info "key: #{key}, value: #{value}" @attr_of_interest += " <rs:requested-attribute id=\"#{key}\"/>" end else $log.info "selected attributes" @attributes.split(",").each {|attr| key="" value="" # if it's hex code if @spectrum_access_code.has_key?(attr.strip) key = attr.strip value = @spectrum_access_code.fetch(key) # if it's the name elsif @spectrum_access_code.has_value?(attr.strip.upcase) value = attr.strip.upcase key = @spectrum_access_code.key(value) # if it's invalid input, not the hex code or name in the map else raise ConfigError, "Spectrum :: ConfigError attribute '#{attr}' is not in the hash map" end $log.info "key: #{key}, value: #{value}" @attr_of_interest += " <rs:requested-attribute id=\"#{key}\"/>" } end # URL Resource def resource @url = 'http://' + @endpoint.to_s + '/spectrum/restful/alarms' RestClient::Resource.new(@url, :user => @username, :password => @password, :open_timeout => 5, :timeout => (@interval * 3)) end end
on_timer()
click to toggle source
# File lib/fluent/plugin/in_spectrum.rb, line 192 def on_timer if not @stop_flag pollingStart = Engine.now.to_i if @highwatermark.last_records(@state_tag) alertStartTime = @highwatermark.last_records(@state_tag) $log.info "got hwm form state file: #{alertStartTime.to_i}" else alertStartTime = (pollingStart.to_i - @interval.to_i) $log.info "no hwm, got new alert start time: #{alertStartTime.to_i}" end pollingEnd = '' pollingDuration = '' # Format XML for spectrum post @xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <rs:alarm-request throttlesize=\"#{select_limit}\" xmlns:rs=\"http://www.ca.com/spectrum/restful/schema/request\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.ca.com/spectrum/restful/schema/request ../../../xsd/Request.xsd \"> <rs:attribute-filter> <search-criteria xmlns=\"http://www.ca.com/spectrum/restful/schema/filter\"> <filtered-models> <greater-than> <attribute id=\"0x11f4e\"> <value> #{alertStartTime} </value> </attribute> </greater-than> </filtered-models> </search-criteria> </rs:attribute-filter> #{@attr_of_interest} </rs:alarm-request>" # Post to Spectrum and parse results begin res=resource.post @xml,:content_type => 'application/xml',:accept => 'application/json' body = JSON.parse(res.body) pollingEnd = Time.parse(res.headers[:date]).to_i pollingDuration = Engine.now.to_i - pollingStart end # Processing for multiple alerts returned if body['ns1.alarm-response-list']['@total-alarms'].to_i > 1 $log.info "Spectrum :: returned #{body['ns1.alarm-response-list']['@total-alarms'].to_i} alarms for period < #{alertStartTime.to_i} took #{pollingDuration.to_i} seconds, ended at #{pollingEnd}" # iterate through each alarm body['ns1.alarm-response-list']['ns1.alarm-responses']['ns1.alarm'].each do |alarm| # Create initial structure record_hash = Hash.new # temp hash to hold attributes of alarm raw_array = Array.new # temp hash to hold attributes of alarm for raw record_hash['event_type'] = @tag.to_s record_hash['intermediary_source'] = @endpoint.to_s record_hash['receive_time_input'] = pollingEnd.to_s # iterate though alarm attributes alarm['ns1.attribute'].each do |attribute| key,value = parseAttributes(attribute) record_hash[key] = value if @include_raw.to_s == "true" raw_array << { "#{key}" => "#{value}" } end end # append raw object if @include_raw.to_s == "true" record_hash[:raw] = raw_array end Engine.emit(@tag, record_hash['CREATION_DATE'].to_i,record_hash) end # Processing for single alarm returned elsif body['ns1.alarm-response-list']['@total-alarms'].to_i == 1 $log.info "Spectrum :: returned #{body['ns1.alarm-response-list']['@total-alarms'].to_i} alarms for period < #{alertStartTime.to_i} took #{pollingDuration.to_i} seconds, ended at #{pollingEnd}" # Create initial structure record_hash = Hash.new # temp hash to hold attributes of alarm raw_array = Array.new # temp hash to hold attributes of alarm for raw record_hash['event_type'] = @tag.to_s record_hash['intermediary_source'] = @endpoint.to_s record_hash['receive_time_input'] = pollingEnd.to_s # iterate though alarm attributes and add to temp hash body['ns1.alarm-response-list']['ns1.alarm-responses']['ns1.alarm']['ns1.attribute'].each do |attribute| key,value = parseAttributes(attribute) record_hash[key] = value if @include_raw.to_s == "true" raw_array << { "#{key}" => "#{value}" } end end # append raw object if @include_raw.to_s == "true" record_hash[:raw] = raw_array end Engine.emit(@tag, record_hash['CREATION_DATE'].to_i,record_hash) # No alarms returned else $log.info "Spectrum :: returned #{body['ns1.alarm-response-list']['@total-alarms'].to_i} alarms for period < #{alertStartTime.to_i} took #{pollingDuration.to_i} seconds, ended at #{pollingEnd}" end @highwatermark.update_records(pollingEnd,@state_tag) end end
parseAttributes(alarmAttribute)
click to toggle source
# File lib/fluent/plugin/in_spectrum.rb, line 47 def parseAttributes(alarmAttribute) key = @spectrum_access_code[alarmAttribute['@id'].to_s].to_s value = ((to_utf8(alarmAttribute['$'].to_s)).strip).gsub(/\r?\n/, " ") return key,value end
resource()
click to toggle source
URL Resource
# File lib/fluent/plugin/in_spectrum.rb, line 164 def resource @url = 'http://' + @endpoint.to_s + '/spectrum/restful/alarms' RestClient::Resource.new(@url, :user => @username, :password => @password, :open_timeout => 5, :timeout => (@interval * 3)) end
run()
click to toggle source
# File lib/fluent/plugin/in_spectrum.rb, line 185 def run @loop.run rescue $log.error "unexpected error", :error=>$!.to_s $log.error_backtrace end
shutdown()
click to toggle source
# File lib/fluent/plugin/in_spectrum.rb, line 178 def shutdown #@loop.watchers.each {|w| w.detach} @stop_flag = true @loop.stop @thread.join end
start()
click to toggle source
# File lib/fluent/plugin/in_spectrum.rb, line 170 def start @stop_flag = false @highwatermark = Highwatermark::HighWaterMark.new(@highwatermark_parameters) @loop = Coolio::Loop.new @loop.attach(TimerWatcher.new(@interval, true, &method(:on_timer))) @thread = Thread.new(&method(:run)) end
to_utf8(str)
click to toggle source
function to UTF8 encode
# File lib/fluent/plugin/in_spectrum.rb, line 41 def to_utf8(str) str = str.force_encoding('UTF-8') return str if str.valid_encoding? str.encode("UTF-8", 'binary', invalid: :replace, undef: :replace, replace: '') end