Skip to content
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
54 changes: 54 additions & 0 deletions examples/utilization/falcon.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env async-service
# frozen_string_literal: true

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

require "falcon/environment/server"
require "async/service/supervisor/supervised"
require "async/service/supervisor/environment"
require "async/service/supervisor/utilization_monitor"

# A simple Rack application that demonstrates utilization monitoring.
class SimpleApp
def call(env)
# Simulate some work
sleep(rand * 0.1)

return [200, {"content-type" => "text/plain"}, ["Hello, World!"]]
end
end

service "web" do
include Falcon::Environment::Server
include Async::Service::Supervisor::Supervised

# Define the middleware stack for this server
middleware do
Falcon::Server.middleware(SimpleApp.new, verbose: false, cache: false)
end

# Define the utilization schema for this service
utilization_schema do
{
connections_total: :u64,
connections_active: :u32,
requests_total: :u64,
requests_active: :u32,
}
end
end

service "supervisor" do
include Async::Service::Supervisor::Environment

# Configure the utilization monitor
monitors do
[
Async::Service::Supervisor::UtilizationMonitor.new(
path: File.expand_path("utilization.shm", __dir__),
interval: 5.0
)
]
end
end
7 changes: 7 additions & 0 deletions examples/utilization/gems.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "falcon", path: "../../"
gem "async-service-supervisor", "~> 0.12"
gem "async-utilization", "~> 0.3"
1 change: 1 addition & 0 deletions falcon.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "async-http", "~> 0.75"
spec.add_dependency "async-http-cache", "~> 0.4"
spec.add_dependency "async-service", "~> 0.19"
spec.add_dependency "async-utilization", "~> 0.3"
spec.add_dependency "bundler"
spec.add_dependency "localhost", "~> 1.1"
spec.add_dependency "openssl", ">= 3.0"
Expand Down
2 changes: 1 addition & 1 deletion lib/falcon/environment/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def client_endpoint
# @parameter endpoint [IO::Endpoint] The endpoint to bind to.
# @returns [Falcon::Server] The server instance.
def make_server(endpoint)
Falcon::Server.new(self.middleware, endpoint, protocol: self.endpoint.protocol, scheme: self.endpoint.scheme)
Falcon::Server.new(self.middleware, endpoint, protocol: self.endpoint.protocol, scheme: self.endpoint.scheme, utilization_registry: self[:utilization_registry])
end
end
end
Expand Down
44 changes: 21 additions & 23 deletions lib/falcon/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
require "protocol/http/content_encoding"

require "async/http/cache"
require "async/utilization"
require_relative "middleware/verbose"
require "protocol/rack"

Expand Down Expand Up @@ -37,38 +38,35 @@ def self.middleware(rack_app, verbose: false, cache: true)
end

# Initialize the server and set up statistics tracking.
def initialize(...)
super
#
# @parameter utilization_registry [Registry, nil] The utilization registry to use for metrics tracking.
# If nil, a new registry instance is created.
def initialize(*arguments, utilization_registry: nil, **options)
super(*arguments, **options)

@accept_count = 0
@connection_count = 0
utilization_registry ||= Async::Utilization::Registry.new

@request_count = 0
@active_count = 0
# Get metric references for utilization tracking:
@connections_total_metric = utilization_registry.metric(:connections_total)
@connections_active_metric = utilization_registry.metric(:connections_active)
@requests_total_metric = utilization_registry.metric(:requests_total)
@requests_active_metric = utilization_registry.metric(:requests_active)
end

attr :request_count
attr :accept_count
attr :connect_count

# Accept a new connection and track connection statistics.
def accept(...)
@accept_count += 1
@connection_count += 1

super
ensure
@connection_count -= 1
@connections_total_metric.increment
@connections_active_metric.track do
super
end
end

# Handle a request and track request statistics.
def call(...)
@request_count += 1
@active_count += 1

super
ensure
@active_count -= 1
@requests_total_metric.increment
@requests_active_metric.track do
super
end
end

# Generates a human-readable string representing the current statistics.
Expand All @@ -83,7 +81,7 @@ def call(...)
#
# @returns [String] A string representing the current statistics.
def statistics_string
"C=#{format_count @connection_count}/#{format_count @accept_count} R=#{format_count @active_count}/#{format_count @request_count}"
"C=#{format_count @connections_active_metric.value}/#{format_count @connections_total_metric.value} R=#{format_count @requests_active_metric.value}/#{format_count @requests_total_metric.value}"
end

private
Expand Down
1 change: 1 addition & 0 deletions releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- **Breaking**: Drop dependency on `async-container-supervisor`, you should migrate to `async-service-supervisor` instead.
- **Breaking**: Remove support for legacy environments, including `Falcon::Configuration`, now using `Async::Service::Configuration` directly.
- **Breaking**: `bake falcon:supervisor:restart` removed – superceeded by `async:service:supervisor:restart`.
- Add support for `async-utilization` metrics.

## v0.54.1

Expand Down
Loading