Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
### Internal

- Unify Logs and Metrics implementations ([#2826](https://github.com/getsentry/sentry-ruby/pull/2826))
- Unify LogEventBuffer and MetricEventBuffer logic ([#2830](https://github.com/getsentry/sentry-ruby/pull/2830))

## 6.2.0

Expand Down
102 changes: 2 additions & 100 deletions sentry-ruby/lib/sentry/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def capture_event(event, scope, hint = {})
# @return [LogEvent]
def buffer_log_event(event, scope)
return unless event.is_a?(LogEvent)
@log_event_buffer.add_event(scope.apply_to_telemetry(event))
@log_event_buffer.add_item(scope.apply_to_telemetry(event))
event
end

Expand All @@ -117,7 +117,7 @@ def buffer_log_event(event, scope)
def buffer_metric_event(event, scope)
return unless event.is_a?(MetricEvent)
event = scope.apply_to_telemetry(event)
@metric_event_buffer.add_metric(event)
@metric_event_buffer.add_item(event)
event
end

Expand Down Expand Up @@ -295,104 +295,6 @@ def send_event(event, hint = nil)
raise
end

# Send an envelope with batched logs
# @param log_events [Array<LogEvent>] the log events to be sent
# @api private
# @return [void]
def send_logs(log_events)
envelope = Envelope.new(
event_id: Sentry::Utils.uuid,
sent_at: Sentry.utc_now.iso8601,
dsn: configuration.dsn,
sdk: Sentry.sdk_meta
)

discarded_count = 0
envelope_items = []

if configuration.before_send_log
log_events.each do |log_event|
processed_log_event = configuration.before_send_log.call(log_event)

if processed_log_event
envelope_items << processed_log_event.to_h
else
discarded_count += 1
end
end

envelope_items
else
envelope_items = log_events.map(&:to_h)
end

envelope.add_item(
{
type: "log",
item_count: envelope_items.size,
content_type: "application/vnd.sentry.items.log+json"
},
{ items: envelope_items }
)

send_envelope(envelope)

unless discarded_count.zero?
transport.record_lost_event(:before_send, "log_item", num: discarded_count)
end
end

# Send an envelope with batched metrics
# @param metrics [Array<MetricEvent>] the metrics to send
# @api private
# @return [void]
def send_metrics(metrics)
return if metrics.nil? || metrics.empty?

envelope = Envelope.new(
event_id: Sentry::Utils.uuid,
sent_at: Sentry.utc_now.iso8601,
dsn: configuration.dsn,
sdk: Sentry.sdk_meta
)

discarded_count = 0
envelope_items = []

if configuration.before_send_metric
metrics.each do |metric|
processed_metric = configuration.before_send_metric.call(metric)

if processed_metric
envelope_items << processed_metric.to_h
else
discarded_count += 1
end
end

envelope_items
else
envelope_items = metrics.map(&:to_h)
end

return if envelope_items.empty?

envelope.add_item(
{
type: "trace_metric",
item_count: envelope_items.size,
content_type: "application/vnd.sentry.items.trace-metric+json"
},
{ items: envelope_items }
)

send_envelope(envelope)

unless discarded_count.zero?
transport.record_lost_event(:before_send, "metric", num: discarded_count)
end
end

# Send an envelope directly to Sentry.
# @param envelope [Envelope] the envelope to be sent.
# @return [void]
Expand Down
3 changes: 2 additions & 1 deletion sentry-ruby/lib/sentry/envelope/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class Envelope::Item
# 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", "trace_metric" then type
when "session", "attachment", "transaction", "profile", "span", "trace_metric" then type
when "log" then "log_item"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log data_category was wrong here

when "sessions" then "session"
when "check_in" then "monitor"
when "event" then "error"
Expand Down
78 changes: 11 additions & 67 deletions sentry-ruby/lib/sentry/log_event_buffer.rb
Original file line number Diff line number Diff line change
@@ -1,82 +1,26 @@
# frozen_string_literal: true

require "sentry/threaded_periodic_worker"
require "sentry/telemetry_event_buffer"

module Sentry
# LogEventBuffer buffers log events and sends them to Sentry in a single envelope.
#
# This is used internally by the `Sentry::Client`.
#
# @!visibility private
class LogEventBuffer < ThreadedPeriodicWorker
FLUSH_INTERVAL = 5 # seconds
class LogEventBuffer < TelemetryEventBuffer
DEFAULT_MAX_EVENTS = 100

# @!visibility private
attr_reader :pending_events

def initialize(configuration, client)
super(configuration.sdk_logger, FLUSH_INTERVAL)

@client = client
@pending_events = []
@max_events = configuration.max_log_events || DEFAULT_MAX_EVENTS
@mutex = Mutex.new

log_debug("[Logging] Initialized buffer with max_events=#{@max_events}, flush_interval=#{FLUSH_INTERVAL}s")
end

def start
ensure_thread
self
end

def flush
@mutex.synchronize do
return if empty?

log_debug("[LogEventBuffer] flushing #{size} log events")

send_events
end

log_debug("[LogEventBuffer] flushed #{size} log events")

self
end
alias_method :run, :flush

def add_event(event)
raise ArgumentError, "expected a LogEvent, got #{event.class}" unless event.is_a?(LogEvent)

@mutex.synchronize do
@pending_events << event
send_events if size >= @max_events
end

self
end

def empty?
@pending_events.empty?
end

def size
@pending_events.size
end

def clear!
@pending_events.clear
end

private

def send_events
@client.send_logs(@pending_events)
rescue => e
log_debug("[LogEventBuffer] Failed to send logs: #{e.message}")
ensure
clear!
super(
configuration,
client,
event_class: LogEvent,
max_items: configuration.max_log_events || DEFAULT_MAX_EVENTS,
envelope_type: "log",
envelope_content_type: "application/vnd.sentry.items.log+json",
before_send: configuration.before_send_log
)
end
end
end
74 changes: 11 additions & 63 deletions sentry-ruby/lib/sentry/metric_event_buffer.rb
Original file line number Diff line number Diff line change
@@ -1,78 +1,26 @@
# frozen_string_literal: true

require "sentry/threaded_periodic_worker"
require "sentry/telemetry_event_buffer"

module Sentry
# MetricEventBuffer buffers metric events and sends them to Sentry in a single envelope.
#
# This is used internally by the `Sentry::Client`.
#
# @!visibility private
class MetricEventBuffer < ThreadedPeriodicWorker
FLUSH_INTERVAL = 5 # seconds
class MetricEventBuffer < TelemetryEventBuffer
DEFAULT_MAX_METRICS = 100

# @!visibility private
attr_reader :pending_metrics

def initialize(configuration, client)
super(configuration.sdk_logger, FLUSH_INTERVAL)

@client = client
@pending_metrics = []
@max_metrics = configuration.max_metric_events || DEFAULT_MAX_METRICS
@mutex = Mutex.new

log_debug("[Metrics] Initialized buffer with max_metrics=#{@max_metrics}, flush_interval=#{FLUSH_INTERVAL}s")
end

def start
ensure_thread
self
end

def flush
@mutex.synchronize do
return if empty?

log_debug("[MetricEventBuffer] flushing #{size} metrics")

send_metrics
end
end
alias_method :run, :flush

def add_metric(metric)
raise ArgumentError, "expected a MetricEvent, got #{metric.class}" unless metric.is_a?(MetricEvent)

@mutex.synchronize do
@pending_metrics << metric
send_metrics if size >= @max_metrics
end

self
end

def empty?
@pending_metrics.empty?
end

def size
@pending_metrics.size
end

def clear!
@pending_metrics.clear
end

private

def send_metrics
@client.send_metrics(@pending_metrics)
rescue => e
log_debug("[MetricEventBuffer] Failed to send metrics: #{e.message}")
ensure
clear!
super(
configuration,
client,
event_class: MetricEvent,
max_items: configuration.max_metric_events || DEFAULT_MAX_METRICS,
envelope_type: "trace_metric",
envelope_content_type: "application/vnd.sentry.items.trace-metric+json",
before_send: configuration.before_send_metric
)
end
end
end
Loading
Loading