Skip to content

Commit

Permalink
Initial metrics and traces providers.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Nov 8, 2024
1 parent a0737d8 commit 23dbb9f
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 13 deletions.
8 changes: 8 additions & 0 deletions config/metrics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

def prepare
require "metrics/provider/async/task"
end
8 changes: 7 additions & 1 deletion config/sus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@
require "covered/sus"
include Covered::Sus

ENV["CONSOLE_LEVEL"] ||= "fatal"
# ENV["CONSOLE_LEVEL"] ||= "fatal"

ENV["TRACES_BACKEND"] ||= "traces/backend/test"
require "traces"

ENV["METRICS_BACKEND"] ||= "metrics/backend/test"
require "metrics"
9 changes: 9 additions & 0 deletions config/traces.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

def prepare
require "traces/provider/async/task"
require "traces/provider/async/scheduler"
end
3 changes: 3 additions & 0 deletions gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
gem "decode"
gem "rubocop"

gem "traces"
gem "metrics"

gem "sus-fixtures-async"
gem "sus-fixtures-console", "~> 0.3"

Expand Down
6 changes: 6 additions & 0 deletions lib/metrics/provider/async.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

require_relative "async/task"
17 changes: 17 additions & 0 deletions lib/metrics/provider/async/task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

require_relative "../../../async/task"
require "metrics/provider"

Metrics::Provider(Async::Task) do
ASYNC_TASK_SCHEDULED = Metrics.metric("async.task.scheduled", :counter, description: "The number of tasks scheduled.")

def schedule(&block)
ASYNC_TASK_SCHEDULED.emit(1)

super(&block)
end
end
6 changes: 6 additions & 0 deletions lib/traces/provider/async.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

require_relative "async/task"
52 changes: 52 additions & 0 deletions lib/traces/provider/async/scheduler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

require_relative "../../../async/scheduler"
require "traces/provider"

# Traces::Provider(Async::Scheduler) do
# def yield
# Traces.trace("async.scheduler.yield") {super}
# end

# def block(blocker, timeout)
# attributes = {
# blocker: blocker.to_s,
# timeout: timeout
# }

# Traces.trace("async.scheduler.block", attributes: attributes) {super}
# end

# def transfer
# Traces.trace("async.scheduler.transfer") {super}
# end

# # @asynchronous May be non-blocking..
# def address_resolve(hostname)
# attributes = {
# hostname: hostname
# }

# Traces.trace("async.scheduler.address_resolve", attributes: attributes) {super}
# end

# def process_wait(pid, flags)
# attributes = {
# pid: pid,
# flags: flags
# }

# Traces.trace("async.scheduler.process_wait", attributes: attributes) {super}
# end

# def with_timeout(duration, exception = Async::TimeoutError, message = "execution expired", &block)
# attributes = {
# duration: duration,
# }

# Traces.trace("async.scheduler.with_timeout", attributes: attributes) {super}
# end
# end
29 changes: 29 additions & 0 deletions lib/traces/provider/async/task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2022, by Samuel Williams.

require_relative "../../../async/task"
require "traces/provider"

Traces::Provider(Async::Task) do
def schedule(&block)
unless self.transient?
trace_context = Traces.trace_context
end

super do
Traces.trace_context = trace_context

if annotation = self.annotation
attributes = {
"annotation" => annotation
}
end

Traces.trace("async.task", attributes: attributes) do
yield
end
end
end
end
8 changes: 8 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Releases

## Unreleased

### Traces and Metrics Providers

Async now has [traces](https://github.com/socketry/traces) and [metrics](https://github.com/socketry/metrics) providers for various core classes. This allows you to emit traces and metrics to a suitable backend (including DataDog, New Relic, OpenTelemetry, etc.) for monitoring and debugging purposes.

To take advantage of this feature, you will need to introduce your own `config/traces.rb` and `config/metrics.rb`. Async's own repository includes these files for testing purposes.

## v2.19.0

### Async::Scheduler Debugging
Expand Down
6 changes: 3 additions & 3 deletions test/async/barrier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@
task2 = barrier.async do
end

expect(task1).to be(:failed?)
expect(task2).to be(:finished?)

expect{barrier.wait}.to raise_exception(RuntimeError, message: be =~ /Boom/)

barrier.wait until barrier.empty?

expect{task1.wait}.to raise_exception(RuntimeError, message: be =~ /Boom/)

expect(barrier).to be(:empty?)

expect(task1).to be(:failed?)
expect(task2).to be(:finished?)
end

it "waits for tasks in order" do
Expand Down
7 changes: 4 additions & 3 deletions test/async/reactor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Copyright, 2017, by Devin Christensen.

require "async"
require "async/variable"
require "sus/fixtures/async"
require "benchmark/ips"

Expand Down Expand Up @@ -229,14 +230,14 @@
start_time = Time.now

subject.run do |task|
condition = Async::Condition.new
variable = Async::Variable.new

task.with_timeout(duration) do
task.async do
condition.wait
variable.wait
end

condition.signal
variable.resolve

task.yield

Expand Down
14 changes: 8 additions & 6 deletions test/async/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@
it "can yield back to scheduler" do
state = nil

reactor.async do |task|
reactor.run do |task|
child = task.async do
state = :yielding
Async::Task.yield
state = :yielded
end

# Async::Task.

Fiber.scheduler.resume(child.fiber)
end

reactor.run

expect(state).to be == :yielded
end
end
Expand Down Expand Up @@ -750,9 +750,11 @@ def sleep_forever
raise "The space time converter has failed."
end

expect do
task.wait
end.to raise_exception(RuntimeError, message: be =~ /space time converter/)
reactor.run do
expect do
task.wait
end.to raise_exception(RuntimeError, message: be =~ /space time converter/)
end

expect(task.result).to be_a(RuntimeError)
end
Expand Down

0 comments on commit 23dbb9f

Please sign in to comment.