diff --git a/.gitignore b/.gitignore index 70f8f10..4f37bd8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ Gemfile.lock # Ignore .idea .idea +# Ignore log files +log/*.log \ No newline at end of file diff --git a/bin/scout_apm_logging_monitor b/bin/scout_apm_logging_monitor new file mode 100644 index 0000000..e156f65 --- /dev/null +++ b/bin/scout_apm_logging_monitor @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +require_relative "../lib/scout_apm/logging/monitor/monitor.rb" + +ScoutApm::Logging::Monitor.new.run diff --git a/lib/scout_apm/logging/monitor/monitor.rb b/lib/scout_apm/logging/monitor/monitor.rb new file mode 100644 index 0000000..532d4e0 --- /dev/null +++ b/lib/scout_apm/logging/monitor/monitor.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +## +# Launched as a daemon process by the monitor manager and Rails startup. +## + +module ScoutApm + module Logging + class Monitor + def run + loop do + sleep 1 + puts "Running..." + end + end + end + end +end diff --git a/lib/scout_apm/logging/monitor_manager.rb b/lib/scout_apm/logging/monitor_manager.rb new file mode 100644 index 0000000..b6f6d2f --- /dev/null +++ b/lib/scout_apm/logging/monitor_manager.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module ScoutApm + module Logging + class MonitorManager + PID_FILE = '/tmp/scout_apm_log_monitor.pid' + + @instance = nil + + # TODO: Is this necessary? + def self.instance + @instance ||= new + end + + def self.setup! + instance.create_process + end + + def create_process + return if File.exist? PID_FILE + + gem_directory = File.expand_path('../../..', __dir__) + monitor_daemon = Process.spawn("ruby #{gem_directory}/bin/scout_apm_logging_monitor &") + + # TODO: Why are we off by one? + File.write(PID_FILE, monitor_daemon + 1) + + # TODO: Add exit handlers? + end + end + end +end \ No newline at end of file diff --git a/lib/scout_apm_logging.rb b/lib/scout_apm_logging.rb index f8e3650..6d7323f 100644 --- a/lib/scout_apm_logging.rb +++ b/lib/scout_apm_logging.rb @@ -2,12 +2,15 @@ require 'scout_apm' +require 'scout_apm/logging/monitor_manager' + module ScoutApm module Logging - # Temporary class for testing hierarchy. - class Hello - def self.world - puts 'Hello World.' + if defined?(Rails) && defined?(Rails::Railtie) + class RailTie < ::Rails::Railtie + initializer "scout_apm_logging.monitor" do + ScoutApm::Logging::MonitorManager.setup! + end end end end diff --git a/spec/scout_apm_logging_spec.rb b/spec/scout_apm_logging_spec.rb index d940ee1..dabd948 100644 --- a/spec/scout_apm_logging_spec.rb +++ b/spec/scout_apm_logging_spec.rb @@ -2,13 +2,28 @@ require 'spec_helper' +require 'rails' + describe ScoutApm::Logging do - let(:hello_world) do - Class.new(ScoutApm::Logging::Hello) + before(:all) do + # Run the Railtie initializers to trigger the daemon spawning + make_basic_app + end + + it "spawns the daemon process" do + # Check if the PID file exists + expect(File.exist?(ScoutApm::Logging::MonitorManager::PID_FILE)).to be_truthy + + # Read the PID from the PID file + pid = File.read(ScoutApm::Logging::MonitorManager::PID_FILE).to_i + + # Check if the process with the stored PID is running + expect(Process.kill(0, pid)).to be_truthy end - it 'writes hello world' do - allow($stdout).to receive(:puts) - expect { hello_world.world }.to output("Hello World.\n").to_stdout + after(:all) do + process = File.read(ScoutApm::Logging::MonitorManager::PID_FILE).to_i + Process.kill('TERM', process) + File.delete(ScoutApm::Logging::MonitorManager::PID_FILE) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3132d52..f84c0fd 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,34 @@ # frozen_string_literal: true require 'scout_apm' -require 'scout_apm_logging' + +# Taken from: +# https://github.com/rails/rails/blob/v7.1.3.2/railties/test/isolation/abstract_unit.rb#L252 +def make_basic_app + require "rails" + require "action_controller/railtie" + require "action_view/railtie" + + # Require after rails, to ensure the railtie is loaded + require 'scout_apm_logging' + + @app = Class.new(Rails::Application) do + def self.name; "RailtiesTestApp"; end + end + @app.config.hosts << proc { true } + @app.config.eager_load = false + @app.config.session_store :cookie_store, key: "_myapp_session" + @app.config.active_support.deprecation = :log + @app.config.log_level = :info + @app.config.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33" + + yield @app if block_given? + @app.initialize! + + @app.routes.draw do + get "/" => "omg#index" + end + + require "rack/test" + extend ::Rack::Test::Methods +end \ No newline at end of file