Path: blob/trunk/rb/lib/selenium/webdriver/common/logger.rb
1865 views
# frozen_string_literal: true12# Licensed to the Software Freedom Conservancy (SFC) under one3# or more contributor license agreements. See the NOTICE file4# distributed with this work for additional information5# regarding copyright ownership. The SFC licenses this file6# to you under the Apache License, Version 2.0 (the7# "License"); you may not use this file except in compliance8# with the License. You may obtain a copy of the License at9#10# http://www.apache.org/licenses/LICENSE-2.011#12# Unless required by applicable law or agreed to in writing,13# software distributed under the License is distributed on an14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY15# KIND, either express or implied. See the License for the16# specific language governing permissions and limitations17# under the License.1819require 'forwardable'20require 'logger'2122module Selenium23module WebDriver24#25# @example Enable full logging26# Selenium::WebDriver.logger.level = :debug27#28# @example Log to file29# Selenium::WebDriver.logger.output = 'selenium.log'30#31# @example Use logger manually32# Selenium::WebDriver.logger.info('This is info message')33# Selenium::WebDriver.logger.warn('This is warning message')34#35class Logger36extend Forwardable3738def_delegators :@logger,39:close,40:debug?,41:info?,42:warn?,43:error?,44:fatal, :fatal?,45:level4647#48# @param [String] progname Allow child projects to use Selenium's Logger pattern49#50def initialize(progname = 'Selenium', default_level: nil, ignored: nil, allowed: nil)51default_level ||= $DEBUG || ENV.key?('DEBUG') ? :debug : :warn5253@logger = create_logger(progname, level: default_level)54@ignored = Array(ignored)55@allowed = Array(allowed)56@first_warning = false57end5859def level=(level)60if level == :info && @logger.level == :info61info(':info is now the default log level, to see additional logging, set log level to :debug')62end6364@logger.level = level65end6667#68# Changes logger output to a new IO.69#70# @param [String] io71#72def output=(io)73@logger.reopen(io)74end7576#77# Returns IO object used by logger internally.78#79# Normally, we would have never needed it, but we want to80# use it as IO object for all child processes to ensure their81# output is redirected there.82#83# It is only used in debug level, in other cases output is suppressed.84#85# @api private86#87def io88@logger.instance_variable_get(:@logdev).dev89end9091#92# Will not log the provided ID.93#94# @param [Array, Symbol] ids95#96def ignore(*ids)97@ignored += Array(ids).flatten98end99100#101# Will only log the provided ID.102#103# @param [Array, Symbol] ids104#105def allow(*ids)106@allowed += Array(ids).flatten107end108109#110# Used to supply information of interest for debugging a problem111# Overrides default #debug to skip ignored messages by provided id112#113# @param [String] message114# @param [Symbol, Array<Symbol>] id115# @yield see #deprecate116#117def debug(message, id: [], &block)118discard_or_log(:debug, message, id, &block)119end120121#122# Used to supply information of general interest123#124# @param [String] message125# @param [Symbol, Array<Symbol>] id126# @yield see #deprecate127#128def info(message, id: [], &block)129discard_or_log(:info, message, id, &block)130end131132#133# Used to supply information that suggests an error occurred134#135# @param [String] message136# @param [Symbol, Array<Symbol>] id137# @yield see #deprecate138#139def error(message, id: [], &block)140discard_or_log(:error, message, id, &block)141end142143#144# Used to supply information that suggests action be taken by user145#146# @param [String] message147# @param [Symbol, Array<Symbol>] id148# @yield see #deprecate149#150def warn(message, id: [], &block)151discard_or_log(:warn, message, id, &block)152end153154#155# Marks code as deprecated with/without replacement.156#157# @param [String] old158# @param [String, nil] new159# @param [Symbol, Array<Symbol>] id160# @param [String] reference161# @yield appends additional message to end of provided template162#163def deprecate(old, new = nil, id: [], reference: '', &block)164id = Array(id)165return if @ignored.include?(:deprecations)166167id << :deprecations if @allowed.include?(:deprecations)168169message = "[DEPRECATION] #{old} is deprecated"170message << if new171". Use #{new} instead."172else173' and will be removed in a future release.'174end175message << " See explanation for this deprecation: #{reference}." unless reference.empty?176177discard_or_log(:warn, message, id, &block)178end179180private181182def create_logger(name, level:)183logger = ::Logger.new($stderr)184logger.progname = name185logger.level = level186logger.formatter = proc do |severity, time, progname, msg|187"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n".force_encoding('UTF-8')188end189190logger191end192193def discard_or_log(level, message, id)194id = Array(id)195return if @ignored.intersect?(id)196return if @allowed.any? && !@allowed.intersect?(id)197198return if ::Logger::Severity.const_get(level.upcase) < @logger.level199200unless @first_warning201@first_warning = true202info("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do203"https://selenium.dev/documentation/webdriver/troubleshooting/logging\n"204end205end206207msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "208msg += " #{yield}" if block_given?209210@logger.send(level) { msg }211end212end # Logger213end # WebDriver214end # Selenium215216217