action_reporter 3.0.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -10
- data/README.md +9 -8
- data/action_reporter.gemspec +6 -4
- data/bin/polyrun +108 -0
- data/lib/action_reporter/active_version_reporter.rb +4 -2
- data/lib/action_reporter/audited_reporter.rb +4 -2
- data/lib/action_reporter/base.rb +35 -2
- data/lib/action_reporter/current.rb +1 -0
- data/lib/action_reporter/honeybadger_reporter.rb +7 -4
- data/lib/action_reporter/paper_trail_reporter.rb +1 -1
- data/lib/action_reporter/plugin_discovery.rb +4 -4
- data/lib/action_reporter/scout_apm_reporter.rb +16 -5
- data/lib/action_reporter/sentry_reporter.rb +24 -5
- data/lib/action_reporter/version.rb +1 -1
- data/lib/action_reporter.rb +31 -1
- metadata +37 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 06c235516e05cc644caaa30e28f8b670fe711f20bc2f849d457ca17b4a7f8625
|
|
4
|
+
data.tar.gz: e82f1fac79ab8df40168305ede20edb759a57fce079f45bb4bd1e30f114eb352
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a62dcee03f8dc0b21806ed98ea68fc32f2444e4dedf4caace3ebb5ae7bdfdde1356f2ecc8b2b5aca586a1b161ee2b0283c6d00b142e1b91a39da538b6f91fd64
|
|
7
|
+
data.tar.gz: 58121c6340d635e26d950b3091d7727eb4a66c3eee48c0a5d19d665b60b935d06e0d50de46cc1664b47612ca685d6fa1af4d9dea02ffb8872979897c82251f74
|
data/CHANGELOG.md
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 3.2.1 (2026-07-13)
|
|
4
|
+
|
|
5
|
+
- Fix check-in identifier errors to raise `ActionReporter::Error` instead of stack overflow when an identifier cannot be stringified
|
|
6
|
+
|
|
7
|
+
## 3.2.0 (2026-07-13)
|
|
8
|
+
|
|
9
|
+
- Improve context propagation across reporters
|
|
10
|
+
- Merge updates into existing reporter context instead of replacing prior keys on each call
|
|
11
|
+
- Remove context keys when an update passes `nil` for that key
|
|
12
|
+
- Apply shared merge semantics to `ActiveVersionReporter`, `AuditedReporter`, `HoneybadgerReporter`, `ScoutApmReporter`, and `SentryReporter`
|
|
13
|
+
- Improve `SentryReporter` reset to clear the reporter context bucket from the Sentry scope
|
|
14
|
+
- Remove unused `gem_spec` parameter from reporter `class_accessor` declarations (version checks were dropped in 2.0.1)
|
|
15
|
+
- Improve plugin discovery warnings for reporter files and registrations that fail to load
|
|
16
|
+
|
|
17
|
+
## 3.1.0 (2026-03-27)
|
|
18
|
+
|
|
19
|
+
- Add `ActionReporter.user_id_resolver` for configuring how to resolve user IDs
|
|
20
|
+
- Improve ScoutApmReporter current user setter to use `id` instead of `user_global_id`
|
|
21
|
+
- Improve HoneybadgerReporter current user setter to use `user_id` instead of `user_global_id`
|
|
22
|
+
- Improve SentryReporter current user setter to use `id` instead of `user_global_id` and fix `transaction_id` setter to use `transaction_id` instead of `transactionId`
|
|
23
|
+
|
|
3
24
|
## 3.0.0 (2026-03-13)
|
|
4
25
|
|
|
5
26
|
- BREAKING: Remove backward-compat reporter loading
|
|
6
27
|
- Remove `AVAILABLE_REPORTERS` constant
|
|
7
28
|
- Stop eager requiring built-in reporters at boot
|
|
8
29
|
- Built-in reporters are now loaded lazily through `ActionReporter.available_reporters`
|
|
9
|
-
- Fix built-in reporter constant autoloading
|
|
10
|
-
- Add `autoload` mappings for built-in reporters (`RailsReporter`, `AuditedReporter`, `PaperTrailReporter`, `ActiveVersionReporter`, `SentryReporter`, `HoneybadgerReporter`, `ScoutApmReporter`)
|
|
11
|
-
- Fix `NameError: uninitialized constant ActionReporter::ActiveVersionReporter` when reporters are referenced directly from app initializers
|
|
12
|
-
- Fix custom reporter lazy loading regression
|
|
13
|
-
- `PluginDiscovery.load_registered_reporter` now attempts `require` before constant lookup
|
|
14
|
-
- Registered reporters can now be loaded from `require_path` when class is not preloaded
|
|
15
30
|
- Improve plugin discovery thread safety
|
|
16
31
|
- Synchronize `register` writes with discovery mutex
|
|
17
32
|
- Snapshot registered reporters under lock in `available_reporters` before iteration
|
|
@@ -25,10 +40,6 @@
|
|
|
25
40
|
- New `ActionReporter::Current.reset_storage_adapter!`
|
|
26
41
|
- Storage resolution order: explicit `storage_adapter` -> `ActiveSupport::IsolatedExecutionState` -> `Thread.current`
|
|
27
42
|
- Enables fiber-aware request storage customization in non-Rails environments
|
|
28
|
-
- Add regression coverage for lazy loading and storage behavior
|
|
29
|
-
- Add spec for loading registered reporter via `require_path` when class is not preloaded
|
|
30
|
-
- Add spec for transforming array-contained objects in deep context transform
|
|
31
|
-
- Add specs for `Current.storage_adapter` validation and precedence
|
|
32
43
|
|
|
33
44
|
## 2.0.2 (2026-03-13)
|
|
34
45
|
|
data/README.md
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
# action_reporter
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/rb/action_reporter) [](https://github.com/amkisko/action_reporter.rb/actions/workflows/test.yml) [](https://codecov.io/gh/amkisko/action_reporter.rb) [](https://sonarcloud.io/summary/new_code?id=amkisko_action_reporter.rb)
|
|
3
|
+
[](https://badge.fury.io/rb/action_reporter) [](https://github.com/amkisko/action_reporter.rb/actions/workflows/test.yml) [](https://codecov.io/gh/amkisko/action_reporter.rb) [](https://sonarcloud.io/summary/new_code?id=amkisko_action_reporter.rb)
|
|
4
4
|
|
|
5
5
|
Ruby wrapper for multiple reporting services.
|
|
6
6
|
|
|
7
7
|
Supported services: Rails logger, gem audited, gem PaperTrail, gem ActiveVersion, Sentry, Honeybadger, scoutapm.
|
|
8
8
|
|
|
9
|
-
Sponsored by [Kisko Labs](https://www.kiskolabs.com).
|
|
10
|
-
|
|
11
|
-
<a href="https://www.kiskolabs.com">
|
|
12
|
-
<img src="kisko.svg" width="200" alt="Sponsored by Kisko Labs" />
|
|
13
|
-
</a>
|
|
14
|
-
|
|
15
|
-
|
|
16
9
|
## Installation
|
|
17
10
|
|
|
18
11
|
Add to your Gemfile:
|
|
@@ -173,3 +166,11 @@ gem push action_reporter-*.gem
|
|
|
173
166
|
## License
|
|
174
167
|
|
|
175
168
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
169
|
+
|
|
170
|
+
## Sponsors
|
|
171
|
+
|
|
172
|
+
Sponsored by [Kisko Labs](https://www.kiskolabs.com).
|
|
173
|
+
|
|
174
|
+
<a href="https://www.kiskolabs.com">
|
|
175
|
+
<img src="kisko.svg" width="200" alt="Sponsored by Kisko Labs" />
|
|
176
|
+
</a>
|
data/action_reporter.gemspec
CHANGED
|
@@ -31,7 +31,9 @@ Gem::Specification.new do |gem|
|
|
|
31
31
|
gem.required_ruby_version = ">= 2.5.0"
|
|
32
32
|
gem.require_path = "lib"
|
|
33
33
|
|
|
34
|
-
gem.add_runtime_dependency "
|
|
34
|
+
gem.add_runtime_dependency "activesupport", ">= 6.0"
|
|
35
|
+
|
|
36
|
+
gem.add_development_dependency "rails", "> 5"
|
|
35
37
|
|
|
36
38
|
gem.add_development_dependency "audited", "~> 5"
|
|
37
39
|
gem.add_development_dependency "honeybadger", "~> 5"
|
|
@@ -40,13 +42,13 @@ Gem::Specification.new do |gem|
|
|
|
40
42
|
gem.add_development_dependency "paper_trail", "~> 15"
|
|
41
43
|
gem.add_development_dependency "active_version", "~> 1"
|
|
42
44
|
|
|
43
|
-
gem.add_development_dependency "bundler", "
|
|
45
|
+
gem.add_development_dependency "bundler", ">= 2"
|
|
44
46
|
gem.add_development_dependency "rspec", "~> 3"
|
|
47
|
+
gem.add_development_dependency "polyrun", ">= 2.2.0"
|
|
48
|
+
gem.add_development_dependency "prosopite", "~> 2.0"
|
|
45
49
|
gem.add_development_dependency "rspec_junit_formatter", "~> 0.6"
|
|
46
50
|
gem.add_development_dependency "webmock", "~> 3"
|
|
47
51
|
gem.add_development_dependency "pry", "~> 0.15"
|
|
48
|
-
gem.add_development_dependency "simplecov", "~> 0.22"
|
|
49
|
-
gem.add_development_dependency "simplecov-cobertura", "~> 3"
|
|
50
52
|
gem.add_development_dependency "standard", "~> 1.52"
|
|
51
53
|
gem.add_development_dependency "standard-custom", "~> 1.0"
|
|
52
54
|
gem.add_development_dependency "standard-performance", "~> 1.8"
|
data/bin/polyrun
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Delegates to `bundle exec polyrun` with repo config.
|
|
3
|
+
# - No args → same as `polyrun` with no subcommand (auto parallel RSpec from polyrun.yml / spec/**/*_spec.rb).
|
|
4
|
+
# - Path-like argv (spec files, globs, dirs) → polyrun implicit parallel (path-only argv).
|
|
5
|
+
# - Named subcommands (plan, config, parallel-rspec, ci-shard-rspec, …) → pass through.
|
|
6
|
+
# - Otherwise (RSpec flags first, e.g. --format) → `start --workers N -- bundle exec rspec "$@"`.
|
|
7
|
+
# Globals: -c/--config, -v/--verbose, -h/--help, --help (same as bundle exec polyrun).
|
|
8
|
+
# Workers: POLYRUN_WORKERS (default 5, max 10, min 1) — read by polyrun run-shards/start.
|
|
9
|
+
set -eo pipefail
|
|
10
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
11
|
+
cd "$ROOT"
|
|
12
|
+
|
|
13
|
+
W="${POLYRUN_WORKERS:-5}"
|
|
14
|
+
case "$W" in ''|*[!0-9]*) W=5 ;; esac
|
|
15
|
+
if [ "$W" -gt 10 ]; then W=10; fi
|
|
16
|
+
if [ "$W" -lt 1 ]; then W=1; fi
|
|
17
|
+
|
|
18
|
+
CONFIG="${POLYRUN_CONFIG:-polyrun.yml}"
|
|
19
|
+
polyrun_prefix=()
|
|
20
|
+
have_config=0
|
|
21
|
+
|
|
22
|
+
while [ $# -gt 0 ]; do
|
|
23
|
+
case "$1" in
|
|
24
|
+
-c|--config)
|
|
25
|
+
polyrun_prefix+=("$1" "$2")
|
|
26
|
+
CONFIG="$2"
|
|
27
|
+
have_config=1
|
|
28
|
+
shift 2
|
|
29
|
+
;;
|
|
30
|
+
-v|--verbose)
|
|
31
|
+
polyrun_prefix+=("$1")
|
|
32
|
+
shift
|
|
33
|
+
;;
|
|
34
|
+
-h|--help)
|
|
35
|
+
if [ "$have_config" -eq 0 ]; then
|
|
36
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" -c "$CONFIG" -h
|
|
37
|
+
else
|
|
38
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" -h
|
|
39
|
+
fi
|
|
40
|
+
;;
|
|
41
|
+
*)
|
|
42
|
+
break
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
done
|
|
46
|
+
|
|
47
|
+
if [ "${1:-}" = "--version" ]; then
|
|
48
|
+
if [ "$have_config" -eq 0 ]; then
|
|
49
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" -c "$CONFIG" version
|
|
50
|
+
else
|
|
51
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" version
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
is_polyrun_command() {
|
|
56
|
+
case "$1" in
|
|
57
|
+
plan|prepare|merge-coverage|report-coverage|report-junit|report-timing|env|config|merge-timing|\
|
|
58
|
+
db:setup-template|db:setup-shard|db:clone-shards|run-shards|parallel-rspec|start|build-paths|\
|
|
59
|
+
ci-shard-run|ci-shard-rspec|init|queue|quick|help|version)
|
|
60
|
+
return 0 ;;
|
|
61
|
+
*)
|
|
62
|
+
return 1 ;;
|
|
63
|
+
esac
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# True if argv should use polyrun implicit path parallel (any path-like token).
|
|
67
|
+
implicit_path_in_argv() {
|
|
68
|
+
for a in "$@"; do
|
|
69
|
+
case "$a" in
|
|
70
|
+
-*) [ "$a" = "-" ] || continue ;;
|
|
71
|
+
esac
|
|
72
|
+
case "$a" in
|
|
73
|
+
*.rb|spec/*|test/*|./|/*|*[\*\?[]*) return 0 ;;
|
|
74
|
+
esac
|
|
75
|
+
[ -e "$a" ] && return 0
|
|
76
|
+
done
|
|
77
|
+
return 1
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
run_polyrun() {
|
|
81
|
+
if [ "$have_config" -eq 0 ]; then
|
|
82
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" -c "$CONFIG" "$@"
|
|
83
|
+
else
|
|
84
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" "$@"
|
|
85
|
+
fi
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
exec_parallel_rspec() {
|
|
89
|
+
if [ "$have_config" -eq 0 ]; then
|
|
90
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" -c "$CONFIG" start --workers "$W" -- bundle exec rspec "$@"
|
|
91
|
+
else
|
|
92
|
+
exec bundle exec polyrun "${polyrun_prefix[@]}" start --workers "$W" -- bundle exec rspec "$@"
|
|
93
|
+
fi
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if [ $# -eq 0 ]; then
|
|
97
|
+
run_polyrun
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
if is_polyrun_command "$1"; then
|
|
101
|
+
run_polyrun "$@"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
if implicit_path_in_argv "$@"; then
|
|
105
|
+
run_polyrun "$@"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
exec_parallel_rspec "$@"
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
module ActionReporter
|
|
2
2
|
class ActiveVersionReporter < Base
|
|
3
|
-
class_accessor "ActiveVersion"
|
|
3
|
+
class_accessor "ActiveVersion"
|
|
4
4
|
|
|
5
5
|
def notify(*)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def context(args)
|
|
9
|
-
|
|
9
|
+
return unless ActiveVersion.respond_to?(:context=)
|
|
10
|
+
|
|
11
|
+
ActiveVersion.context = merge_context_updates(ActiveVersion.context, args)
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def reset_context
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
module ActionReporter
|
|
2
2
|
class AuditedReporter < Base
|
|
3
|
-
class_accessor "Audited"
|
|
3
|
+
class_accessor "Audited"
|
|
4
4
|
|
|
5
5
|
def notify(*)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def context(args)
|
|
9
|
-
|
|
9
|
+
return unless Audited.respond_to?(:context=)
|
|
10
|
+
|
|
11
|
+
Audited.context = merge_context_updates(Audited.context, args)
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def reset_context
|
data/lib/action_reporter/base.rb
CHANGED
|
@@ -2,7 +2,7 @@ require_relative "error"
|
|
|
2
2
|
|
|
3
3
|
module ActionReporter
|
|
4
4
|
class Base
|
|
5
|
-
def self.class_accessor(class_name
|
|
5
|
+
def self.class_accessor(class_name)
|
|
6
6
|
method_name = class_name.gsub("::", "_").downcase + "_class"
|
|
7
7
|
define_method(method_name) do
|
|
8
8
|
raise ActionReporter::Error.new("#{class_name} is not defined") unless Object.const_defined?(class_name)
|
|
@@ -24,13 +24,23 @@ module ActionReporter
|
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
def merge_context_updates(current, updates)
|
|
28
|
+
transformed = transform_context(updates)
|
|
29
|
+
keys_to_remove = transformed.each_with_object([]) do |(key, value), removals|
|
|
30
|
+
removals << key if value.nil?
|
|
31
|
+
end
|
|
32
|
+
current.merge(transformed).except(*keys_to_remove)
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
def resolve_check_in_id(identifier)
|
|
28
36
|
if identifier.respond_to?(:reporter_check_in)
|
|
29
37
|
identifier.reporter_check_in
|
|
30
38
|
elsif identifier.respond_to?(:to_s)
|
|
31
39
|
identifier.to_s
|
|
32
40
|
else
|
|
33
|
-
raise ActionReporter::Error.new(
|
|
41
|
+
raise ActionReporter::Error.new(
|
|
42
|
+
"Unknown check-in identifier (#{identifier.class}, object_id=#{identifier.object_id})"
|
|
43
|
+
)
|
|
34
44
|
end
|
|
35
45
|
end
|
|
36
46
|
|
|
@@ -48,5 +58,28 @@ module ActionReporter
|
|
|
48
58
|
|
|
49
59
|
def transaction_name=(transaction_name)
|
|
50
60
|
end
|
|
61
|
+
|
|
62
|
+
def resolve_user_id(user)
|
|
63
|
+
resolver = ActionReporter.user_id_resolver
|
|
64
|
+
if resolver.respond_to?(:call)
|
|
65
|
+
resolver.call(user)
|
|
66
|
+
else
|
|
67
|
+
default_resolve_user_id(user)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def default_resolve_user_id(user)
|
|
74
|
+
if defined?(::GlobalID) && user.is_a?(::GlobalID)
|
|
75
|
+
user.to_s
|
|
76
|
+
elsif defined?(::ActiveRecord::Base) && user.is_a?(::ActiveRecord::Base)
|
|
77
|
+
(user.try(:to_global_id) || user.try(:id)).to_s
|
|
78
|
+
elsif user.respond_to?(:to_global_id)
|
|
79
|
+
user.to_global_id.to_s
|
|
80
|
+
else
|
|
81
|
+
user.to_s
|
|
82
|
+
end
|
|
83
|
+
end
|
|
51
84
|
end
|
|
52
85
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module ActionReporter
|
|
2
2
|
class HoneybadgerReporter < Base
|
|
3
|
-
class_accessor "Honeybadger"
|
|
3
|
+
class_accessor "Honeybadger"
|
|
4
4
|
|
|
5
5
|
def notify(error, context: {})
|
|
6
6
|
new_context = transform_context(context)
|
|
@@ -8,8 +8,10 @@ module ActionReporter
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def context(args)
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
current = honeybadger_class.get_context || {}
|
|
12
|
+
merged = merge_context_updates(current, args)
|
|
13
|
+
honeybadger_class.context.clear!
|
|
14
|
+
honeybadger_class.context(merged) unless merged.empty?
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def reset_context
|
|
@@ -22,7 +24,8 @@ module ActionReporter
|
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def current_user=(user)
|
|
25
|
-
|
|
27
|
+
id = resolve_user_id(user)
|
|
28
|
+
honeybadger_class.context(user_id: id)
|
|
26
29
|
end
|
|
27
30
|
end
|
|
28
31
|
end
|
|
@@ -6,7 +6,7 @@ module ActionReporter
|
|
|
6
6
|
module PluginDiscovery
|
|
7
7
|
class << self
|
|
8
8
|
# Initialize class instance variables
|
|
9
|
-
@registered_reporters =
|
|
9
|
+
@registered_reporters = nil
|
|
10
10
|
@discovered_reporters = nil
|
|
11
11
|
@discovery_lock = Mutex.new
|
|
12
12
|
|
|
@@ -55,7 +55,7 @@ module ActionReporter
|
|
|
55
55
|
discovered_reporters << reporter_class if reporter_class
|
|
56
56
|
rescue => e
|
|
57
57
|
# Silently skip files that can't be loaded (non-blocking)
|
|
58
|
-
warn "ActionReporter: Failed to discover reporter from #{file}: #{e.message}"
|
|
58
|
+
warn "ActionReporter: Failed to discover reporter from #{file}: #{e.message}"
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
self.discovered_reporters = discovered_reporters.freeze
|
|
@@ -74,7 +74,7 @@ module ActionReporter
|
|
|
74
74
|
reporters << reporter_class if reporter_class
|
|
75
75
|
rescue => e
|
|
76
76
|
# Silently skip registered reporters that can't be loaded (non-blocking)
|
|
77
|
-
warn "ActionReporter: Failed to load registered reporter #{config[:class_name]}: #{e.message}"
|
|
77
|
+
warn "ActionReporter: Failed to load registered reporter #{config[:class_name]}: #{e.message}"
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
reporters.uniq.freeze
|
|
@@ -125,7 +125,7 @@ module ActionReporter
|
|
|
125
125
|
begin
|
|
126
126
|
require config[:require_path]
|
|
127
127
|
rescue LoadError => e
|
|
128
|
-
warn "ActionReporter: Could not require #{config[:require_path]}: #{e.message}"
|
|
128
|
+
warn "ActionReporter: Could not require #{config[:require_path]}: #{e.message}"
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ActionReporter
|
|
2
2
|
class ScoutApmReporter < Base
|
|
3
|
-
class_accessor "ScoutApm::Error"
|
|
4
|
-
class_accessor "ScoutApm::Context"
|
|
3
|
+
class_accessor "ScoutApm::Error"
|
|
4
|
+
class_accessor "ScoutApm::Context"
|
|
5
5
|
|
|
6
6
|
def notify(error, context: {})
|
|
7
7
|
self.context(context)
|
|
@@ -9,12 +9,23 @@ module ActionReporter
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def context(args)
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
context_object = scoutapm_context_class.current
|
|
13
|
+
extra = context_object.instance_variable_get(:@extra).dup
|
|
14
|
+
# ScoutApm::Context.add ignores nil values and has no per-key delete API; replace @extra directly.
|
|
15
|
+
context_object.instance_variable_set(:@extra, merge_context_updates(extra, args))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def reset_context
|
|
19
|
+
scoutapm_context_class.clear! if scoutapm_context_class.respond_to?(:clear!)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def current_remote_addr=(remote_addr)
|
|
23
|
+
scoutapm_context_class.add_user(ip: remote_addr)
|
|
14
24
|
end
|
|
15
25
|
|
|
16
26
|
def current_user=(user)
|
|
17
|
-
|
|
27
|
+
id = resolve_user_id(user)
|
|
28
|
+
scoutapm_context_class.add_user(id: id)
|
|
18
29
|
end
|
|
19
30
|
|
|
20
31
|
def ignore_transaction!
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module ActionReporter
|
|
2
2
|
class SentryReporter < Base
|
|
3
|
-
class_accessor "Sentry"
|
|
3
|
+
class_accessor "Sentry"
|
|
4
4
|
|
|
5
5
|
def notify(error, context: {})
|
|
6
6
|
sentry_class.with_scope do |temp_scope|
|
|
@@ -15,19 +15,20 @@ module ActionReporter
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def context(args)
|
|
18
|
-
|
|
18
|
+
apply_reporter_context(merge_context_updates(current_reporter_context, args))
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def reset_context
|
|
22
|
-
|
|
22
|
+
apply_reporter_context({})
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def current_user=(user)
|
|
26
|
-
|
|
26
|
+
id = resolve_user_id(user)
|
|
27
|
+
sentry_class.set_user(id: id)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def transaction_id=(transaction_id)
|
|
30
|
-
sentry_class.set_tags(
|
|
31
|
+
sentry_class.set_tags(transaction_id: transaction_id)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
def transaction_name=(transaction_name)
|
|
@@ -35,5 +36,23 @@ module ActionReporter
|
|
|
35
36
|
scope.set_transaction_name(transaction_name)
|
|
36
37
|
end
|
|
37
38
|
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def current_reporter_context
|
|
43
|
+
sentry_class.get_current_scope.contexts["context"] || {}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# sentry-ruby merges via set_context and cannot remove keys; replace the bucket via protected setter.
|
|
47
|
+
def apply_reporter_context(context_hash)
|
|
48
|
+
scope = sentry_class.get_current_scope
|
|
49
|
+
contexts = scope.contexts.dup
|
|
50
|
+
if context_hash.empty?
|
|
51
|
+
contexts.delete("context")
|
|
52
|
+
else
|
|
53
|
+
contexts["context"] = context_hash
|
|
54
|
+
end
|
|
55
|
+
scope.send(:contexts=, contexts)
|
|
56
|
+
end
|
|
38
57
|
end
|
|
39
58
|
end
|
data/lib/action_reporter.rb
CHANGED
|
@@ -33,9 +33,11 @@ module ActionReporter
|
|
|
33
33
|
PluginDiscovery.register(name, class_name: class_name, require_path: require_path)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
@enabled_reporters =
|
|
36
|
+
@enabled_reporters = nil
|
|
37
37
|
@logger = nil
|
|
38
38
|
@error_handler = nil
|
|
39
|
+
@user_id_resolver = nil
|
|
40
|
+
@no_reporters_warned = false
|
|
39
41
|
|
|
40
42
|
def enabled_reporters=(reporters)
|
|
41
43
|
@enabled_reporters = reporters || []
|
|
@@ -61,6 +63,18 @@ module ActionReporter
|
|
|
61
63
|
@error_handler = handler
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
# Optional proc to turn +current_user+ into a string id for reporters (Sentry, Scout, etc.).
|
|
67
|
+
# Receives the same object passed to +ActionReporter.current_user=+ and must return a String
|
|
68
|
+
# (or +nil+ to skip setting an id, if the reporter supports it).
|
|
69
|
+
# When unset, {ActionReporter::Base#resolve_user_id} uses built-in defaults.
|
|
70
|
+
def user_id_resolver
|
|
71
|
+
@user_id_resolver
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def user_id_resolver=(resolver)
|
|
75
|
+
@user_id_resolver = resolver
|
|
76
|
+
end
|
|
77
|
+
|
|
64
78
|
def handle_reporter_error(reporter, error, method_name)
|
|
65
79
|
error_message = "ActionReporter: #{reporter.class}##{method_name} failed: #{error.class} - #{error.message}"
|
|
66
80
|
|
|
@@ -78,6 +92,8 @@ module ActionReporter
|
|
|
78
92
|
end
|
|
79
93
|
|
|
80
94
|
def notify(error, context: {})
|
|
95
|
+
warn_if_no_reporters(:notify)
|
|
96
|
+
|
|
81
97
|
enabled_reporters.each do |reporter|
|
|
82
98
|
next unless reporter.respond_to?(:notify)
|
|
83
99
|
|
|
@@ -92,6 +108,8 @@ module ActionReporter
|
|
|
92
108
|
def context(args)
|
|
93
109
|
raise ArgumentError, "context must be a Hash" unless args.is_a?(Hash)
|
|
94
110
|
|
|
111
|
+
warn_if_no_reporters(:context)
|
|
112
|
+
|
|
95
113
|
enabled_reporters.each do |reporter|
|
|
96
114
|
next unless reporter.respond_to?(:context)
|
|
97
115
|
|
|
@@ -241,6 +259,18 @@ module ActionReporter
|
|
|
241
259
|
ensure
|
|
242
260
|
self.transaction_name = previous_name if name
|
|
243
261
|
self.transaction_id = previous_id if id
|
|
262
|
+
if context_options.any?
|
|
263
|
+
context(context_options.transform_values { nil })
|
|
264
|
+
end
|
|
244
265
|
end
|
|
245
266
|
end
|
|
267
|
+
|
|
268
|
+
def warn_if_no_reporters(method_name)
|
|
269
|
+
return if @no_reporters_warned
|
|
270
|
+
return unless enabled_reporters.empty?
|
|
271
|
+
|
|
272
|
+
@no_reporters_warned = true
|
|
273
|
+
warn "[action_reporter] #{method_name} called but enabled_reporters is empty"
|
|
274
|
+
end
|
|
275
|
+
private :warn_if_no_reporters
|
|
246
276
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: action_reporter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activesupport
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '6.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '6.0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: rails
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -16,7 +30,7 @@ dependencies:
|
|
|
16
30
|
- - ">"
|
|
17
31
|
- !ruby/object:Gem::Version
|
|
18
32
|
version: '5'
|
|
19
|
-
type: :
|
|
33
|
+
type: :development
|
|
20
34
|
prerelease: false
|
|
21
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
36
|
requirements:
|
|
@@ -111,14 +125,14 @@ dependencies:
|
|
|
111
125
|
name: bundler
|
|
112
126
|
requirement: !ruby/object:Gem::Requirement
|
|
113
127
|
requirements:
|
|
114
|
-
- - "
|
|
128
|
+
- - ">="
|
|
115
129
|
- !ruby/object:Gem::Version
|
|
116
130
|
version: '2'
|
|
117
131
|
type: :development
|
|
118
132
|
prerelease: false
|
|
119
133
|
version_requirements: !ruby/object:Gem::Requirement
|
|
120
134
|
requirements:
|
|
121
|
-
- - "
|
|
135
|
+
- - ">="
|
|
122
136
|
- !ruby/object:Gem::Version
|
|
123
137
|
version: '2'
|
|
124
138
|
- !ruby/object:Gem::Dependency
|
|
@@ -136,75 +150,75 @@ dependencies:
|
|
|
136
150
|
- !ruby/object:Gem::Version
|
|
137
151
|
version: '3'
|
|
138
152
|
- !ruby/object:Gem::Dependency
|
|
139
|
-
name:
|
|
153
|
+
name: polyrun
|
|
140
154
|
requirement: !ruby/object:Gem::Requirement
|
|
141
155
|
requirements:
|
|
142
|
-
- - "
|
|
156
|
+
- - ">="
|
|
143
157
|
- !ruby/object:Gem::Version
|
|
144
|
-
version:
|
|
158
|
+
version: 2.2.0
|
|
145
159
|
type: :development
|
|
146
160
|
prerelease: false
|
|
147
161
|
version_requirements: !ruby/object:Gem::Requirement
|
|
148
162
|
requirements:
|
|
149
|
-
- - "
|
|
163
|
+
- - ">="
|
|
150
164
|
- !ruby/object:Gem::Version
|
|
151
|
-
version:
|
|
165
|
+
version: 2.2.0
|
|
152
166
|
- !ruby/object:Gem::Dependency
|
|
153
|
-
name:
|
|
167
|
+
name: prosopite
|
|
154
168
|
requirement: !ruby/object:Gem::Requirement
|
|
155
169
|
requirements:
|
|
156
170
|
- - "~>"
|
|
157
171
|
- !ruby/object:Gem::Version
|
|
158
|
-
version: '
|
|
172
|
+
version: '2.0'
|
|
159
173
|
type: :development
|
|
160
174
|
prerelease: false
|
|
161
175
|
version_requirements: !ruby/object:Gem::Requirement
|
|
162
176
|
requirements:
|
|
163
177
|
- - "~>"
|
|
164
178
|
- !ruby/object:Gem::Version
|
|
165
|
-
version: '
|
|
179
|
+
version: '2.0'
|
|
166
180
|
- !ruby/object:Gem::Dependency
|
|
167
|
-
name:
|
|
181
|
+
name: rspec_junit_formatter
|
|
168
182
|
requirement: !ruby/object:Gem::Requirement
|
|
169
183
|
requirements:
|
|
170
184
|
- - "~>"
|
|
171
185
|
- !ruby/object:Gem::Version
|
|
172
|
-
version: '0.
|
|
186
|
+
version: '0.6'
|
|
173
187
|
type: :development
|
|
174
188
|
prerelease: false
|
|
175
189
|
version_requirements: !ruby/object:Gem::Requirement
|
|
176
190
|
requirements:
|
|
177
191
|
- - "~>"
|
|
178
192
|
- !ruby/object:Gem::Version
|
|
179
|
-
version: '0.
|
|
193
|
+
version: '0.6'
|
|
180
194
|
- !ruby/object:Gem::Dependency
|
|
181
|
-
name:
|
|
195
|
+
name: webmock
|
|
182
196
|
requirement: !ruby/object:Gem::Requirement
|
|
183
197
|
requirements:
|
|
184
198
|
- - "~>"
|
|
185
199
|
- !ruby/object:Gem::Version
|
|
186
|
-
version: '
|
|
200
|
+
version: '3'
|
|
187
201
|
type: :development
|
|
188
202
|
prerelease: false
|
|
189
203
|
version_requirements: !ruby/object:Gem::Requirement
|
|
190
204
|
requirements:
|
|
191
205
|
- - "~>"
|
|
192
206
|
- !ruby/object:Gem::Version
|
|
193
|
-
version: '
|
|
207
|
+
version: '3'
|
|
194
208
|
- !ruby/object:Gem::Dependency
|
|
195
|
-
name:
|
|
209
|
+
name: pry
|
|
196
210
|
requirement: !ruby/object:Gem::Requirement
|
|
197
211
|
requirements:
|
|
198
212
|
- - "~>"
|
|
199
213
|
- !ruby/object:Gem::Version
|
|
200
|
-
version: '
|
|
214
|
+
version: '0.15'
|
|
201
215
|
type: :development
|
|
202
216
|
prerelease: false
|
|
203
217
|
version_requirements: !ruby/object:Gem::Requirement
|
|
204
218
|
requirements:
|
|
205
219
|
- - "~>"
|
|
206
220
|
- !ruby/object:Gem::Version
|
|
207
|
-
version: '
|
|
221
|
+
version: '0.15'
|
|
208
222
|
- !ruby/object:Gem::Dependency
|
|
209
223
|
name: standard
|
|
210
224
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -356,6 +370,7 @@ files:
|
|
|
356
370
|
- LICENSE.md
|
|
357
371
|
- README.md
|
|
358
372
|
- action_reporter.gemspec
|
|
373
|
+
- bin/polyrun
|
|
359
374
|
- lib/action_reporter.rb
|
|
360
375
|
- lib/action_reporter/active_version_reporter.rb
|
|
361
376
|
- lib/action_reporter/audited_reporter.rb
|
|
@@ -393,7 +408,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
393
408
|
- !ruby/object:Gem::Version
|
|
394
409
|
version: '0'
|
|
395
410
|
requirements: []
|
|
396
|
-
rubygems_version:
|
|
411
|
+
rubygems_version: 4.0.6
|
|
397
412
|
specification_version: 4
|
|
398
413
|
summary: See description
|
|
399
414
|
test_files: []
|