Class: ActiveSanction::Instrumentation::Event
- Inherits:
-
Object
- Object
- ActiveSanction::Instrumentation::Event
- Extended by:
- T::Sig
- Defined in:
- lib/active_sanction/instrumentation/event.rb
Overview
One thing this library did, after it finished doing it.
ActiveSanction.configure do |c|
c.instrumenter = ->(event) { StatsD.timing("sanctions.#{event.name}", event.duration_ms) }
end
event.name # => :fetch
event.duration # => 2.418, seconds
event[:source] # => :ofac_sdn
event[:bytes] # => 12_845_056
A subscriber is handed a finished event and never a running one. That is
the difference between this and a block-based instrumenter, and it is
deliberate: a subscriber that cannot wrap the work cannot retry it,
cannot swallow its exception, and cannot leave a begin half-entered if
it raises. The cost is that nothing here can time a stage from the
outside -- which nothing needs to, since every event already carries its
own duration.
Every event carries a duration and enough to correlate it
There are no anonymous timings. duration is monotonic seconds, taken
across the stage this event describes, and started_at is the wall
clock at its start -- both, because one answers "how long did it take"
and the other answers "when, in the log I am reading beside this". Every
event but screen names a source; screen names the snapshot
checksums it consulted, which is the same question asked of a query.
An event is emitted for work that raised
With error set to the exception, and with whichever payload keys the
stage had filled in before it failed. A publisher that starts timing out
is exactly what a host is watching for, and an instrumentation layer
that only reports successes cannot see it. See Instrumentation.
Frozen, and its payload with it, so a subscriber cannot edit what the next one is handed.
Instance Attribute Summary collapse
-
#duration ⇒ Float
readonly
Seconds the stage took, from a monotonic clock, so it is not moved by a clock adjustment mid-stage.
-
#name ⇒ Symbol
readonly
The stage this event describes -- one of Instrumentation::EVENTS.
-
#payload ⇒ Hash{Symbol => T.untyped}
readonly
What the stage measured, keyed as documented for each event name in docs/api_stability.md.
-
#started_at ⇒ Time
readonly
The wall clock when the stage started, UTC.
Instance Method Summary collapse
-
#[](key) ⇒ T.untyped
One payload key, or nil for one this event does not carry.
-
#duration_ms ⇒ Float
Milliseconds, which is what a metrics backend usually wants.
-
#error ⇒ StandardError?
The exception the stage raised, or nil for one that finished.
- #failed? ⇒ Boolean
-
#finished_at ⇒ Time
The wall clock when the stage finished.
- #initialize(name:, payload:, started_at:, duration:) ⇒ void constructor
- #inspect ⇒ String
-
#source ⇒ Symbol?
Which list this was about, or nil for an event that is not about one --
screen, which is about a query, andsync, which is about a run. -
#to_h ⇒ Hash{Symbol => T.untyped}
The whole event as one Hash, for a subscriber that forwards it somewhere structured.
- #to_s ⇒ String
Constructor Details
#initialize(name:, payload:, started_at:, duration:) ⇒ void
70 71 72 73 74 75 76 |
# File 'lib/active_sanction/instrumentation/event.rb', line 70 def initialize(name:, payload:, started_at:, duration:) @name = T.let(name, Symbol) @payload = T.let(payload.freeze, T::Hash[Symbol, T.untyped]) @started_at = T.let(started_at, Time) @duration = T.let(duration, Float) freeze end |
Instance Attribute Details
#duration ⇒ Float (readonly)
Seconds the stage took, from a monotonic clock, so it is not moved by a clock adjustment mid-stage.
65 66 67 |
# File 'lib/active_sanction/instrumentation/event.rb', line 65 def duration @duration end |
#name ⇒ Symbol (readonly)
The stage this event describes -- one of Instrumentation::EVENTS.
50 51 52 |
# File 'lib/active_sanction/instrumentation/event.rb', line 50 def name @name end |
#payload ⇒ Hash{Symbol => T.untyped} (readonly)
What the stage measured, keyed as documented for each event name in docs/api_stability.md. Frozen.
55 56 57 |
# File 'lib/active_sanction/instrumentation/event.rb', line 55 def payload @payload end |
#started_at ⇒ Time (readonly)
The wall clock when the stage started, UTC. For lining an event up
against a log; duration is what to measure with.
60 61 62 |
# File 'lib/active_sanction/instrumentation/event.rb', line 60 def started_at @started_at end |
Instance Method Details
#[](key) ⇒ T.untyped
One payload key, or nil for one this event does not carry.
80 |
# File 'lib/active_sanction/instrumentation/event.rb', line 80 def [](key) = payload[key] |
#duration_ms ⇒ Float
Milliseconds, which is what a metrics backend usually wants.
104 |
# File 'lib/active_sanction/instrumentation/event.rb', line 104 def duration_ms = (duration * 1_000).round(3).to_f |
#error ⇒ StandardError?
The exception the stage raised, or nil for one that finished. An event carrying one is a partial measurement: the keys the stage had not reached are absent rather than zero.
91 |
# File 'lib/active_sanction/instrumentation/event.rb', line 91 def error = payload[:error] |
#failed? ⇒ Boolean
94 |
# File 'lib/active_sanction/instrumentation/event.rb', line 94 def failed? = !error.nil? |
#finished_at ⇒ Time
The wall clock when the stage finished. Derived from started_at and
the monotonic duration rather than read again, so the two cannot
disagree about how long this took.
100 |
# File 'lib/active_sanction/instrumentation/event.rb', line 100 def finished_at = started_at + duration |
#inspect ⇒ String
119 |
# File 'lib/active_sanction/instrumentation/event.rb', line 119 def inspect = "#<#{self.class} #{name} #{payload.inspect} #{format("%.3f", duration)}s>" |
#source ⇒ Symbol?
Which list this was about, or nil for an event that is not about one
-- screen, which is about a query, and sync, which is about a run.
85 |
# File 'lib/active_sanction/instrumentation/event.rb', line 85 def source = payload[:source] |
#to_h ⇒ Hash{Symbol => T.untyped}
The whole event as one Hash, for a subscriber that forwards it
somewhere structured. The payload is spread in at the top level, and
its keys win over nothing -- name, started_at and duration are
not payload keys on any event this library emits.
111 112 113 |
# File 'lib/active_sanction/instrumentation/event.rb', line 111 def to_h { name: name, started_at: started_at, duration: duration }.merge(payload) end |
#to_s ⇒ String
116 |
# File 'lib/active_sanction/instrumentation/event.rb', line 116 def to_s = "#{name} #{format("%.3f", duration)}s#{" #{source}" if source}#{" failed" if failed?}" |