Skip to content

Commit 3540041

Browse files
Fix how we detect the logging frame (#6)
* Fix how we detect the frame which initiated logging * 🐛 * ✅ * 💄 * 📦 * 🐛 Fix compatibility with Truffle Ruby * ⏪ * 🐛
1 parent 63a7be2 commit 3540041

File tree

4 files changed

+34
-22
lines changed

4 files changed

+34
-22
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1414
## [0.1.2] - 2021-04-22
1515

1616
- Fixed string encoding.
17+
18+
## [0.1.3] - 2021-06-11
19+
20+
- Fixed detection of the frame that calls the logger.

lib/logtail/log_entry.rb

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class LogEntry #:nodoc:
1212
BINARY_LIMIT_THRESHOLD = 1_000.freeze
1313
DT_PRECISION = 6.freeze
1414
MESSAGE_MAX_BYTES = 8192.freeze
15-
LOGTAIL_GEM_REGEX = /\/logtail(?:-ruby|-rails|-rack)?(?:-\d+(?:\.\d+)*)?\/lib$/.freeze
15+
LOGGER_FILE = '/logtail/logger.rb'.freeze
1616

1717
attr_reader :context_snapshot, :event, :level, :message, :progname, :tags, :time
1818

@@ -39,6 +39,7 @@ def initialize(level, time, progname, message, context_snapshot, event, options
3939
@tags = options[:tags]
4040
@context_snapshot = context_snapshot
4141
@event = event
42+
@runtime_context = current_runtime_context || {}
4243
end
4344

4445
# Builds a hash representation containing simple objects, suitable for serialization (JSON).
@@ -64,7 +65,7 @@ def to_hash(options = {})
6465

6566
hash[:context] ||= {}
6667
hash[:context][:runtime] ||= {}
67-
hash[:context][:runtime].merge!(current_runtime_context || {})
68+
hash[:context][:runtime].merge!(@runtime_context)
6869

6970
if options[:only]
7071
hash.select do |key, _value|
@@ -114,32 +115,40 @@ def encode_string(string)
114115
end
115116

116117
def current_runtime_context
117-
index = caller_locations.rindex { |x| logtail_frame?(x) }
118-
frame = caller_locations[index + 1] unless index.nil?
119-
return convert_to_runtime_context(frame) unless frame.nil?
118+
last_logger_invocation_index = caller_locations.rindex { |frame| logtail_logger_frame?(frame) }
119+
return {} if last_logger_invocation_index.nil?
120+
121+
calling_frame_index = last_logger_invocation_index + 1
122+
frame = caller_locations[calling_frame_index]
123+
124+
return convert_to_runtime_context(frame)
120125
end
121126

122127
def convert_to_runtime_context(frame)
123128
{
124-
file: relative_to_main_module(frame.absolute_path),
129+
file: path_relative_to_app_root(frame),
125130
line: frame.lineno,
126131
frame_label: frame.label,
127132
}
128133
end
129134

130-
def logtail_frame?(frame)
131-
return false if frame.absolute_path.nil? || logtail_gem_paths.empty?
132-
logtail_gem_paths.any? { |path| frame.absolute_path.start_with?(path) }
135+
def logtail_logger_frame?(frame)
136+
!frame.absolute_path.nil? && frame.absolute_path.end_with?(LOGGER_FILE)
133137
end
134138

135-
def logtail_gem_paths
136-
@logtail_gem_paths ||= $LOAD_PATH.select { |path| path.match(LOGTAIL_GEM_REGEX) }
139+
def path_relative_to_app_root(frame)
140+
Pathname.new(frame.absolute_path).relative_path_from(root_path).to_s
137141
end
138142

139-
def relative_to_main_module(path)
140-
base_file = caller_locations.last.absolute_path
141-
base_path = Pathname.new(File.dirname(base_file || '/'))
142-
Pathname.new(path).relative_path_from(base_path).to_s
143+
def root_path
144+
if Object.const_defined?('Rails')
145+
Rails.root.to_s
146+
elsif Object.const_defined?('Rack::Directory')
147+
Rack::Directory.new('').root
148+
else
149+
base_file = caller_locations.last.absolute_path
150+
Pathname.new(File.dirname(base_file || '/'))
151+
end
143152
end
144153
end
145154
end

lib/logtail/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module Logtail
2-
VERSION = "0.1.2"
2+
VERSION = "0.1.3"
33
end

spec/logtail/log_entry_spec.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require "spec_helper"
22

33
describe Logtail::LogEntry do
4-
let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
4+
let(:time) { Time.utc(2021, 06, 11, 12, 0, 0) }
55

66
describe "#to_msgpack" do
77
it "should encode properly with an event and context" do
@@ -16,20 +16,19 @@
1616
context = {custom: {a: "b"}}
1717
log_entry = described_class.new("INFO", time, nil, "log message", context, event)
1818
msgpack = log_entry.to_msgpack
19-
expect(msgpack).to start_with("\x85\xA5level\xA4INFO\xA2dt\xBB2016-09-01T12:00:00.000000Z".force_encoding("ASCII-8BIT"))
19+
expect(msgpack).to start_with("\x85\xA5level\xA4INFO\xA2dt\xBB2021-06-11T12:00:00.000000Z".force_encoding("ASCII-8BIT"))
2020
end
2121
end
2222

2323
describe "#to_hash" do
2424
it "should include runtime context information" do
25-
$:.unshift(File.expand_path(__dir__ + '/../../lib'))
25+
log_entry = Logtail::Logger::PassThroughFormatter.new.call("INFO", time, "", "log message")
2626

27-
log_entry = described_class.new("INFO", time, nil, "log message", {}, {})
2827
hash = log_entry.to_hash
2928
expect(hash[:context]).to_not be_nil
3029
expect(hash[:context][:runtime]).to_not be_nil
31-
expect(hash[:context][:runtime][:file]).to_not be_nil
32-
expect(hash[:context][:runtime][:line]).to_not be_nil
30+
expect(hash[:context][:runtime][:file]).to end_with('/spec/logtail/log_entry_spec.rb')
31+
expect(hash[:context][:runtime][:line]).to be(25)
3332
expect(hash[:context][:runtime][:frame_label]).to_not be_nil
3433
end
3534
end

0 commit comments

Comments
 (0)