Module: DebugBundle::BeforeSend
- Defined in:
- lib/debugbundle/before_send.rb
Constant Summary collapse
- REQUIRED_PAYLOAD_FIELDS =
{ 'backend_exception' => %w[name message stack handled request response runtime], 'request_event' => %w[method path query headers response_status duration_ms], 'log_event' => %w[level message attributes], 'frontend_breadcrumb' => %w[breadcrumb_type data], 'frontend_exception' => %w[name message stack], 'deploy_metadata' => %w[commit_sha version branch environment deployed_at], 'error_suppressed' => %w[fingerprint suppressed_count window_seconds first_seen last_seen], 'probe_event' => %w[label data activation_id probe_label_pattern] }.freeze
- ALLOWED_PAYLOAD_FIELDS =
{ 'backend_exception' => %w[name message stack handled request response runtime probe_data], 'request_event' => %w[ method path query headers body response_status duration_ms route_template response_headers response_body device ], 'log_event' => %w[level message attributes device], 'frontend_breadcrumb' => %w[breadcrumb_type route data device], 'frontend_exception' => %w[ name message stack route browser breadcrumbs device browser_event rejection_reason dom_context probe_data ], 'deploy_metadata' => %w[commit_sha version branch environment deployed_at], 'error_suppressed' => %w[fingerprint suppressed_count window_seconds first_seen last_seen device], 'probe_event' => %w[label data activation_id probe_label_pattern device] }.freeze
- ROOT_FIELDS =
%w[ schema_version event_id event_type project_token project_id sdk_name sdk_version service occurred_at correlation context payload ].freeze
- UUID_PATTERN =
/\A[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\z/i
Class Method Summary collapse
- .apply(event, hook) ⇒ Object
- .non_empty_strings?(payload, *fields) ⇒ Boolean
- .non_negative_integer?(value) ⇒ Boolean
- .non_negative_number?(value) ⇒ Boolean
- .nullable_uuid?(value) ⇒ Boolean
- .optional_hash?(payload, field) ⇒ Boolean
- .positive_integer?(value) ⇒ Boolean
- .timestamp?(value) ⇒ Boolean
- .valid?(event) ⇒ Boolean
- .valid_backend_exception?(payload) ⇒ Boolean
- .valid_deploy_metadata?(payload) ⇒ Boolean
- .valid_error_suppressed?(payload) ⇒ Boolean
- .valid_frontend_exception?(payload) ⇒ Boolean
- .valid_payload_shape?(event_type, payload) ⇒ Boolean
- .valid_probe_event?(payload) ⇒ Boolean
- .valid_request_event?(payload) ⇒ Boolean
Class Method Details
.apply(event, hook) ⇒ Object
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/debugbundle/before_send.rb', line 41 def apply(event, hook) return event unless hook result = hook.call(Marshal.load(Marshal.dump(event))) return nil if result.nil? valid?(result) ? result : event rescue StandardError event end |
.non_empty_strings?(payload, *fields) ⇒ Boolean
142 143 144 |
# File 'lib/debugbundle/before_send.rb', line 142 def non_empty_strings?(payload, *fields) fields.all? { |field| payload[field].is_a?(String) && !payload[field].strip.empty? } end |
.non_negative_integer?(value) ⇒ Boolean
154 155 156 |
# File 'lib/debugbundle/before_send.rb', line 154 def non_negative_integer?(value) value.is_a?(Integer) && value >= 0 end |
.non_negative_number?(value) ⇒ Boolean
150 151 152 |
# File 'lib/debugbundle/before_send.rb', line 150 def non_negative_number?(value) value.is_a?(Numeric) && value.finite? && value >= 0 end |
.nullable_uuid?(value) ⇒ Boolean
168 169 170 |
# File 'lib/debugbundle/before_send.rb', line 168 def nullable_uuid?(value) value.nil? || (value.is_a?(String) && UUID_PATTERN.match?(value)) end |
.optional_hash?(payload, field) ⇒ Boolean
146 147 148 |
# File 'lib/debugbundle/before_send.rb', line 146 def optional_hash?(payload, field) !payload.key?(field) || payload[field].is_a?(Hash) end |
.positive_integer?(value) ⇒ Boolean
158 159 160 |
# File 'lib/debugbundle/before_send.rb', line 158 def positive_integer?(value) value.is_a?(Integer) && value.positive? end |
.timestamp?(value) ⇒ Boolean
162 163 164 165 166 |
# File 'lib/debugbundle/before_send.rb', line 162 def (value) value.is_a?(String) && Time.iso8601(value) rescue ArgumentError false end |
.valid?(event) ⇒ Boolean
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/debugbundle/before_send.rb', line 52 def valid?(event) return false unless event.is_a?(Hash) return false unless (event.keys - ROOT_FIELDS).empty? return false unless %w[schema_version event_id event_type occurred_at sdk_name sdk_version].all? do |field| event[field].is_a?(String) && !event[field].empty? end return false unless UUID_PATTERN.match?(event['event_id']) Time.iso8601(event['occurred_at']) service = event['service'] payload = event['payload'] fields = REQUIRED_PAYLOAD_FIELDS[event['event_type']] allowed_fields = ALLOWED_PAYLOAD_FIELDS[event['event_type']] service.is_a?(Hash) && service['name'].is_a?(String) && !service['name'].empty? && service['environment'].is_a?(String) && !service['environment'].empty? && payload.is_a?(Hash) && fields && allowed_fields && (payload.keys - allowed_fields).empty? && fields.all? { |field| payload.key?(field) } && valid_payload_shape?(event['event_type'], payload) rescue ArgumentError false end |
.valid_backend_exception?(payload) ⇒ Boolean
101 102 103 104 105 106 |
# File 'lib/debugbundle/before_send.rb', line 101 def valid_backend_exception?(payload) non_empty_strings?(payload, 'name', 'message', 'stack') && [true, false].include?(payload['handled']) && %w[request response runtime].all? { |field| payload[field].is_a?(Hash) } && optional_hash?(payload, 'probe_data') end |
.valid_deploy_metadata?(payload) ⇒ Boolean
123 124 125 126 |
# File 'lib/debugbundle/before_send.rb', line 123 def (payload) non_empty_strings?(payload, 'commit_sha', 'version', 'branch', 'environment') && (payload['deployed_at']) end |
.valid_error_suppressed?(payload) ⇒ Boolean
128 129 130 131 132 133 134 |
# File 'lib/debugbundle/before_send.rb', line 128 def valid_error_suppressed?(payload) non_empty_strings?(payload, 'fingerprint') && non_negative_integer?(payload['suppressed_count']) && positive_integer?(payload['window_seconds']) && (payload['first_seen']) && (payload['last_seen']) end |
.valid_frontend_exception?(payload) ⇒ Boolean
117 118 119 120 121 |
# File 'lib/debugbundle/before_send.rb', line 117 def valid_frontend_exception?(payload) non_empty_strings?(payload, 'name', 'message', 'stack') && (!payload.key?('breadcrumbs') || payload['breadcrumbs'].is_a?(Array)) && optional_hash?(payload, 'probe_data') end |
.valid_payload_shape?(event_type, payload) ⇒ Boolean
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/debugbundle/before_send.rb', line 78 def valid_payload_shape?(event_type, payload) case event_type when 'backend_exception' valid_backend_exception?(payload) when 'request_event' valid_request_event?(payload) when 'log_event' non_empty_strings?(payload, 'level', 'message') && payload['attributes'].is_a?(Hash) when 'frontend_breadcrumb' non_empty_strings?(payload, 'breadcrumb_type') && payload['data'].is_a?(Hash) when 'frontend_exception' valid_frontend_exception?(payload) when 'deploy_metadata' (payload) when 'error_suppressed' valid_error_suppressed?(payload) when 'probe_event' valid_probe_event?(payload) else false end end |
.valid_probe_event?(payload) ⇒ Boolean
136 137 138 139 140 |
# File 'lib/debugbundle/before_send.rb', line 136 def valid_probe_event?(payload) non_empty_strings?(payload, 'label', 'probe_label_pattern') && payload['data'].is_a?(Hash) && nullable_uuid?(payload['activation_id']) end |
.valid_request_event?(payload) ⇒ Boolean
108 109 110 111 112 113 114 115 |
# File 'lib/debugbundle/before_send.rb', line 108 def valid_request_event?(payload) non_empty_strings?(payload, 'method', 'path') && payload['query'].is_a?(Hash) && payload['headers'].is_a?(Hash) && non_negative_number?(payload['response_status']) && non_negative_number?(payload['duration_ms']) && optional_hash?(payload, 'response_headers') end |