scout_apm_logging 0.0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.github/workflows/test.yml +37 -0
 - data/.gitignore +13 -0
 - data/.rubocop.yml +65 -0
 - data/Dockerfile +18 -0
 - data/Gemfile +5 -0
 - data/README.md +58 -0
 - data/Rakefile +35 -0
 - data/bin/scout_apm_logging_monitor +5 -0
 - data/gems/rails.gemfile +3 -0
 - data/lib/scout_apm/logging/config.rb +265 -0
 - data/lib/scout_apm/logging/context.rb +58 -0
 - data/lib/scout_apm/logging/logger.rb +26 -0
 - data/lib/scout_apm/logging/loggers/capture.rb +46 -0
 - data/lib/scout_apm/logging/loggers/formatter.rb +86 -0
 - data/lib/scout_apm/logging/loggers/logger.rb +82 -0
 - data/lib/scout_apm/logging/loggers/proxy.rb +39 -0
 - data/lib/scout_apm/logging/loggers/swap.rb +82 -0
 - data/lib/scout_apm/logging/monitor/collector/checksum.rb +51 -0
 - data/lib/scout_apm/logging/monitor/collector/configuration.rb +148 -0
 - data/lib/scout_apm/logging/monitor/collector/downloader.rb +78 -0
 - data/lib/scout_apm/logging/monitor/collector/extractor.rb +37 -0
 - data/lib/scout_apm/logging/monitor/collector/manager.rb +57 -0
 - data/lib/scout_apm/logging/monitor/monitor.rb +214 -0
 - data/lib/scout_apm/logging/monitor_manager/manager.rb +150 -0
 - data/lib/scout_apm/logging/state.rb +70 -0
 - data/lib/scout_apm/logging/utils.rb +86 -0
 - data/lib/scout_apm/logging/version.rb +7 -0
 - data/lib/scout_apm_logging.rb +35 -0
 - data/scout_apm_logging.gemspec +27 -0
 - data/spec/data/config_test_1.yml +27 -0
 - data/spec/data/empty_logs_config.yml +0 -0
 - data/spec/data/logs_config.yml +3 -0
 - data/spec/data/mock_config.yml +29 -0
 - data/spec/data/state_file.json +3 -0
 - data/spec/integration/loggers/capture_spec.rb +78 -0
 - data/spec/integration/monitor/collector/downloader/will_verify_checksum.rb +47 -0
 - data/spec/integration/monitor/collector_healthcheck_spec.rb +27 -0
 - data/spec/integration/monitor/continuous_state_collector_spec.rb +29 -0
 - data/spec/integration/monitor/previous_collector_setup_spec.rb +42 -0
 - data/spec/integration/monitor_manager/disable_agent_spec.rb +28 -0
 - data/spec/integration/monitor_manager/monitor_pid_file_spec.rb +36 -0
 - data/spec/integration/monitor_manager/single_monitor_spec.rb +53 -0
 - data/spec/integration/rails/lifecycle_spec.rb +29 -0
 - data/spec/spec_helper.rb +65 -0
 - data/spec/unit/config_spec.rb +25 -0
 - data/spec/unit/loggers/capture_spec.rb +64 -0
 - data/spec/unit/monitor/collector/configuration_spec.rb +64 -0
 - data/spec/unit/state_spec.rb +20 -0
 - data/tooling/checksums.rb +106 -0
 - metadata +167 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 198bf309d17f0abfcf2c33f820a2d44e1e92ef5af9e321ee9fbaacfec256f032
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 2a09b14a45e702fe1e4f4caee6ff89475e14971ba9edad41ae5cf3c72ab97850
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ebd30ceac50e2f14f3693946e8dd883112cc502513678b3a9963e253f2622d1ea488c2a66bce01f3e20726d7c6f08f61392cde6f22f1d9d0412987780f6399fa
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c0cfeb3cfbed2628772550b18b1a2f7965a144fafea14846ed65936043ae283b48cef6ba0109a05dfe9df3b826080d0f24676c0957b3909311cae12098b1e2de
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            name: Test
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            on: [push, pull_request]
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            jobs:
         
     | 
| 
      
 6 
     | 
    
         
            +
              test:
         
     | 
| 
      
 7 
     | 
    
         
            +
                name: RSpec
         
     | 
| 
      
 8 
     | 
    
         
            +
                strategy:
         
     | 
| 
      
 9 
     | 
    
         
            +
                  fail-fast: false
         
     | 
| 
      
 10 
     | 
    
         
            +
                  matrix:
         
     | 
| 
      
 11 
     | 
    
         
            +
                    ruby: ['2.6', '2.7', '3.0', '3.1', '3.2', '3.3' ]
         
     | 
| 
      
 12 
     | 
    
         
            +
                env:
         
     | 
| 
      
 13 
     | 
    
         
            +
                  DOCKER_RUBY_VERSION: ${{ matrix.ruby }}
         
     | 
| 
      
 14 
     | 
    
         
            +
                  BUNDLE_GEMFILE: gems/rails.gemfile
         
     | 
| 
      
 15 
     | 
    
         
            +
                runs-on: ubuntu-20.04
         
     | 
| 
      
 16 
     | 
    
         
            +
                steps:
         
     | 
| 
      
 17 
     | 
    
         
            +
                  - uses: actions/checkout@v2
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - name: Set up Ruby
         
     | 
| 
      
 19 
     | 
    
         
            +
                    uses: ruby/setup-ruby@v1
         
     | 
| 
      
 20 
     | 
    
         
            +
                    with:
         
     | 
| 
      
 21 
     | 
    
         
            +
                      ruby-version: ${{ matrix.ruby }}
         
     | 
| 
      
 22 
     | 
    
         
            +
                      bundler-cache: true
         
     | 
| 
      
 23 
     | 
    
         
            +
                  - name: Run RSpec
         
     | 
| 
      
 24 
     | 
    
         
            +
                    run: bundle exec rake test
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              rubocop:
         
     | 
| 
      
 27 
     | 
    
         
            +
                name: RuboCop
         
     | 
| 
      
 28 
     | 
    
         
            +
                runs-on: ubuntu-latest
         
     | 
| 
      
 29 
     | 
    
         
            +
                steps:
         
     | 
| 
      
 30 
     | 
    
         
            +
                  - uses: actions/checkout@v2
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - name: Set up Ruby
         
     | 
| 
      
 32 
     | 
    
         
            +
                    uses: ruby/setup-ruby@v1
         
     | 
| 
      
 33 
     | 
    
         
            +
                    with:
         
     | 
| 
      
 34 
     | 
    
         
            +
                      ruby-version: "3.2"
         
     | 
| 
      
 35 
     | 
    
         
            +
                      bundler-cache: true
         
     | 
| 
      
 36 
     | 
    
         
            +
                  - name: Run check
         
     | 
| 
      
 37 
     | 
    
         
            +
                    run: bundle exec rubocop
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rubocop.yml
    ADDED
    
    | 
         @@ -0,0 +1,65 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            AllCops:
         
     | 
| 
      
 2 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 3 
     | 
    
         
            +
                - "bin/*"
         
     | 
| 
      
 4 
     | 
    
         
            +
                - "tmp/**/*"
         
     | 
| 
      
 5 
     | 
    
         
            +
                - "vendor/**/*"
         
     | 
| 
      
 6 
     | 
    
         
            +
                - "spec/spec_helper.rb"
         
     | 
| 
      
 7 
     | 
    
         
            +
                - "gems/*"
         
     | 
| 
      
 8 
     | 
    
         
            +
                - "Rakefile"
         
     | 
| 
      
 9 
     | 
    
         
            +
                - "tooling/*"
         
     | 
| 
      
 10 
     | 
    
         
            +
              NewCops: disable
         
     | 
| 
      
 11 
     | 
    
         
            +
              TargetRubyVersion: 2.6
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Metrics/BlockLength:
         
     | 
| 
      
 14 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 15 
     | 
    
         
            +
                - "spec/**/*"
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            Metrics/ClassLength:
         
     | 
| 
      
 18 
     | 
    
         
            +
              Max: 150
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            Style/FrozenStringLiteralComment:
         
     | 
| 
      
 21 
     | 
    
         
            +
              EnforcedStyle: always
         
     | 
| 
      
 22 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 23 
     | 
    
         
            +
                - "Gemfile*"
         
     | 
| 
      
 24 
     | 
    
         
            +
                - "*.gemspec"
         
     | 
| 
      
 25 
     | 
    
         
            +
                - "spec/**/*"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            Naming/FileName:
         
     | 
| 
      
 28 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 29 
     | 
    
         
            +
                - "lib/scout_apm/scout_apm_logging.rb"
         
     | 
| 
      
 30 
     | 
    
         
            +
                - "spec/scout_apm_logging_spec.rb"
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            Style/Documentation:
         
     | 
| 
      
 33 
     | 
    
         
            +
              Enabled: true
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            Naming/PredicateName:
         
     | 
| 
      
 36 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            Metrics/PerceivedComplexity:
         
     | 
| 
      
 39 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            Metrics/CyclomaticComplexity:
         
     | 
| 
      
 42 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            Style/ClassVars:
         
     | 
| 
      
 45 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            Style/EmptyElse:
         
     | 
| 
      
 48 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            Naming/AccessorMethodName:
         
     | 
| 
      
 51 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            Metrics/MethodLength:
         
     | 
| 
      
 54 
     | 
    
         
            +
              Max: 25
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            Lint/LiteralAsCondition:
         
     | 
| 
      
 57 
     | 
    
         
            +
              Enabled: false
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            Layout/LineLength:
         
     | 
| 
      
 60 
     | 
    
         
            +
              Max: 130
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            Style/PercentLiteralDelimiters:
         
     | 
| 
      
 63 
     | 
    
         
            +
              PreferredDelimiters:
         
     | 
| 
      
 64 
     | 
    
         
            +
                '%w': "[]"
         
     | 
| 
      
 65 
     | 
    
         
            +
                '%W': "[]"
         
     | 
    
        data/Dockerfile
    ADDED
    
    | 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ARG RUBY_VERSION=3.3
         
     | 
| 
      
 2 
     | 
    
         
            +
            FROM ruby:$RUBY_VERSION
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # Set the working directory inside the container
         
     | 
| 
      
 5 
     | 
    
         
            +
            WORKDIR /app
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ARG BUNDLE_GEMFILE=./gems/rails.gemfile
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # # Copy the entire project directory into the container
         
     | 
| 
      
 10 
     | 
    
         
            +
            COPY . .
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            # Remove any local .lock files after copying
         
     | 
| 
      
 13 
     | 
    
         
            +
            RUN find . -type f -name "*.lock" -exec rm -f {} \;
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            # Install dependencies
         
     | 
| 
      
 16 
     | 
    
         
            +
            RUN bundle install
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ENV BUNDLE_GEMFILE=./gems/rails.gemfile
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ScoutApm Ruby Logging
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            [](https://github.com/scoutapp/scout_apm_ruby_logging/actions)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            A Ruby gem for detailed, easy to navigate, managed log monitoring.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Sign up for an account at https://www.scoutapm.com to start monitoring your logs and application performance in minutes.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ## Getting Started
         
     | 
| 
      
 10 
     | 
    
         
            +
            Add the gem to your Gemfile: 
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 13 
     | 
    
         
            +
            gem 'scout_apm_logging'
         
     | 
| 
      
 14 
     | 
    
         
            +
            ```
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            Update your Gemfile: 
         
     | 
| 
      
 17 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 18 
     | 
    
         
            +
            bundle install
         
     | 
| 
      
 19 
     | 
    
         
            +
            ```
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            Update your [RAILS_ROOT/config/scout_apm.yml](https://scoutapm.com/apps/new_ruby_application_configuration) and add the following:
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ```yaml
         
     | 
| 
      
 24 
     | 
    
         
            +
              # ... Previous &defaults or environment defined configurations
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # ENV equivalent: SCOUT_LOGS_MONITOR=true
         
     | 
| 
      
 27 
     | 
    
         
            +
              # ENV equivalent: SCOUT_LOGS_INGEST_KEY=...
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              logs_monitor: true
         
     | 
| 
      
 30 
     | 
    
         
            +
              logs_ingest_key: ...
         
     | 
| 
      
 31 
     | 
    
         
            +
            ```
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            Deploy :rocket:
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ## Testing
         
     | 
| 
      
 36 
     | 
    
         
            +
            To run the entire test suite:
         
     | 
| 
      
 37 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 38 
     | 
    
         
            +
            bundle exec rake test
         
     | 
| 
      
 39 
     | 
    
         
            +
            ```
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            To run an individual test file within the suite:
         
     | 
| 
      
 42 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 43 
     | 
    
         
            +
            bundle exec rake test file=/path/to/spec/_spec.rb
         
     | 
| 
      
 44 
     | 
    
         
            +
            ```
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            To run test(s) against a specific Ruby version:
         
     | 
| 
      
 47 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 48 
     | 
    
         
            +
            DOCKER_RUBY_VERSION=3.3 bundle exec rake test
         
     | 
| 
      
 49 
     | 
    
         
            +
            ```
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            ## Local
         
     | 
| 
      
 52 
     | 
    
         
            +
            Point your Gemfile at your local checkout: 
         
     | 
| 
      
 53 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 54 
     | 
    
         
            +
            gem 'scout_apm_logging', path: '/path/to/scout_apm_ruby_logging'
         
     | 
| 
      
 55 
     | 
    
         
            +
            ```
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            ## Help
         
     | 
| 
      
 58 
     | 
    
         
            +
            Email support@scoutapm.com if you need a hand.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            task :default => :test
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            task :test do
         
     | 
| 
      
 4 
     | 
    
         
            +
              ruby_version = ENV.has_key?("DOCKER_RUBY_VERSION") ? ENV["DOCKER_RUBY_VERSION"] : "3.3"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              unless system("docker image inspect rspec-runner-#{ruby_version} > /dev/null 2>&1")
         
     | 
| 
      
 7 
     | 
    
         
            +
                puts "Building RSpec runner Docker image..."
         
     | 
| 
      
 8 
     | 
    
         
            +
                system("docker build --build-arg RUBY_VERSION=#{ruby_version} -t rspec-runner-#{ruby_version} .")
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              additional_options = ENV["debug"] ? "-it" : ""
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              if ENV["file"]
         
     | 
| 
      
 14 
     | 
    
         
            +
                puts "Running RSpec test for #{ENV["file"]}..."
         
     | 
| 
      
 15 
     | 
    
         
            +
                system("docker run -v #{Dir.pwd}/lib:/app/lib -v #{Dir.pwd}/spec:/app/spec #{additional_options} --rm rspec-runner-#{ruby_version} bundle exec rspec #{ENV["file"]} 2>&1")
         
     | 
| 
      
 16 
     | 
    
         
            +
              else
         
     | 
| 
      
 17 
     | 
    
         
            +
                puts "Running RSpec tests..."
         
     | 
| 
      
 18 
     | 
    
         
            +
                Dir.glob("spec/**/*_spec.rb") do |spec_file|
         
     | 
| 
      
 19 
     | 
    
         
            +
                  puts "Running #{spec_file}..."
         
     | 
| 
      
 20 
     | 
    
         
            +
                  system("docker run -v #{Dir.pwd}/lib:/app/lib -v #{Dir.pwd}/spec:/app/spec #{additional_options} --rm rspec-runner-#{ruby_version} bundle exec rspec #{spec_file} 2>&1")
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  # Exit the task if a test fails
         
     | 
| 
      
 23 
     | 
    
         
            +
                  unless $?.success?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    abort("Test failed: #{spec_file}")
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            task :access_container do
         
     | 
| 
      
 31 
     | 
    
         
            +
              puts "Accessing a new rspec-runner-#{ruby_version} container..."
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              ruby_version = ENV.has_key?("DOCKER_RUBY_VERSION") ? ENV["DOCKER_RUBY_VERSION"] : "3.3"
         
     | 
| 
      
 34 
     | 
    
         
            +
              system("docker run -it --rm -v #{Dir.pwd}/lib:/app/lib -v #{Dir.pwd}/spec:/app/spec --entrypoint /bin/bash rspec-runner-#{ruby_version}")
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
    
        data/gems/rails.gemfile
    ADDED
    
    
| 
         @@ -0,0 +1,265 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Valid Config Options:
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            # This list is complete, but some are for developers of
         
     | 
| 
      
 6 
     | 
    
         
            +
            # scout_apm_logging itself. See the documentation at https://scoutapm.com/docs for
         
     | 
| 
      
 7 
     | 
    
         
            +
            # customer-focused documentation.
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # config_file - location of the scout_apm.yml configuration file
         
     | 
| 
      
 10 
     | 
    
         
            +
            # log_level          - log level for the internal library itself
         
     | 
| 
      
 11 
     | 
    
         
            +
            # log_stdout         - true or false.  If true, log to STDOUT
         
     | 
| 
      
 12 
     | 
    
         
            +
            # log_stderr         - true or false.  If true, log to STDERR
         
     | 
| 
      
 13 
     | 
    
         
            +
            # log_file_path      - either a directory or "STDOUT"
         
     | 
| 
      
 14 
     | 
    
         
            +
            # log_class          - the underlying class to use for logging.  Defaults to Ruby's Logger class
         
     | 
| 
      
 15 
     | 
    
         
            +
            # logs_monitor       - true or false.  If true, monitor logs
         
     | 
| 
      
 16 
     | 
    
         
            +
            # logs_monitored     - an array of log file paths to monitor. Overrides the default log destination detection
         
     | 
| 
      
 17 
     | 
    
         
            +
            # logs_ingest_key    - the ingest key to use for logs
         
     | 
| 
      
 18 
     | 
    
         
            +
            # logs_capture_level - the minimum log level to start capturing logs for
         
     | 
| 
      
 19 
     | 
    
         
            +
            # logs_config        - a hash of configuration options for merging into the collector's config
         
     | 
| 
      
 20 
     | 
    
         
            +
            # logs_reporting_endpoint - the endpoint to send logs to
         
     | 
| 
      
 21 
     | 
    
         
            +
            # logs_proxy_log_dir - the directory to store logs in for monitoring
         
     | 
| 
      
 22 
     | 
    
         
            +
            # manager_lock_file  - the location for obtaining an exclusive lock for running monitor manager
         
     | 
| 
      
 23 
     | 
    
         
            +
            # monitor_pid_file   - the location of the pid file for the monitor
         
     | 
| 
      
 24 
     | 
    
         
            +
            # monitor_state_file - the location of the state file for the monitor
         
     | 
| 
      
 25 
     | 
    
         
            +
            # monitor_interval   - the interval to check the collector healtcheck and for new state logs
         
     | 
| 
      
 26 
     | 
    
         
            +
            # monitor_interval_delay - the delay to wait before running the first monitor interval
         
     | 
| 
      
 27 
     | 
    
         
            +
            # collector_log_level - the log level for the collector
         
     | 
| 
      
 28 
     | 
    
         
            +
            # collector_sending_queue_storage_dir - the directory to store queue files
         
     | 
| 
      
 29 
     | 
    
         
            +
            # collector_offset_storage_dir - the directory to store offset files
         
     | 
| 
      
 30 
     | 
    
         
            +
            # collector_pid_file - the location of the pid file for the collector
         
     | 
| 
      
 31 
     | 
    
         
            +
            # collector_download_dir - the directory to store downloaded collector files
         
     | 
| 
      
 32 
     | 
    
         
            +
            # collector_config_file - the location of the config file for the collector
         
     | 
| 
      
 33 
     | 
    
         
            +
            # collector_version - the version of the collector to download
         
     | 
| 
      
 34 
     | 
    
         
            +
            # health_check_port - the port to use for the collector health check. Default is dynamically derived based on port availability
         
     | 
| 
      
 35 
     | 
    
         
            +
            #
         
     | 
| 
      
 36 
     | 
    
         
            +
            # Any of these config settings can be set with an environment variable prefixed
         
     | 
| 
      
 37 
     | 
    
         
            +
            # by SCOUT_ and uppercasing the key: SCOUT_LOG_LEVEL for instance.
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            module ScoutApm
         
     | 
| 
      
 40 
     | 
    
         
            +
              module Logging
         
     | 
| 
      
 41 
     | 
    
         
            +
                # Holds the configuration values for Scout APM Logging.
         
     | 
| 
      
 42 
     | 
    
         
            +
                class Config < ScoutApm::Config
         
     | 
| 
      
 43 
     | 
    
         
            +
                  KNOWN_CONFIG_OPTIONS = %w[
         
     | 
| 
      
 44 
     | 
    
         
            +
                    config_file
         
     | 
| 
      
 45 
     | 
    
         
            +
                    log_level
         
     | 
| 
      
 46 
     | 
    
         
            +
                    log_stderr
         
     | 
| 
      
 47 
     | 
    
         
            +
                    log_stdout
         
     | 
| 
      
 48 
     | 
    
         
            +
                    log_file_path
         
     | 
| 
      
 49 
     | 
    
         
            +
                    log_class
         
     | 
| 
      
 50 
     | 
    
         
            +
                    logs_monitor
         
     | 
| 
      
 51 
     | 
    
         
            +
                    logs_monitored
         
     | 
| 
      
 52 
     | 
    
         
            +
                    logs_ingest_key
         
     | 
| 
      
 53 
     | 
    
         
            +
                    logs_capture_level
         
     | 
| 
      
 54 
     | 
    
         
            +
                    logs_config
         
     | 
| 
      
 55 
     | 
    
         
            +
                    logs_reporting_endpoint
         
     | 
| 
      
 56 
     | 
    
         
            +
                    logs_proxy_log_dir
         
     | 
| 
      
 57 
     | 
    
         
            +
                    manager_lock_file
         
     | 
| 
      
 58 
     | 
    
         
            +
                    monitor_pid_file
         
     | 
| 
      
 59 
     | 
    
         
            +
                    monitor_state_file
         
     | 
| 
      
 60 
     | 
    
         
            +
                    monitor_interval
         
     | 
| 
      
 61 
     | 
    
         
            +
                    monitor_interval_delay
         
     | 
| 
      
 62 
     | 
    
         
            +
                    collector_sending_queue_storage_dir
         
     | 
| 
      
 63 
     | 
    
         
            +
                    collector_offset_storage_dir
         
     | 
| 
      
 64 
     | 
    
         
            +
                    collector_pid_file
         
     | 
| 
      
 65 
     | 
    
         
            +
                    collector_download_dir
         
     | 
| 
      
 66 
     | 
    
         
            +
                    collector_config_file
         
     | 
| 
      
 67 
     | 
    
         
            +
                    collector_log_level
         
     | 
| 
      
 68 
     | 
    
         
            +
                    collector_version
         
     | 
| 
      
 69 
     | 
    
         
            +
                    health_check_port
         
     | 
| 
      
 70 
     | 
    
         
            +
                  ].freeze
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  SETTING_COERCIONS = {
         
     | 
| 
      
 73 
     | 
    
         
            +
                    'logs_monitor' => BooleanCoercion.new,
         
     | 
| 
      
 74 
     | 
    
         
            +
                    'logs_monitored' => JsonCoercion.new,
         
     | 
| 
      
 75 
     | 
    
         
            +
                    'monitor_interval' => IntegerCoercion.new,
         
     | 
| 
      
 76 
     | 
    
         
            +
                    'monitor_interval_delay' => IntegerCoercion.new,
         
     | 
| 
      
 77 
     | 
    
         
            +
                    'health_check_port' => IntegerCoercion.new
         
     | 
| 
      
 78 
     | 
    
         
            +
                  }.freeze
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  # The bootstrapped, and initial config that we attach to the context. Will be swapped out by
         
     | 
| 
      
 81 
     | 
    
         
            +
                  # both the monitor and manager on initialization to the one with a file (which also has the dynamic
         
     | 
| 
      
 82 
     | 
    
         
            +
                  # and state configs).
         
     | 
| 
      
 83 
     | 
    
         
            +
                  def self.without_file(context)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    overlays = [
         
     | 
| 
      
 85 
     | 
    
         
            +
                      ConfigEnvironment.new,
         
     | 
| 
      
 86 
     | 
    
         
            +
                      ConfigDefaults.new,
         
     | 
| 
      
 87 
     | 
    
         
            +
                      ConfigNull.new
         
     | 
| 
      
 88 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 89 
     | 
    
         
            +
                    new(context, overlays)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  def self.with_file(context, file_path = nil, config = {})
         
     | 
| 
      
 93 
     | 
    
         
            +
                    overlays = [
         
     | 
| 
      
 94 
     | 
    
         
            +
                      ConfigEnvironment.new,
         
     | 
| 
      
 95 
     | 
    
         
            +
                      ConfigFile.new(context, file_path, config),
         
     | 
| 
      
 96 
     | 
    
         
            +
                      ConfigDynamic.new,
         
     | 
| 
      
 97 
     | 
    
         
            +
                      ConfigState.new(context),
         
     | 
| 
      
 98 
     | 
    
         
            +
                      ConfigDefaults.new,
         
     | 
| 
      
 99 
     | 
    
         
            +
                      ConfigNull.new
         
     | 
| 
      
 100 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 101 
     | 
    
         
            +
                    new(context, overlays)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  def state
         
     | 
| 
      
 105 
     | 
    
         
            +
                    @overlays.find { |overlay| overlay.is_a? ConfigState }
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  def value(key)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    unless KNOWN_CONFIG_OPTIONS.include?(key)
         
     | 
| 
      
 110 
     | 
    
         
            +
                      logger.debug("Requested looking up a unknown configuration key: #{key} (not a problem. Evaluate and add to config.rb)")
         
     | 
| 
      
 111 
     | 
    
         
            +
                    end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                    o = overlay_for_key(key)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    raw_value = if o
         
     | 
| 
      
 115 
     | 
    
         
            +
                                  o.value(key)
         
     | 
| 
      
 116 
     | 
    
         
            +
                                else
         
     | 
| 
      
 117 
     | 
    
         
            +
                                  # No overlay said it could handle this key, bail out with nil.
         
     | 
| 
      
 118 
     | 
    
         
            +
                                  nil
         
     | 
| 
      
 119 
     | 
    
         
            +
                                end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                    coercion = SETTING_COERCIONS.fetch(key, NullCoercion.new)
         
     | 
| 
      
 122 
     | 
    
         
            +
                    coercion.coerce(raw_value)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                  def all_settings
         
     | 
| 
      
 126 
     | 
    
         
            +
                    KNOWN_CONFIG_OPTIONS.inject([]) do |memo, key|
         
     | 
| 
      
 127 
     | 
    
         
            +
                      o = overlay_for_key(key)
         
     | 
| 
      
 128 
     | 
    
         
            +
                      memo << { key: key, value: value(key).inspect, source: o.name }
         
     | 
| 
      
 129 
     | 
    
         
            +
                    end
         
     | 
| 
      
 130 
     | 
    
         
            +
                  end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                  # Dynamically set state based on the application.
         
     | 
| 
      
 133 
     | 
    
         
            +
                  class ConfigDynamic
         
     | 
| 
      
 134 
     | 
    
         
            +
                    @values_to_set = {
         
     | 
| 
      
 135 
     | 
    
         
            +
                      'health_check_port': nil
         
     | 
| 
      
 136 
     | 
    
         
            +
                    }
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 139 
     | 
    
         
            +
                      attr_reader :values_to_set
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                      def set_value(key, value)
         
     | 
| 
      
 142 
     | 
    
         
            +
                        @values_to_set[key] = value
         
     | 
| 
      
 143 
     | 
    
         
            +
                      end
         
     | 
| 
      
 144 
     | 
    
         
            +
                    end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    def value(key)
         
     | 
| 
      
 147 
     | 
    
         
            +
                      self.class.values_to_set[key]
         
     | 
| 
      
 148 
     | 
    
         
            +
                    end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                    def has_key?(key)
         
     | 
| 
      
 151 
     | 
    
         
            +
                      self.class.values_to_set.key?(key)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                    def name
         
     | 
| 
      
 155 
     | 
    
         
            +
                      'dynamic'
         
     | 
| 
      
 156 
     | 
    
         
            +
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  # State that is persisted and communicated upon by multiple processes.
         
     | 
| 
      
 160 
     | 
    
         
            +
                  class ConfigState
         
     | 
| 
      
 161 
     | 
    
         
            +
                    @values_to_set = {
         
     | 
| 
      
 162 
     | 
    
         
            +
                      'logs_monitored': [],
         
     | 
| 
      
 163 
     | 
    
         
            +
                      'health_check_port': nil
         
     | 
| 
      
 164 
     | 
    
         
            +
                    }
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 167 
     | 
    
         
            +
                      attr_reader :values_to_set
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                      def set_value(key, value)
         
     | 
| 
      
 170 
     | 
    
         
            +
                        @values_to_set[key] = value
         
     | 
| 
      
 171 
     | 
    
         
            +
                      end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                      def get_values_to_set
         
     | 
| 
      
 174 
     | 
    
         
            +
                        @values_to_set.keys.map(&:to_s)
         
     | 
| 
      
 175 
     | 
    
         
            +
                      end
         
     | 
| 
      
 176 
     | 
    
         
            +
                    end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                    attr_reader :context, :state
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                    def initialize(context)
         
     | 
| 
      
 181 
     | 
    
         
            +
                      @context = context
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                      # Note, the config on the context we are passing in here comes from the Config.without_file. We
         
     | 
| 
      
 184 
     | 
    
         
            +
                      # won't be aware of a state file that was defined in a config file, but this would be a very
         
     | 
| 
      
 185 
     | 
    
         
            +
                      # rare thing to have happen as this is more of an internal config value.
         
     | 
| 
      
 186 
     | 
    
         
            +
                      @state = State.new(context)
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                      set_values_from_state
         
     | 
| 
      
 189 
     | 
    
         
            +
                    end
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
                    def value(key)
         
     | 
| 
      
 192 
     | 
    
         
            +
                      self.class.values_to_set[key]
         
     | 
| 
      
 193 
     | 
    
         
            +
                    end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                    def has_key?(key)
         
     | 
| 
      
 196 
     | 
    
         
            +
                      self.class.values_to_set.key?(key)
         
     | 
| 
      
 197 
     | 
    
         
            +
                    end
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                    def name
         
     | 
| 
      
 200 
     | 
    
         
            +
                      'state'
         
     | 
| 
      
 201 
     | 
    
         
            +
                    end
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                    def flush_state!
         
     | 
| 
      
 204 
     | 
    
         
            +
                      state.flush_to_file!
         
     | 
| 
      
 205 
     | 
    
         
            +
                    end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                    def add_log_locations!(updated_log_locations)
         
     | 
| 
      
 208 
     | 
    
         
            +
                      state.flush_to_file!(updated_log_locations)
         
     | 
| 
      
 209 
     | 
    
         
            +
                    end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                    private
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                    def set_values_from_state
         
     | 
| 
      
 214 
     | 
    
         
            +
                      data = state.load_state_from_file
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                      return unless data
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                      data.each do |key, value|
         
     | 
| 
      
 219 
     | 
    
         
            +
                        self.class.set_value(key, value)
         
     | 
| 
      
 220 
     | 
    
         
            +
                      end
         
     | 
| 
      
 221 
     | 
    
         
            +
                    end
         
     | 
| 
      
 222 
     | 
    
         
            +
                  end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                  # Defaults in case no config file has been found.
         
     | 
| 
      
 225 
     | 
    
         
            +
                  class ConfigDefaults
         
     | 
| 
      
 226 
     | 
    
         
            +
                    DEFAULTS = {
         
     | 
| 
      
 227 
     | 
    
         
            +
                      'log_level' => 'info',
         
     | 
| 
      
 228 
     | 
    
         
            +
                      'logs_monitored' => [],
         
     | 
| 
      
 229 
     | 
    
         
            +
                      'logs_capture_level' => 'debug',
         
     | 
| 
      
 230 
     | 
    
         
            +
                      'logs_reporting_endpoint' => 'https://otlp.telemetryhub.com:4317',
         
     | 
| 
      
 231 
     | 
    
         
            +
                      'logs_proxy_log_dir' => '/tmp/scout_apm/logs/',
         
     | 
| 
      
 232 
     | 
    
         
            +
                      'manager_lock_file' => '/tmp/scout_apm/monitor_lock_file.lock',
         
     | 
| 
      
 233 
     | 
    
         
            +
                      'monitor_pid_file' => '/tmp/scout_apm/scout_apm_log_monitor.pid',
         
     | 
| 
      
 234 
     | 
    
         
            +
                      'monitor_state_file' => '/tmp/scout_apm/scout_apm_log_monitor_state.json',
         
     | 
| 
      
 235 
     | 
    
         
            +
                      'monitor_interval' => 60,
         
     | 
| 
      
 236 
     | 
    
         
            +
                      'monitor_interval_delay' => 60,
         
     | 
| 
      
 237 
     | 
    
         
            +
                      'collector_log_level' => 'error',
         
     | 
| 
      
 238 
     | 
    
         
            +
                      'collector_offset_storage_dir' => '/tmp/scout_apm/file_storage/receiver/',
         
     | 
| 
      
 239 
     | 
    
         
            +
                      'collector_sending_queue_storage_dir' => '/tmp/scout_apm/file_storage/otc/',
         
     | 
| 
      
 240 
     | 
    
         
            +
                      'collector_pid_file' => '/tmp/scout_apm/scout_apm_otel_collector.pid',
         
     | 
| 
      
 241 
     | 
    
         
            +
                      'collector_download_dir' => '/tmp/scout_apm/',
         
     | 
| 
      
 242 
     | 
    
         
            +
                      'collector_config_file' => '/tmp/scout_apm/config.yml',
         
     | 
| 
      
 243 
     | 
    
         
            +
                      'collector_version' => '0.102.1'
         
     | 
| 
      
 244 
     | 
    
         
            +
                    }.freeze
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                    def value(key)
         
     | 
| 
      
 247 
     | 
    
         
            +
                      DEFAULTS[key]
         
     | 
| 
      
 248 
     | 
    
         
            +
                    end
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
                    def has_key?(key)
         
     | 
| 
      
 251 
     | 
    
         
            +
                      DEFAULTS.key?(key)
         
     | 
| 
      
 252 
     | 
    
         
            +
                    end
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
                    # Dyanmic/computed values are here, but not counted as user specified.
         
     | 
| 
      
 255 
     | 
    
         
            +
                    def any_keys_found?
         
     | 
| 
      
 256 
     | 
    
         
            +
                      false
         
     | 
| 
      
 257 
     | 
    
         
            +
                    end
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
                    def name
         
     | 
| 
      
 260 
     | 
    
         
            +
                      'defaults'
         
     | 
| 
      
 261 
     | 
    
         
            +
                    end
         
     | 
| 
      
 262 
     | 
    
         
            +
                  end
         
     | 
| 
      
 263 
     | 
    
         
            +
                end
         
     | 
| 
      
 264 
     | 
    
         
            +
              end
         
     | 
| 
      
 265 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ScoutApm
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Logging
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Contains context around Scout APM logging, such as environment, configuration, and the logger.
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Context
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # The root of the application.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_accessor :application_root
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # Initially start up without attempting to load a configuration file. We
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # need to be able to lookup configuration options like "application_root"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # which would then in turn influence where the yaml configuration file is
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # located
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # Later in initialization, we set config= to include the file.
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @logger = LoggerFactory.build_minimal_logger
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def config
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @config ||= Config.without_file(self)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def environment
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @environment ||= ScoutApm::Environment.instance
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def logger
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @logger ||= LoggerFactory.build(config, environment, application_root)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def config=(config)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @config = config
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    @logger = nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Create a logger based on the configuration settings.
         
     | 
| 
      
 40 
     | 
    
         
            +
                class LoggerFactory
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def self.build(config, environment, application_root = nil)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    root = application_root || environment.root
         
     | 
| 
      
 43 
     | 
    
         
            +
                    Logger.new(root,
         
     | 
| 
      
 44 
     | 
    
         
            +
                               {
         
     | 
| 
      
 45 
     | 
    
         
            +
                                 log_level: config.value('log_level'),
         
     | 
| 
      
 46 
     | 
    
         
            +
                                 log_file_path: config.value('log_file_path'),
         
     | 
| 
      
 47 
     | 
    
         
            +
                                 stdout: config.value('log_stdout') || environment.platform_integration.log_to_stdout?,
         
     | 
| 
      
 48 
     | 
    
         
            +
                                 stderr: config.value('log_stderr'),
         
     | 
| 
      
 49 
     | 
    
         
            +
                                 logger_class: config.value('log_class')
         
     | 
| 
      
 50 
     | 
    
         
            +
                               })
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def self.build_minimal_logger
         
     | 
| 
      
 54 
     | 
    
         
            +
                    Logger.new(nil, stdout: true)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ScoutApm
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Logging
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Custom internal logger for ScoutApm Logging.
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Logger < ScoutApm::Logger
         
     | 
| 
      
 7 
     | 
    
         
            +
                  private
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def determine_log_destination
         
     | 
| 
      
 10 
     | 
    
         
            +
                    case true
         
     | 
| 
      
 11 
     | 
    
         
            +
                    when stdout?
         
     | 
| 
      
 12 
     | 
    
         
            +
                      $stdout
         
     | 
| 
      
 13 
     | 
    
         
            +
                    when stderr?
         
     | 
| 
      
 14 
     | 
    
         
            +
                      $stderr
         
     | 
| 
      
 15 
     | 
    
         
            +
                    when validate_path(@opts[:log_file])
         
     | 
| 
      
 16 
     | 
    
         
            +
                      @opts[:log_file]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    when validate_path("#{log_file_path}/scout_apm_logging.log")
         
     | 
| 
      
 18 
     | 
    
         
            +
                      "#{log_file_path}/scout_apm_logging.log"
         
     | 
| 
      
 19 
     | 
    
         
            +
                    else
         
     | 
| 
      
 20 
     | 
    
         
            +
                      # Safe fallback
         
     | 
| 
      
 21 
     | 
    
         
            +
                      $stdout
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'logger'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative './swap'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative './proxy'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module ScoutApm
         
     | 
| 
      
 9 
     | 
    
         
            +
              module Logging
         
     | 
| 
      
 10 
     | 
    
         
            +
                module Loggers
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # Will capture the log destinations from the application's loggers.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  class Capture
         
     | 
| 
      
 13 
     | 
    
         
            +
                    attr_reader :context
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def initialize(context)
         
     | 
| 
      
 16 
     | 
    
         
            +
                      @context = context
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    def capture_log_locations! # rubocop:disable Metrics/AbcSize
         
     | 
| 
      
 20 
     | 
    
         
            +
                      logger_instances << Rails.logger if defined?(Rails)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      logger_instances << Sidekiq.logger if defined?(Sidekiq)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      logger_instances << ObjectSpace.each_object(::ScoutTestLogger).to_a if defined?(::ScoutTestLogger)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                      # Swap in our logger for each logger instance, in conjunction with the original class.
         
     | 
| 
      
 25 
     | 
    
         
            +
                      updated_log_locations = logger_instances.compact.flatten.map do |logger|
         
     | 
| 
      
 26 
     | 
    
         
            +
                        swapped_in_location(logger)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                      context.config.state.add_log_locations!(updated_log_locations)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    private
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def logger_instances
         
     | 
| 
      
 35 
     | 
    
         
            +
                      @logger_instances ||= []
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    def swapped_in_location(log_instance)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      swap = Swap.new(context, log_instance)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      swap.update_logger!
         
     | 
| 
      
 41 
     | 
    
         
            +
                      swap.log_location
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     |