Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the ability to send stash for resources #481

Merged
merged 3 commits into from
May 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@ Airbrake Ruby Changelog

### master

* Added `Airbrake::Query#stash`, `Airbrake::Request#stash`,
`Airbrake::PerformanceBreakdown#stash` that allows storing arbitrary
information in these structures
([#481](https://github.com/airbrake/airbrake-ruby/pull/481))
* Added the ability to attach objects to stash to `Airbrake.notify_query`,
`Airbrake.notify_request`, `Airbrake.notify_performance_breakdown`
([#481](https://github.com/airbrake/airbrake-ruby/pull/481))

Example:
```ruby
query_info = { query: '...', ...}
stash = { request_id: 123 }
Airbrake.notify_query(query_info, stash)
```

This stash can be accessed from performance filters.

### [v4.3.0][v4.3.0] (April 30, 2019)

* Added `Airbrake::TimedTrace` for measuring performance of arbitrary code
Expand Down
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,24 @@ Airbrake.notify_request(
)
```


Optionally, you can attach information to the stash (`request_id` in this
example).

```ruby
Airbrake.notify_request(
{
# normal params
},
request_id: 123
)
```

This stash can be accessed from performance filters as
`resource.stash[:request_id]`.

##### Return value

When [`config.performance_stats = false`](#performance_stats), it always returns
a rejected promise.

Expand All @@ -752,6 +770,23 @@ Airbrake.notify_query(
)
```

Optionally, you can attach information to the stash (`request_id` in this
example).

```ruby
Airbrake.notify_query(
{
# normal params
},
request_id: 123
)
```

This stash can be accessed from performance filters as
`resource.stash[:request_id]`.

##### Return value

When [`config.performance_stats = false`](#performance_stats), it always returns
a rejected promise.

Expand All @@ -774,6 +809,29 @@ Airbrake.notify_performance_breakdown(
)
```

Optionally, you can attach information to the stash (`request_id` in this
example).

```ruby
Airbrake.notify_performance_breakdown(
{
# normal params
},
request_id: 123
)
```

This stash can be accessed from performance filters as
`resource.stash[:request_id]`.

##### Return value

When [`config.performance_stats = false`](#performance_stats), it always returns
a rejected promise.

When [`config.performance_stats = true`](#performance_stats), then it aggregates
statistics and sends as a batch every 15 seconds.

#### Airbrake.add_performance_filter

Adds a performance filter that filters performance data. Works exactly like
Expand Down
25 changes: 19 additions & 6 deletions lib/airbrake-ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

require 'airbrake-ruby/version'
require 'airbrake-ruby/loggable'
require 'airbrake-ruby/stashable'
require 'airbrake-ruby/config'
require 'airbrake-ruby/config/validator'
require 'airbrake-ruby/promise'
Expand Down Expand Up @@ -346,11 +347,15 @@ def merge_context(context)
# (optional)
# @option request_info [Date] :start_time When the request started
# @option request_info [Time] :end_time When the request ended (optional)
# @param [Hash] stash What needs to be appeneded to the stash, so it's
# available in filters
# @return [void]
# @since v3.0.0
# @see Airbrake::PerformanceNotifier#notify
def notify_request(request_info)
performance_notifier.notify(Request.new(request_info))
def notify_request(request_info, stash = {})
request = Request.new(request_info)
request.stash.merge!(stash)
performance_notifier.notify(request)
end

# Increments SQL statistics of a certain +query+ that was invoked on
Expand All @@ -377,11 +382,15 @@ def notify_request(request_info)
# @option request_info [String] :query The query that was executed
# @option request_info [Date] :start_time When the query started executing
# @option request_info [Time] :end_time When the query finished (optional)
# @param [Hash] stash What needs to be appeneded to the stash, so it's
# available in filters
# @return [void]
# @since v3.2.0
# @see Airbrake::PerformanceNotifier#notify
def notify_query(query_info)
performance_notifier.notify(Query.new(query_info))
def notify_query(query_info, stash = {})
query = Query.new(query_info)
query.stash.merge!(stash)
performance_notifier.notify(query)
end

# Increments performance breakdown statistics of a certain route.
Expand All @@ -402,10 +411,14 @@ def notify_query(query_info)
# @option breakdown_info [String] :response_type
# @option breakdown_info [Array<Hash{Symbol=>Float}>] :groups
# @option breakdown_info [Date] :start_time
# @param [Hash] stash What needs to be appeneded to the stash, so it's
# available in filters
# @return [void]
# @since v4.2.0
def notify_performance_breakdown(breakdown_info)
performance_notifier.notify(PerformanceBreakdown.new(breakdown_info))
def notify_performance_breakdown(breakdown_info, stash = {})
performance_breakdown = PerformanceBreakdown.new(breakdown_info)
performance_breakdown.stash.merge!(stash)
performance_notifier.notify(performance_breakdown)
end

# Runs a callback before {.notify_request} or {.notify_query} kicks in. This
Expand Down
9 changes: 3 additions & 6 deletions lib/airbrake-ruby/notice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ class Notice

include Ignorable
include Loggable

# @since v1.7.0
# @return [Hash{Symbol=>Object}] the hash with arbitrary objects to be used
# in filters
attr_reader :stash
include Stashable

# @api private
def initialize(exception, params = {})
Expand All @@ -69,8 +65,9 @@ def initialize(exception, params = {})
session: {},
params: params
}
@stash = { exception: exception }
@truncator = Airbrake::Truncator.new(PAYLOAD_MAX_SIZE)

stash[:exception] = exception
end

# Converts the notice to JSON. Calls +to_json+ on each object inside
Expand Down
1 change: 1 addition & 0 deletions lib/airbrake-ruby/performance_breakdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module Airbrake
) do
include HashKeyable
include Ignorable
include Stashable

def initialize(
method:,
Expand Down
1 change: 1 addition & 0 deletions lib/airbrake-ruby/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module Airbrake
) do
include HashKeyable
include Ignorable
include Stashable

def initialize(
method:,
Expand Down
1 change: 1 addition & 0 deletions lib/airbrake-ruby/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Airbrake
Request = Struct.new(:method, :route, :status_code, :start_time, :end_time) do
include HashKeyable
include Ignorable
include Stashable

def initialize(
method:,
Expand Down
15 changes: 15 additions & 0 deletions lib/airbrake-ruby/stashable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Airbrake
# Stashable should be included in any class that wants the ability to stash
# arbitrary objects. It is mainly used by data objects that users can access
# through filters.
#
# @since v4.4.0
# @api private
module Stashable
# @return [Hash{Symbol=>Object}] the hash with arbitrary objects to be used
# in filters
def stash
@stash ||= {}
end
end
end
108 changes: 108 additions & 0 deletions spec/airbrake_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,114 @@
end
end

describe "#notify_request" do
context "when :stash key is not provided" do
it "doesn't add anything to the stash of the request" do
expect(described_class.performance_notifier).to receive(:notify) do |request|
expect(request.stash).to be_empty
end

described_class.notify_request(
method: 'GET',
route: '/',
status_code: 200,
start_time: Time.now
)
end
end

context "when :stash key is provided" do
it "adds the value as the stash of the request" do
expect(described_class.performance_notifier).to receive(:notify) do |request|
expect(request.stash).to eq(request_id: 1)
end

described_class.notify_request(
{
method: 'GET',
route: '/',
status_code: 200,
start_time: Time.now
},
request_id: 1
)
end
end
end

describe "#notify_query" do
context "when :stash key is not provided" do
it "doesn't add anything to the stash of the query" do
expect(described_class.performance_notifier).to receive(:notify) do |query|
expect(query.stash).to be_empty
end

described_class.notify_query(
method: 'GET',
route: '/',
query: '',
start_time: Time.now
)
end
end

context "when :stash key is provided" do
it "adds the value as the stash of the query" do
expect(described_class.performance_notifier).to receive(:notify) do |query|
expect(query.stash).to eq(request_id: 1)
end

described_class.notify_query(
{
method: 'GET',
route: '/',
query: '',
start_time: Time.now
},
request_id: 1
)
end
end
end

describe "#notify_performance_breakdown" do
context "when :stash key is not provided" do
it "doesn't add anything to the stash of the performance breakdown" do
expect(described_class.performance_notifier).to receive(:notify) do |query|
expect(query.stash).to be_empty
end

described_class.notify_query(
method: 'GET',
route: '/',
query: '',
start_time: Time.now
)
end
end

context "when :stash key is provided" do
it "adds the value as the stash of the performance breakdown" do
expect(
described_class.performance_notifier
).to receive(:notify) do |performance_breakdown|
expect(performance_breakdown.stash).to eq(request_id: 1)
end

described_class.notify_performance_breakdown(
{
method: 'GET',
route: '/',
response_type: :html,
groups: {},
start_time: Time.now
},
request_id: 1
)
end
end
end

describe ".performance_notifier" do
it "returns a performance notifier" do
expect(described_class.performance_notifier)
Expand Down
8 changes: 3 additions & 5 deletions spec/notice_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,8 @@ def to_json(*)
end

describe "#stash" do
it "returns a hash" do
obj = Object.new
notice.stash[:bingo_object] = obj
expect(notice.stash[:bingo_object]).to eql(obj)
end
subject { described_class.new(AirbrakeTestError.new) }

it { is_expected.to respond_to(:stash) }
end
end
12 changes: 12 additions & 0 deletions spec/performance_breakdown_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
RSpec.describe Airbrake::PerformanceBreakdown do
describe "#stash" do
subject do
described_class.new(
method: 'GET', route: '/', response_type: '', groups: {},
start_time: Time.now
)
end

it { is_expected.to respond_to(:stash) }
end
end
11 changes: 11 additions & 0 deletions spec/query_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RSpec.describe Airbrake::Query do
describe "#stash" do
subject do
described_class.new(
method: 'GET', route: '/', query: '', start_time: Time.now
)
end

it { is_expected.to respond_to(:stash) }
end
end
11 changes: 11 additions & 0 deletions spec/request_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RSpec.describe Airbrake::Request do
describe "#stash" do
subject do
described_class.new(
method: 'GET', route: '/', status_code: 200, start_time: Time.now
)
end

it { is_expected.to respond_to(:stash) }
end
end
Loading