1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 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 77 78 79 80 81 82 83 84 85 86 87 88
|
# frozen_string_literal: true
module Sentry
# @api private
class Envelope::Item
STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD = 500
MAX_SERIALIZED_PAYLOAD_SIZE = 1024 * 1000
SIZE_LIMITS = Hash.new(MAX_SERIALIZED_PAYLOAD_SIZE).update(
"profile" => 1024 * 1000 * 50
)
attr_reader :size_limit, :headers, :payload, :type, :data_category
# rate limits and client reports use the data_category rather than envelope item type
def self.data_category(type)
case type
when "session", "attachment", "transaction", "profile", "span", "log" then type
when "sessions" then "session"
when "check_in" then "monitor"
when "statsd", "metric_meta" then "metric_bucket"
when "event" then "error"
when "client_report" then "internal"
else "default"
end
end
def initialize(headers, payload)
@headers = headers
@payload = payload
@type = headers[:type] || "event"
@data_category = self.class.data_category(type)
@size_limit = SIZE_LIMITS[type]
end
def to_s
[JSON.generate(@headers), @payload.is_a?(String) ? @payload : JSON.generate(@payload)].join("\n")
end
def serialize
result = to_s
if result.bytesize > size_limit
remove_breadcrumbs!
result = to_s
end
if result.bytesize > size_limit
reduce_stacktrace!
result = to_s
end
[result, result.bytesize > size_limit]
end
def size_breakdown
payload.map do |key, value|
"#{key}: #{JSON.generate(value).bytesize}"
end.join(", ")
end
private
def remove_breadcrumbs!
if payload.key?(:breadcrumbs)
payload.delete(:breadcrumbs)
elsif payload.key?("breadcrumbs")
payload.delete("breadcrumbs")
end
end
def reduce_stacktrace!
if exceptions = payload.dig(:exception, :values) || payload.dig("exception", "values")
exceptions.each do |exception|
# in most cases there is only one exception (2 or 3 when have multiple causes), so we won't loop through this double condition much
traces = exception.dig(:stacktrace, :frames) || exception.dig("stacktrace", "frames")
if traces && traces.size > STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD
size_on_both_ends = STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD / 2
traces.replace(
traces[0..(size_on_both_ends - 1)] + traces[-size_on_both_ends..-1],
)
end
end
end
end
end
end
|