Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/logging/log_dispatcher.rb
Views: 11777
# -*- coding: binary -*-1require 'rex/sync'23module Rex4module Logging56###7#8# The log dispatcher associates log sources with log sinks. A log source9# is a unique identity that is associated with one and only one log sink.10# For instance, the framework-core registers the 'core'11#12###13class LogDispatcher1415#16# Creates the global log dispatcher instance and initializes it for use.17#18def initialize()19self.log_sinks = {}20self.log_levels = {}21self.log_sinks_lock = Mutex.new22end2324#25# Returns the sink that is associated with the supplied source.26#27def [](src)28sink = nil2930log_sinks_lock.synchronize {31sink = log_sinks[src]32}3334return sink35end3637#38# Calls the source association routie.39#40def []=(src, sink)41store(src, sink)42end4344#45# Associates the supplied source with the supplied sink. If a log level46# has already been defined for the source, the level argument is ignored.47# Use set_log_level to alter it.48#49def store(src, sink, level = 0)50log_sinks_lock.synchronize {51if (log_sinks[src] == nil)52log_sinks[src] = sink5354set_log_level(src, level) if (log_levels[src] == nil)55else56raise(57RuntimeError,58"The supplied log source #{src} is already registered.",59caller)60end61}62end6364#65# Removes a source association if one exists.66#67def delete(src)68sink = nil6970log_sinks_lock.synchronize {71sink = log_sinks[src]7273log_sinks.delete(src)74}7576if (sink)77sink.cleanup7879return true80end8182return false83end8485#86# Performs the actual log operation against the supplied source87#88def log(sev, src, level, msg)89log_sinks_lock.synchronize {90if ((sink = log_sinks[src]))91next if (log_levels[src] and level > log_levels[src])9293sink.log(sev, src, level, msg)94end95}96end9798#99# This method sets the log level threshold for a given source.100#101def set_level(src, level)102log_levels[src] = level.to_i103end104105#106# This method returns the log level threshold of a given source.107#108def get_level(src)109log_levels.fetch(src, DEFAULT_LOG_LEVEL)110end111112attr_accessor :log_sinks, :log_sinks_lock # :nodoc:113attr_accessor :log_levels # :nodoc:114end115116end117end118119# An instance of the log dispatcher exists in the global namespace, along120# with stubs for many of the common logging methods. Various sources can121# register themselves as a log sink such that logs can be directed at122# various targets depending on where they're sourced from. By doing it123# this way, things like sessions can use the global logging stubs and124# still be directed at the correct log file.125#126###127ExceptionCallStack = "__EXCEPTCALLSTACK__"128129BACKTRACE_LOG_LEVEL = 3 # Equal to LEV_3130DEFAULT_LOG_LEVEL = 0 # Equal to LEV_3131132def dlog(msg, src = 'core', level = 0)133$dispatcher.log(LOG_DEBUG, src, level, msg)134end135136# Logs errors in a standard format for each Log Level.137#138# @param msg [String] Contains message from the developer explaining why an error was encountered.139# Can also be an +Exception+, in which case a log is built from the +Exception+ with no accompanying message.140#141# @param src [String] Used to indicate where the error is originating from. Most commonly set to 'core'.142#143# @param log_level [Integer] Indicates the level of logging the message should be recorded at. If log_level is greater than144# the global log level set for +src+, then the log is not recorded.145#146# @param error [Exception] Exception of an error that needs to be logged. For all log messages, the class and message of147# an exception is added to a log message. If the global log level set for +src+ is greater than +BACKTRACE_LOG_LEVEL+,148# then the stack trace for an error is also added to the log message.149#150# (Eg Loop Iterations, Variables, Function Calls).151#152# @return [NilClass].153def elog(msg, src = 'core', log_level = 0, error: nil)154error = msg.is_a?(Exception) ? msg : error155156if error.nil? || !error.is_a?(Exception)157$dispatcher.log(LOG_ERROR, src, log_level, msg)158else159error_details = "#{error.class} #{error.message}"160if get_log_level(src) >= BACKTRACE_LOG_LEVEL161if error.backtrace162error_details << "\nCall stack:\n#{error.backtrace.join("\n")}"163else164error_details << "\nCall stack:\nNone"165end166end167168if msg.is_a?(Exception)169$dispatcher.log(LOG_ERROR, src, log_level,"#{error_details}")170else171$dispatcher.log(LOG_ERROR, src, log_level,"#{msg} - #{error_details}")172end173end174end175176def wlog(msg, src = 'core', level = 0)177$dispatcher.log(LOG_WARN, src, level, msg)178end179180def ilog(msg, src = 'core', level = 0)181$dispatcher.log(LOG_INFO, src, level, msg)182end183184def rlog(msg, src = 'core', level = 0)185if (msg == ExceptionCallStack)186msg = "\nCall stack:\n" + $@.join("\n") + "\n"187end188189$dispatcher.log(LOG_RAW, src, level, msg)190end191192def log_source_registered?(src)193($dispatcher[src] != nil)194end195196def register_log_source(src, sink, level = nil)197$dispatcher[src] = sink198199set_log_level(src, level) if (level)200end201202def deregister_log_source(src)203$dispatcher.delete(src)204end205206def set_log_level(src, level)207$dispatcher.set_level(src, level)208end209210def get_log_level(src)211$dispatcher.get_level(src)212end213214# Creates the global log dispatcher215$dispatcher = Rex::Logging::LogDispatcher.new216217218