@@ -149,7 +149,7 @@ defmodule Sentry.LogEvent do
149149 # Positional parameters: %s placeholders
150150 defp interpolate_template ( message , parameters ) when is_list ( parameters ) do
151151 # Convert parameters to proper types for storage
152- processed_params = Enum . map ( parameters , & stringify_parameter / 1 )
152+ processed_params = Enum . map ( parameters , & sanitize_attribute_value / 1 )
153153
154154 # Interpolate %s placeholders
155155 body = interpolate_positional_placeholders ( message , parameters )
@@ -166,7 +166,7 @@ defmodule Sentry.LogEvent do
166166 processed_params =
167167 Enum . map ( keys , fn key ->
168168 value = Map . get ( parameters , key ) || Map . get ( parameters , to_string ( key ) )
169- stringify_parameter ( value )
169+ sanitize_attribute_value ( value )
170170 end )
171171
172172 # Interpolate %{key} placeholders
@@ -209,14 +209,18 @@ defmodule Sentry.LogEvent do
209209 defp to_string_for_interpolation ( value ) when is_float ( value ) , do: Float . to_string ( value )
210210 defp to_string_for_interpolation ( value ) , do: inspect ( value )
211211
212- # Convert parameter values to a form suitable for Sentry attributes
212+ # Converts values to JSON-safe attribute types.
213+ # Primitives (string, boolean, integer, float) pass through unchanged.
214+ # Atoms are converted to strings. All other types (structs, maps, lists,
215+ # tuples, PIDs, etc.) are converted to their inspect() representation.
216+ # Used for both message template parameters and user-provided attributes.
213217 # Note: is_boolean must come before is_atom since true/false are atoms
214- defp stringify_parameter ( value ) when is_binary ( value ) , do: value
215- defp stringify_parameter ( value ) when is_boolean ( value ) , do: value
216- defp stringify_parameter ( value ) when is_atom ( value ) , do: Atom . to_string ( value )
217- defp stringify_parameter ( value ) when is_integer ( value ) , do: value
218- defp stringify_parameter ( value ) when is_float ( value ) , do: value
219- defp stringify_parameter ( value ) , do: inspect ( value )
218+ defp sanitize_attribute_value ( value ) when is_binary ( value ) , do: value
219+ defp sanitize_attribute_value ( value ) when is_boolean ( value ) , do: value
220+ defp sanitize_attribute_value ( value ) when is_atom ( value ) , do: Atom . to_string ( value )
221+ defp sanitize_attribute_value ( value ) when is_integer ( value ) , do: value
222+ defp sanitize_attribute_value ( value ) when is_float ( value ) , do: value
223+ defp sanitize_attribute_value ( value ) , do: inspect ( value )
220224
221225 # Extract message body and optionally template/parameters
222226 # If user_params provided via metadata, use those for interpolation
@@ -248,7 +252,7 @@ defmodule Sentry.LogEvent do
248252 when is_list ( format ) and is_list ( args ) do
249253 body = format |> :io_lib . format ( args ) |> IO . chardata_to_string ( )
250254 template = IO . chardata_to_string ( format )
251- processed_params = Enum . map ( args , & stringify_parameter / 1 )
255+ processed_params = Enum . map ( args , & sanitize_attribute_value / 1 )
252256 { body , template , processed_params }
253257 end
254258
@@ -270,10 +274,11 @@ defmodule Sentry.LogEvent do
270274 defp extract_trace_context ( _log_event ) , do: { nil , nil }
271275
272276 defp build_attributes ( % __MODULE__ { } = log_event ) do
273- # Start with user-provided attributes
277+ # Start with user-provided attributes, converting non-primitive values to strings
274278 formatted_attrs =
275279 Enum . into ( log_event . attributes , % { } , fn { key , value } ->
276- { to_string ( key ) , % { value: value , type: attribute_type ( value ) } }
280+ safe_value = sanitize_attribute_value ( value )
281+ { to_string ( key ) , % { value: safe_value , type: attribute_type ( safe_value ) } }
277282 end )
278283
279284 # Add Sentry-specific attributes
0 commit comments