Skip to content

Commit 3f3e7c6

Browse files
committed
Fix adapter field for AMS logs
1 parent 3892b57 commit 3f3e7c6

File tree

6 files changed

+64
-7
lines changed

6 files changed

+64
-7
lines changed

lib/log_struct/integrations/active_model_serializers.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def self.setup(config)
3131
LogStruct.info(
3232
LogStruct::Log::ActiveModelSerializers.new(
3333
message: "ams.render",
34-
serializer: serializer&.to_s,
35-
adapter: adapter&.to_s,
34+
serializer: serializer&.name,
35+
adapter: adapter&.class&.name,
3636
resource_class: resource&.class&.name,
3737
duration_ms: duration_ms,
3838
timestamp: started

rails_test_app/templates/app/controllers/logging_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ def test_error_logging
145145
render json: {status: "ok", message: "Stack-safe error handling test completed"}
146146
end
147147

148+
# AMS serialization - triggers ActiveModelSerializers instrumentation
149+
def test_ams_serialization
150+
user = User.create!(name: "AMS Test User", email: "ams@example.com")
151+
render json: user, serializer: UserSerializer
152+
end
153+
148154
# Shrine file upload - triggers Shrine instrumentation logging
149155
def test_shrine_upload
150156
document = Document.create_with_shrine_file(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# typed: true
2+
# frozen_string_literal: true
3+
4+
class UserSerializer < ActiveModel::Serializer
5+
attributes :id, :name, :email
6+
end

rails_test_app/templates/config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
get "/logging/request", to: "logging#test_request"
1313
get "/logging/error_logging", to: "logging#test_error_logging"
1414
get "/logging/shrine_upload", to: "logging#test_shrine_upload"
15+
get "/logging/ams", to: "logging#test_ams_serialization"
1516

1617
# Healthcheck route
1718
get "/health", to: proc { [200, {}, ["OK"]] }

rails_test_app/templates/test/integration/ams_logging_test.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,40 @@ def test_ams_logs_do_not_pollute_with_default_format
7676
stdout_output,
7777
"AMS default log format should not appear in stdout")
7878
end
79+
80+
def test_ams_logs_adapter_class_name_not_serialized_output
81+
raise "AMS not available" unless defined?(::ActiveModelSerializers)
82+
83+
get "/logging/ams"
84+
85+
::SemanticLogger.flush
86+
@log_output.rewind
87+
output = @log_output.read.to_s
88+
89+
# Find the AMS log line
90+
ams_lines = output.lines.select { |line| line.include?('"msg":"ams.render"') }
91+
92+
assert_predicate ams_lines, :any?, "Expected to find ams.render log line, got:\n#{output}"
93+
94+
ams_line = ams_lines.first
95+
parsed = JSON.parse(ams_line)
96+
97+
# serializer should be the class name
98+
assert_equal "UserSerializer",
99+
parsed["serializer"],
100+
"Expected serializer to be 'UserSerializer', got: #{parsed["serializer"]}"
101+
102+
# adapter should be the adapter CLASS NAME, not serialized output
103+
adapter = parsed["adapter"]
104+
105+
assert_kind_of String, adapter, "adapter should be a string"
106+
assert_match(/^ActiveModelSerializers::Adapter::/,
107+
adapter,
108+
"adapter should be an AMS adapter class name like 'ActiveModelSerializers::Adapter::Attributes', got: #{adapter.inspect}")
109+
110+
# MUST NOT contain serialized user data (the bug we're fixing)
111+
refute_includes adapter,
112+
"AMS Test User",
113+
"adapter field MUST NOT contain serialized output"
114+
end
79115
end

test/log_struct/integrations/active_model_serializers_test.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,25 @@ class ActiveModelSerializersTest < ActiveSupport::TestCase
2222
test "subscribes to AMS notifications and emits structured log" do
2323
logs = []
2424
LogStruct.stub(:info, ->(log) { logs << log }) do
25-
serializer = Class.new do
26-
def self.to_s
25+
serializer_class = Class.new do
26+
def self.name
2727
"UserSerializer"
2828
end
2929
end
30+
31+
adapter_class = Class.new do
32+
def self.name
33+
"ActiveModelSerializers::Adapter::Json"
34+
end
35+
end
36+
adapter_instance = adapter_class.new
37+
3038
resource = OpenStruct.new(id: 1)
3139

3240
ActiveSupport::Notifications.instrument(
3341
"render.active_model_serializers",
34-
serializer: serializer,
35-
adapter: :json,
42+
serializer: serializer_class,
43+
adapter: adapter_instance,
3644
resource: resource
3745
) { sleep 0.001 }
3846
end
@@ -47,7 +55,7 @@ def self.to_s
4755
assert_equal "generate", json["evt"]
4856
assert_equal "ams.render", json["msg"]
4957
assert_equal "UserSerializer", json["serializer"]
50-
assert_equal "json", json["adapter"]
58+
assert_equal "ActiveModelSerializers::Adapter::Json", json["adapter"]
5159
assert_equal "OpenStruct", json["resource_class"]
5260
assert_in_delta 0.0, json["duration_ms"], 50.0
5361
end

0 commit comments

Comments
 (0)