Class: SolidErrors::Frontend::Report

Inherits:
Object
  • Object
show all
Defined in:
lib/solid_errors/frontend/report.rb

Overview

One browser error, normalised into everything needed to report it.

Every field here arrives from the client, so nothing is passed through untouched: the capture site picks the reported source and severity (rather than the payload naming them), extra context is allowlisted, and the message is normalised and truncated.

Constant Summary collapse

CAPTURE_SITES =

Capture site => [reported source, severity, handled]. The source ends up in the fingerprint, so this both labels the report and keeps, say, a Turbo failure from grouping with an identically-worded uncaught exception.

{
  "window" => [ "javascript.window", :error, false ],
  "promise" => [ "javascript.promise", :error, false ],
  "stimulus" => [ "javascript.stimulus", :error, false ],
  "turbo" => [ "javascript.turbo", :warning, true ]
}.freeze
DEFAULT_CAPTURE_SITE =
[ "javascript", :error, false ].freeze
MAX_CONTEXT_VALUE_LENGTH =

Values are kept flat and short whatever SolidErrors::Frontend.allowed_context_keys permits: backends render context as a plain key/value list, and the payload is unauthenticated.

200

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, message:, stack:, capture_site:, context: nil) ⇒ Report

Returns a new instance of Report.



48
49
50
51
52
53
54
# File 'lib/solid_errors/frontend/report.rb', line 48

def initialize(name:, message:, stack:, capture_site:, context: nil)
  @name = name
  @message = message
  @stack = stack
  @source, @severity, @handled = CAPTURE_SITES.fetch(capture_site.to_s, DEFAULT_CAPTURE_SITE)
  @context = sanitize_context(context)
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



28
29
30
# File 'lib/solid_errors/frontend/report.rb', line 28

def context
  @context
end

#messageObject (readonly)

Returns the value of attribute message.



28
29
30
# File 'lib/solid_errors/frontend/report.rb', line 28

def message
  @message
end

#nameObject (readonly)

Returns the value of attribute name.



28
29
30
# File 'lib/solid_errors/frontend/report.rb', line 28

def name
  @name
end

#severityObject (readonly)

Returns the value of attribute severity.



28
29
30
# File 'lib/solid_errors/frontend/report.rb', line 28

def severity
  @severity
end

#sourceObject (readonly)

Returns the value of attribute source.



28
29
30
# File 'lib/solid_errors/frontend/report.rb', line 28

def source
  @source
end

#stackObject (readonly)

Returns the value of attribute stack.



28
29
30
# File 'lib/solid_errors/frontend/report.rb', line 28

def stack
  @stack
end

Class Method Details

.from(attributes) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/solid_errors/frontend/report.rb', line 30

def self.from(attributes)
  attributes = attributes.to_h { |key, value| [ key.to_s, value ] }

  # A blank message would be dropped (or worse, raise) by backends that
  # require one, so fall back to the error name before giving up.
  message = MessageNormalizer.call(attributes["message"])
  message = MessageNormalizer.call(attributes["name"]) if message.empty?
  return nil if message.empty?

  new(
    name: attributes["name"],
    message: message,
    stack: attributes["stack"],
    capture_site: attributes["source"],
    context: attributes["context"]
  )
end

Instance Method Details

#error_classObject



58
# File 'lib/solid_errors/frontend/report.rb', line 58

def error_class = SolidErrors::Frontend.error_class_for(name)

#framesObject



60
61
62
# File 'lib/solid_errors/frontend/report.rb', line 60

def frames
  @frames ||= StackParser.parse(stack)
end

#handled?Boolean

Returns:

  • (Boolean)


56
# File 'lib/solid_errors/frontend/report.rb', line 56

def handled? = @handled