Skip to content

Commit

Permalink
[rb] Initial implementation of Logger class
Browse files Browse the repository at this point in the history
  • Loading branch information
p0deje committed Feb 21, 2017
1 parent d949ae4 commit 4f07336
Show file tree
Hide file tree
Showing 19 changed files with 174 additions and 63 deletions.
10 changes: 10 additions & 0 deletions rb/lib/selenium/webdriver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,15 @@ def self.root
def self.for(*args)
WebDriver::Driver.for(*args)
end

#
# Returns logger instance that can be used across the whole Selenium.
#
# @return [Logger]
#

def self.logger
@logger ||= WebDriver::Logger.new
end
end # WebDriver
end # Selenium
5 changes: 2 additions & 3 deletions rb/lib/selenium/webdriver/chrome/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ class Service < WebDriver::Service

def start_process
server_command = [@executable_path, "--port=#{@port}", *@extra_args]
@process = ChildProcess.build(*server_command)

@process.io.inherit! if $DEBUG
@process = ChildProcess.build(*server_command)
@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.leader = true unless Platform.windows?
@process.start
end
Expand Down
1 change: 1 addition & 0 deletions rb/lib/selenium/webdriver/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
require 'selenium/webdriver/common/navigation'
require 'selenium/webdriver/common/timeouts'
require 'selenium/webdriver/common/window'
require 'selenium/webdriver/common/logger'
require 'selenium/webdriver/common/logs'
require 'selenium/webdriver/common/options'
require 'selenium/webdriver/common/w3c_options'
Expand Down
79 changes: 79 additions & 0 deletions rb/lib/selenium/webdriver/common/logger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# encoding: utf-8
#
# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

require 'forwardable'
require 'logger'

module Selenium
module WebDriver
#
# @example Enable full logging
# Selenium::WebDriver.logger.level = :debug
#
# @example Log to file
# Selenium::WebDriver.logger.output = 'selenium.log'
#
# @example Use logger manually
# Selenium::WebDriver.logger.info('This is info message')
# Selenium::WebDriver.logger.warn('This is warning message')
#
class Logger
extend Forwardable

def_delegators :@logger, :debug, :debug?,
:info, :info?,
:warn, :warn?,
:error, :error?,
:fatal, :fatal?,
:level, :level=

def initialize
@logger = ::Logger.new($stdout)
@logger.progname = 'Selenium'
@logger.level = ($DEBUG ? :debug : :warn)
@logger.formatter = proc do |severity, time, progname, msg|
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
end
end

def output=(io)
@logger.reopen(io)
end

#
# Returns IO object used by logger internally.
#
# Normally, we would have never needed it, but we want to
# use it as IO object for all child processes to ensure their
# output is redirected there.
#
# It is only used in debug level, in other cases output is suppressed.
#
# @api private
#
def io
if debug?
@logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
else
File.new(Platform.null_device, 'w')
end
end
end # Logger
end # WebDriver
end # Selenium
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/common/port_prober.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def self.free?(port)
begin
TCPServer.new(host, port).close
rescue *IGNORED_ERRORS => ex
$stderr.puts "port prober could not bind to #{host}:#{port} (#{ex.message})" if $DEBUG
WebDriver.logger.info("port prober could not bind to #{host}:#{port} (#{ex.message})")
# ignored - some machines appear unable to bind to some of their interfaces
end
end
Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/common/socket_lock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def can_lock?

true
rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => ex
$stderr.puts "#{self}: #{ex.message}" if $DEBUG
WebDriver.logger.info("#{self}: #{ex.message}")
false
end

Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/common/socket_poller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def listening?
true
rescue *NOT_CONNECTED_ERRORS
sock.close if sock
$stderr.puts [@host, @port].inspect if $DEBUG
WebDriver.logger.info("polling for socket on #{[@host, @port].inspect}")
false
end
end
Expand Down
5 changes: 2 additions & 3 deletions rb/lib/selenium/webdriver/edge/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ class Service < WebDriver::Service

def start_process
server_command = [@executable_path, "--port=#{@port}", *@extra_args]
@process = ChildProcess.build(*server_command)

@process.io.inherit! if $DEBUG
@process = ChildProcess.build(*server_command)
@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.start
end

Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/firefox/binary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def wait
def execute(*extra_args)
args = [self.class.path, '-no-remote'] + extra_args
@process = ChildProcess.build(*args)
@process.io.inherit! if $DEBUG
@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.start
end

Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/firefox/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def install_extensions(directory)
destination = File.join(directory, 'extensions')

@extensions.each do |name, extension|
p extension: name if $DEBUG
WebDriver.logger.info({extenstion: name}.inspect)
extension.write_to(destination)
end
end
Expand Down
22 changes: 2 additions & 20 deletions rb/lib/selenium/webdriver/firefox/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,11 @@ def stop

def start_process
server_command = [@executable_path, "--binary=#{Firefox::Binary.path}", "--port=#{@port}", *@extra_args]
@process = ChildProcess.build(*server_command)

if $DEBUG
@process.io.inherit!
elsif Platform.windows?
# workaround stdio inheritance issue
# https://github.com/mozilla/geckodriver/issues/48
@process.io.stdout = @process.io.stderr = File.new(Platform.null_device, 'w')
end

@process = ChildProcess.build(*server_command)
@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.start
end

def stop_process
super
return unless Platform.windows? && !$DEBUG
begin
@process.io.close
rescue
nil
end
end

def cannot_connect_error_text
"unable to connect to Mozilla geckodriver #{@host}:#{@port}"
end
Expand Down
5 changes: 2 additions & 3 deletions rb/lib/selenium/webdriver/ie/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ class Service < WebDriver::Service

def start_process
server_command = [@executable_path, "--port=#{@port}", *@extra_args]
@process = ChildProcess.new(*server_command)

@process.io.inherit! if $DEBUG
@process = ChildProcess.new(*server_command)
@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.start
end

Expand Down
19 changes: 1 addition & 18 deletions rb/lib/selenium/webdriver/phantomjs/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,10 @@ class Service < WebDriver::Service
def start_process
server_command = [@executable_path, "--webdriver=#{@port}", *@extra_args]
@process = ChildProcess.build(*server_command.compact)

if $DEBUG
@process.io.inherit!
elsif Platform.jruby?
# apparently we need to read the output for phantomjs to work on jruby
@process.io.stdout = @process.io.stderr = File.new(Platform.null_device, 'w')
end

@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.start
end

def stop_process
super
return unless Platform.jruby? && !$DEBUG
begin
@process.io.close
rescue
nil
end
end

def cannot_connect_error_text
"unable to connect to phantomjs @ #{uri} after #{START_TIMEOUT} seconds"
end
Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/remote/bridge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ def raw_execute(command, opts = {}, command_hash = nil)
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
end

puts "-> #{verb.to_s.upcase} #{path}" if $DEBUG
WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
http.call verb, path, command_hash
end

Expand Down
8 changes: 3 additions & 5 deletions rb/lib/selenium/webdriver/remote/http/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,8 @@ def call(verb, url, command_hash)
headers['Content-Type'] = "#{CONTENT_TYPE}; charset=utf-8"
headers['Content-Length'] = payload.bytesize.to_s if [:post, :put].include?(verb)

if $DEBUG
puts " >>> #{url} | #{payload}"
puts " > #{headers.inspect}"
end
WebDriver.logger.info(" >>> #{url} | #{payload}")
WebDriver.logger.info(" > #{headers.inspect}")
elsif verb == :post
payload = '{}'
headers['Content-Length'] = '2'
Expand All @@ -78,7 +76,7 @@ def create_response(code, body, content_type)
code = code.to_i
body = body.to_s.strip
content_type = content_type.to_s
puts "<- #{body}\n" if $DEBUG
WebDriver.logger.info("<- #{body}")

if content_type.include? CONTENT_TYPE
raise Error::WebDriverError, "empty body: #{content_type.inspect} (#{code})\n#{body}" if body.empty?
Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/remote/http/curb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def client
c.max_redirects = MAX_REDIRECTS
c.follow_location = true
c.timeout = @timeout if @timeout
c.verbose = $DEBUG
c.verbose = WebDriver.logger.info?

c
)
Expand Down
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/remote/w3c_bridge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ def raw_execute(command, opts = {}, command_hash = nil)
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
end

puts "-> #{verb.to_s.upcase} #{path}" if $DEBUG
WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
http.call verb, path, command_hash
end

Expand Down
5 changes: 2 additions & 3 deletions rb/lib/selenium/webdriver/safari/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ def binary_path(path)

def start_process
server_command = [@executable_path, "--port=#{@port}", *@extra_args]
@process = ChildProcess.build(*server_command)

@process.io.inherit! if $DEBUG
@process = ChildProcess.build(*server_command)
@process.io.stdout = @process.io.stderr = WebDriver.logger.io
@process.start
end

Expand Down
62 changes: 62 additions & 0 deletions rb/spec/unit/selenium/webdriver/common/logger_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# encoding: utf-8
#
# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

require File.expand_path('../../spec_helper', __FILE__)

module Selenium
module WebDriver
describe Logger do
around do |example|
WebDriver.instance_variable_set(:@logger, nil) # reset cache
debug = $DEBUG
$DEBUG = false
example.call
$DEBUG = debug
end

it 'logs warnings by default' do
expect(WebDriver.logger.level).to eq(2)
end

it 'logs everything if $DEBUG is set to true' do
$DEBUG = true
expect(WebDriver.logger.level).to eq(0)
end

it 'allows to change level during execution' do
WebDriver.logger.level = :info
expect(WebDriver.logger.level).to eq(1)
end

it 'outputs to stdout by default' do
expect { WebDriver.logger.warn('message') }.to output(/WARN Selenium message/).to_stdout
end

it 'allows to output to file' do
begin
WebDriver.logger.output = 'test.log'
WebDriver.logger.warn('message')
expect(File.read('test.log')).to include('WARN Selenium message')
ensure
File.delete('test.log')
end
end
end
end # WebDriver
end # Selenium

0 comments on commit 4f07336

Please sign in to comment.