#!/usr/bin/env ruby # The MIT License # # Copyright (c) 2015 Marcelo "Ataxexe" GuimarĂ£es # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'yummi' require 'optparse' require_relative '../lib/sherlog_holmes' include Sherlog @opts = OptionParser::new @stacktrace = true @filter = nil @operation = :and @listeners = {} @groups = [] def add_filter(filter) filter = filter.negate if @negate if @filter @filter = @filter.send @operation, filter else @filter = filter end @negate = false end def print_table(name, data) table = Yummi::Table::new table.title = name.to_s.capitalize table.header = %w{Name Count} table.colorize :name, with: 'bold.white' table.colorize :count, with: 'magenta' data.each do |name, count| table << [name, count] end table.print puts end @opts.banner = 'Usage: sherlog [options] [logfile ...]' @opts.separator "\n Config Options\n".bold.white @opts.on '-p FILE', '--patterns FILE', 'Configures the patterns' do |file| Sherlog.load_patterns file end @opts.on '--encode ENCODE', 'Sets the encode to read the log' do |encode| ENV['SHERLOG_FILE_ENCODE'] = encode end @opts.on '-t TYPE', '--type TYPE', 'Sets the type of the log (for loading patterns)' do |type| @type = type.to_sym end @opts.separator "\n Filter Options\n".bold.white @opts.on '-c EXPRESSION', '--category EXPRESSION', 'Set the category filter expression' do |expression| add_filter Filter::category(expression) end @opts.on '-l EXPRESSION', '--level EXPRESSION', 'Set the level filter expression' do |expression| add_filter Filter::level(expression) end @opts.on '-o EXPRESSION', '--origin EXPRESSION', 'Sets the origin filter expression' do |expression| add_filter Filter::origin(expression) end @opts.on '-m EXPRESSION', '--message EXPRESSION', 'Set the message filter expression' do |expression| add_filter Filter::message(expression) end @opts.on '-e EXPRESSION', '--exception EXPRESSION', 'Sets the exception filter expression' do |expression| add_filter Filter::exception(expression) end @opts.on '--any-exception', 'Filter exception entries' do add_filter Filter::exceptions end @opts.on '-f NAME', '--field NAME', 'Sets the custom attribute filter name' do |name| @field = name end @opts.on '-v EXPRESSION', '--value EXPRESSION', 'Sets the custom attribute filter expression' do |expression| add_filter Filter::custom_attribute(@field, expression) end @opts.separator "\n Logical Options\n".bold.white @opts.on '--and', 'Sets the next filter to use the AND operator' do @operation = :and end @opts.on '--or', 'Sets the next filter to use the OR operation' do @operation = :or end @opts.on '--not', 'Negates the next filter' do @negate = true end @opts.separator "\n Operation Options\n".bold.white @opts.on '--print', 'Prints the filtered entries' do @listeners[:print] = PrintListener::new end @opts.on '--no-stacktrace', 'Do not print stacktraces (use with --print)' do @no_stacktrace = true end @opts.on '--count GROUPS...', 'Counts entries and print the result by group (level, category, origin, exception or all)', Array do |groups| all_groups = [:level, :category, :origin, :exception] @groups = if groups == ['all'] all_groups else all_groups.find_all do |name| groups.index name.to_s end end @listeners[:count] = CountListener::new end @opts.on '-h', '--help', 'Shows the usage help' do puts @opts exit end @opts.parse! ARGV @listeners[:print].hide_stacktrace if @no_stacktrace and @listeners[:print] parser = Sherlog.parser @type if @type parser ||= Parser::new parser.filter @filter @listeners.values.each do |listener| parser.on_new_entry listener end begin if ARGV.empty? ARGF.each_line do |line| parser.parse line.chomp end else ARGV.each do |file| parser.parse file end end @groups.each do |group| print_table group, @listeners[:count].send(group).sort_by { |name, count| -count } end rescue Interrupt exit end