A specialized Ruby library designed to inject Datadog monitoring capabilities into Ruby applications with minimal impact and maximum compatibility across different Ruby environments.
The Datadog Ruby Injector is an unusual Ruby project that allows injecting telemetry and tracing capabilities into Ruby applications, engineered to be compatible with a wide range of Ruby versions (1.8.7 and newer) and implementations (including JRuby).
This project differs from conventional Ruby applications:
-
Custom Module System: Instead of using Ruby's standard
requiremechanism, it implements a custom import system that creates isolated modules for each file to avoid any global namespace pollution. -
Broad Version Compatibility: Designed to work with CRuby 1.8.7 to 3.4, as well as JRuby 9.2 to 9.4.
-
Zero Global Footprint: The injector is carefully designed to avoid creating any global variables or constants, making it completely unintrusive to the host application. Once the injection is done, most - ideally all - of it will be unreferenced and garbage-collected.
-
No Gem Packaging: Unlike most Ruby libraries that are packaged as gems, the injector is designed for direct inclusion via Ruby's
-roption. -
Rich Testing Matrix: The test suite uses a sophisticated matrix approach to test across the whole matrix of Ruby environments, bundler configurations, and application scenarios very quickly.
- Automatic detection of the Ruby runtime environment
- Safe injection mechanics with guards to prevent incompatible injections
- Telemetry emission for monitoring the injection process
- Support for various Ruby runtime contexts including Bundler-managed environments
- Compatibility with deployment, frozen, and hot (development-like) environments
- Ruby (MRI) version 1.8.7 or newer, or JRuby 9.2+
- For test running: docker
- For development: Nix package manager (project uses flakes)
The injector is typically loaded via Ruby's -r option:
ruby -r/path/to/datadog-injector-rb/src/injector.rb your_application.rb
Note: Best behaviour is only guaranteed when the injector is loaded first.
Alternatively, using the RUBYOPT environment variable makes use of the injector automatic:
export RUBYOPT="-r/path/to/datadog-injector-rb/src/injector.rb"
# run as usual
ruby your_application.rb
# or using bundler
bundle exec ruby your_application.rb
/src: Contains the main injector codeinjector.rb: Entry point for the library/mod: Module files that provide the core functionality
/test: Test fixtures and utilities/fixtures: Different application environments for testing/unit: Unit teststest.rb: Main test runner
The test suite is designed to validate the injector's behavior across multiple Ruby environments and application configurations. The testing framework employs a comprehensive test matrix approach to verify compatibility across different scenarios.
There are two kind of tests:
- Unit Tests: narrow and focused on strict, detailed guarantees
- Component Tests: behaviour oriented, aims to validate component contract
The test matrix evaluates the injector against:
- Ruby Implementations: MRI Ruby (1.8.7 through 3.4) and JRuby (9.2 through 9.4)
- Environment Types:
hot: Standard Bundler environmentdeployment: Bundler deployment modefrozen: Bundler with frozen dependenciesunbundled: Ruby environment without Bundler
To run the full test suite:
ruby test.rbTo run specific tests (TODO):
# Run tests for a specific Ruby version
ruby test.rb "ruby:2.7"
# Run tests for a specific fixture
ruby test.rb "fixture:hot"
# Run tests for a specific combination
ruby test.rb "ruby:2.7 fixture:hot"The /test/fixtures directory contains different application environments used for testing:
hot: Standard Bundler environment with a Gemfiledeployment: Tests against Bundler deployment modefrozen: Tests with Bundler's frozen dependenciesunbundled: Tests without Bundler integration (no Gemfile)
Test results show telemetry events and injection status for each scenario, validating:
- Proper startup detection (
telemetry should include start) - Correct decision-making based on the environment (proceed or abort)
- Proper reason codes for abort when applicable
- Successful completion in compatible environments
This project optionally uses Nix for simple development environment management. To set up a development environment:
- Install Nix if you haven't already
- Run
nix develop(or its older incantationnix-shell)
Copyright (c) Datadog, Inc. See LICENSE file.