I recently published my first Ruby gem, app_pulse, and I wanted to share the motivation, design decisions, and lessons learned while building it.
This is not an APM, not a dashboard, and not an optimizer.
It’s a signal collector.
Why app_pulse?
In many Ruby and Rails applications, we jump too quickly to dashboards, alerts, or optimization tools before we even understand what’s happening inside our apps.
I wanted a tool that:
- Collects request lifecycle signals
- Is safe in production
- Does not depend on Rails internals
- Stores data in simple formats
- Lets developers decide later what to do with the data
That idea became app_pulse.
What app_pulse Does
app_pulse is a Rack-based middleware that captures basic request signals:
- Timestamp (UTC, ISO-8601)
- HTTP method
- Path
- Status code
- Duration (ms)
- Success / failure
- Error message (if any)
The data is stored locally in CSV, JSON, or Text files, rotated daily.
No database.
No UI.
No advice.
Just clean signals.
What app_pulse Does NOT Do
This is important:
- ❌ No performance recommendations
- ❌ No dashboards
- ❌ No automatic optimization
- ❌ No Rails-only behavior
- ❌ No database writes
Those concerns are intentionally left for future extensions or external tools.
Design Philosophy
A few principles guided this gem:
- Signals > opinions
- Rack first, Rails friendly
- Zero configuration by default
- Fail silently, never break the host app
- Extensible, not monolithic
Observability tools should never affect availability.
Example Usage (Rails)
# config/application.rb
config.middleware.use AppPulse::Middleware::Request
Optional configuration:
AppPulse.configure do |config|
config.output_path = "log/app_pulse"
config.output_format = :csv
config.sampling_rate = 1.0
end
That’s it.
Ruby & Framework Compatibility
Ruby 2.3+
Rails, Rack, Sinatra
No ActiveSupport dependency in core
The gem is tested with modern Ruby and older Ruby (2.3) using Rack apps.
Lessons Learned
Building and releasing this gem taught me a lot about:
Ruby gem packaging pitfalls
Load path issues
Semantic versioning
Testing across Ruby versions
Designing APIs that don’t lock you in early
Shipping something small and correct is much harder — and more valuable — than shipping something big and fragile.
Links
RubyGems: https://rubygems.org/gems/app_pulse
Source code: https://github.com/virendra-jadhav/app_pulse
Feedback, critique, and suggestions are very welcome.
Top comments (0)