Skip to content

Commit

Permalink
Add support for SemanticLogger
Browse files Browse the repository at this point in the history
  • Loading branch information
coderberry committed Feb 1, 2024
1 parent ce8c918 commit e17b191
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 42 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Whoop.setup do |config|
config.logger = ActiveSupport::Logger.new("log/debug.log")
# config.logger = ActiveSupport::Logger.new("log/#{Rails.env}.log")
# config.logger = ActiveSupport::Logger.new($stdout)
# config.logger = SemanticLogger["WHOOP"]
# config.logger = nil # uses `puts`

config.level = :debug
Expand Down Expand Up @@ -63,6 +64,7 @@ You can pass any options into the `whoop` method to change the output.
- `caller_depth` - the depth of the caller to use for the source (default: 0)
- `explain` - whether to run `EXPLAIN` on the SQL query (default: false)
- `context` - a hash of key/value pairs to include in the output
- `tags` - an array of tags to include in the output

## Examples

Expand Down
85 changes: 49 additions & 36 deletions lib/whoop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
require "active_support"
require "colorize"
require "rouge"
require "semantic_logger"

require_relative "whoop/version"
require_relative "whoop/formatters/json_formatter"
require_relative "whoop/formatters/pretty_formatter"
Expand Down Expand Up @@ -40,9 +42,10 @@ module Main
# @param [String] pattern - the pattern to use for the line (e.g. '-')
# @param [Integer] count - the number of times to repeat the pattern per line (e.g. 80)
# @param [Symbol] color - the color to use for the line (e.g. :red)
# @param [Symbol] format - the format to use for the message (one of :json, :sql, :plain, :pretty (default))
# @param [Symbol] format - the format to use for the message (one of :json, :sql, :plain, :semantic, :pretty (default))
# @param [Integer] caller_depth - the depth of the caller to use for the source (default: 0)
# @param [Boolean] explain - whether to explain the SQL query (default: false)
# @param [Array<String, Symbol>] tags - Any tags you'd like to include in the log
# @param [Hash] context - Any additional context you'd like to include in the log
def whoop(
label = nil,
Expand All @@ -52,14 +55,35 @@ def whoop(
format: :pretty,
caller_depth: 0,
explain: false,
tags: [],
context: nil
)
message = block_given? ? yield : label

if Whoop.logger.is_a?(SemanticLogger::Logger)
context ||= {}

if tags.length > 0
Whoop.logger.tagged(*tags) do
Whoop.logger.send(Whoop.level.to_sym, message, **context)
end
else
Whoop.logger.send(Whoop.level.to_sym, message, **context)
end

return
end

if tags.length > 0
context ||= {}
context[:tags] = tags
end

logger_method = detect_logger_method
color_method = detect_color_method(color)
formatter_method = detect_formatter_method(format, colorize: color.present?, explain: explain)

line = pattern * count
caller_path = clean_caller_path(caller[caller_depth])
line = pattern * count
caller_path_line = [color_method.call(INDENT), "source:".colorize(:light_black).underline, caller_path].join(" ")
timestamp_line = [color_method.call(INDENT), "timestamp:".colorize(:light_black).underline, Time.now].join(" ")

Expand All @@ -72,38 +96,23 @@ def whoop(
[]
end

if block_given?
result = yield
top_line =
if label.present? && label.is_a?(String)
wrapped_line(label.to_s, pattern: pattern, count: count)
else
pattern * count
end
result.tap do
logger_method.call color_method.call "\n\n#{TOP_LINE_CHAR}#{top_line}"
logger_method.call timestamp_line
logger_method.call caller_path_line
context_lines.each { |l| logger_method.call l }
logger_method.call ""
logger_method.call formatter_method.call(result)
logger_method.call ""
display_invalid_format_message(format, color_method, logger_method)
logger_method.call color_method.call "#{BOTTOM_LINE_CHAR}#{line}\n\n"
end
else
tap do
logger_method.call color_method.call "\n\n#{TOP_LINE_CHAR}#{line}"
logger_method.call timestamp_line
logger_method.call caller_path_line
context_lines.each { |l| logger_method.call l }
logger_method.call ""
logger_method.call formatter_method.call(label)
logger_method.call ""
display_invalid_format_message(format, color_method, logger_method)
logger_method.call color_method.call "#{BOTTOM_LINE_CHAR}#{line}\n\n"
top_line =
if label.present? && label.is_a?(String)
wrapped_line(label.to_s, pattern: pattern, count: count)
else
pattern * count
end
end

logger_method.call color_method.call top_line
logger_method.call color_method.call "\n\n#{TOP_LINE_CHAR}#{top_line}"
logger_method.call timestamp_line
logger_method.call caller_path_line
context_lines.each { |l| logger_method.call l }
logger_method.call ""
logger_method.call formatter_method.call(message)
logger_method.call ""
display_invalid_format_message(format, color_method, logger_method)
logger_method.call color_method.call "#{BOTTOM_LINE_CHAR}#{line}\n\n"
end

private
Expand Down Expand Up @@ -140,16 +149,20 @@ def detect_logger_method
end

# Return the format method to use
# @param [Symbol] format
# @param [Symbol] format - one of :json, :sql, :pretty, :semantic, :plain
# @param [Hash] context - the context provided
# @param [Boolean] explain - if format is sql, execute the explain on the query
# @return [Method] format method
def detect_formatter_method(format, colorize: false, explain: false)
def detect_formatter_method(format, context: {}, colorize: false, explain: false)
case format.to_sym
when :json
->(message) { Whoop::Formatters::JsonFormatter.format(message, colorize: colorize) }
when :sql
->(message) { Whoop::Formatters::SqlFormatter.format(message, colorize: colorize, explain: explain) }
when :pretty
->(message) { Whoop::Formatters::PrettyFormatter.format(message) }
when :semantic
->(message, context = {}) { Whoop::Formatters::PrettyFormatter.format(message, **context) }
else
->(message) { message }
end
Expand Down
65 changes: 61 additions & 4 deletions sig/whoop.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ module Whoop
#
# _@param_ `color` — - the color to use for the line (e.g. :red)
#
# _@param_ `format` — - the format to use for the message (one of :json, :sql, :plain, :pretty (default))
# _@param_ `format` — - the format to use for the message (one of :json, :sql, :plain, :semantic, :pretty (default))
#
# _@param_ `caller_depth` — - the depth of the caller to use for the source (default: 0)
#
# _@param_ `explain` — - whether to explain the SQL query (default: false)
#
# _@param_ `tags` — - Any tags you'd like to include in the log
#
# _@param_ `context` — - Any additional context you'd like to include in the log
def whoop: (
?String? label,
Expand All @@ -44,6 +46,7 @@ module Whoop
?format: Symbol,
?caller_depth: Integer,
?explain: bool,
?tags: ::Array[(String | Symbol)],
?context: ::Hash[untyped, untyped]?
) -> untyped

Expand All @@ -65,13 +68,21 @@ module Whoop
def detect_logger_method: () -> Method

# sord omit - no YARD type given for "colorize:", using untyped
# sord omit - no YARD type given for "explain:", using untyped
# Return the format method to use
#
# _@param_ `format`
# _@param_ `format` — - one of :json, :sql, :pretty, :semantic, :plain
#
# _@param_ `context` — - the context provided
#
# _@param_ `explain` — - if format is sql, execute the explain on the query
#
# _@return_ — format method
def detect_formatter_method: (Symbol format, ?colorize: untyped, ?explain: untyped) -> Method
def detect_formatter_method: (
Symbol format,
?context: ::Hash[untyped, untyped],
?colorize: untyped,
?explain: bool
) -> Method

# sord omit - no YARD type given for "format", using untyped
# sord omit - no YARD type given for "color_method", using untyped
Expand All @@ -89,6 +100,52 @@ module Whoop
def wrapped_line: (String label, ?count: Integer, ?pattern: String) -> String
end

module Constants
class ICONS
CHECKMARK: untyped
TIMES: untyped
PLUS: untyped
MINUS: untyped
end

class COLORS
BLACK: untyped
RED: untyped
GREEN: untyped
YELLOW: untyped
BLUE: untyped
MAGENTA: untyped
CYAN: untyped
WHITE: untyped
DEFAULT: untyped
LIGHT_BLACK: untyped
LIGHT_RED: untyped
LIGHT_GREEN: untyped
LIGHT_YELLOW: untyped
LIGHT_BLUE: untyped
LIGHT_MAGENTA: untyped
LIGHT_CYAN: untyped
LIGHT_WHITE: untyped
end

class MODES
DEFAULT: untyped
BOLD: untyped
DIM: untyped
ITALIC: untyped
UNDERLINE: untyped
BLINK: untyped
BLINK_SLOW: untyped
BLINK_FAST: untyped
INVERT: untyped
HIDE: untyped
STRIKE: untyped
DOUBLE_UNDERLINE: untyped
REVEAL: untyped
OVERLINED: untyped
end
end

module Formatters
module SqlFormatter
PATTERNS_TO_PRESERVE: untyped
Expand Down
46 changes: 46 additions & 0 deletions spec/whoop_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,39 @@
end
end

context "when the format is :semantic" do
it "writes to the logger" do
@original_stdout = $stdout
$stdout = StringIO.new

SemanticLogger.default_level = :debug
SemanticLogger.add_appender(io: $stdout, level: :debug)

Whoop.setup do |config|
config.logger = SemanticLogger[Whoop]
config.level = :debug
end

context = {current_user: "Eric", ip_address: "127.0.0.1"}
tags = %w[tag1 tag2]

whoop("Hello Semantic Logger", context: context, tags: tags)
logged_message = $stdout.string

$stdout = @original_stdout

puts "\n------ Semantic Output ------"
puts logged_message.to_s
puts "-----------------------------\n"

# Example output:
# 2024-02-01 10:38:55.044748 D [81357:6060] [tag1] [tag2] Whoop -- Hello Semantic Logger -- {:current_user=>"Eric", :ip_address=>"127.0.0.1"}

expect(logged_message).to include(%([tag1] [tag2] Whoop -- Hello Semantic Logger -- {:current_user=>"Eric", :ip_address=>"127.0.0.1"}))
expect(logged_message).not_to include("Unsupported format used.")
end
end

context "when context is passed" do
it "writes to the logger" do
io = setup_whoop
Expand All @@ -105,6 +138,19 @@
end
end

context "when tags are passed" do
it "writes to the logger" do
io = setup_whoop
tags = %w[tag1 tag2]
whoop("With Tags", tags: tags) { "Should include tags" }
logged_message = io.string

puts logged_message

expect(logged_message.uncolorize).to include "tags: tag1 tag2"
end
end

context "when invalid context is passed" do
it "writes to the logger" do
io = setup_whoop
Expand Down
5 changes: 3 additions & 2 deletions whoop.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ Gem::Specification.new do |spec|

spec.add_dependency "activerecord", ">= 6.1.4"
spec.add_dependency "activesupport", ">= 6.1.4"
spec.add_dependency "amazing_print"
spec.add_dependency "anbt-sql-formatter"
spec.add_dependency "colorize"
spec.add_dependency "rouge"
spec.add_dependency "amazing_print"
spec.add_dependency "semantic_logger"

spec.add_development_dependency "magic_frozen_string_literal"
spec.add_development_dependency "pry-byebug"
spec.add_development_dependency "pry"
spec.add_development_dependency "rspec"
spec.add_development_dependency "rake"
spec.add_development_dependency "standard"
Expand Down

0 comments on commit e17b191

Please sign in to comment.