diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..08ba582 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '[BUG] ' +labels: 'bug' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..fd4ace0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: bundler + directory: "/" + schedule: + interval: monthly + open-pull-requests-limit: 10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab528dc..cd9510c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,13 +1,8 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake -# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby - -name: Tests +name: Build on: + push: + branches: ["master", "main"] pull_request: branches: ["**"] @@ -15,6 +10,21 @@ permissions: contents: read jobs: + rubocop: + name: RuboCop + runs-on: ubuntu-latest + env: + BUNDLE_ONLY: rubocop + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Ruby and install gems + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.3.0 + bundler-cache: true + - name: Run Rubocop + run: bundle exec rubocop --parallel test: runs-on: ubuntu-latest strategy: diff --git a/.rubocop.yml b/.rubocop.yml index e4675a9..f590b6e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,6 +5,7 @@ AllCops: - "treblle-ruby.gemspec" - "Gemfile.lock" - "gemfiles/*" + - "vendor/**/*" require: - rubocop-performance @@ -126,3 +127,6 @@ Style/StringConcatenation: Style/DocumentDynamicEvalDefinition: Enabled: false + +Style/Documentation: + Enabled: false diff --git a/Gemfile b/Gemfile index 78e7f41..b1033a4 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,13 @@ gem "appraisal" gem 'rails' gem 'rake' gem 'rspec' -gem 'rubocop', require: false -gem 'rubocop-performance', require: false -gem 'simplecov', require: false, group: :test gem 'webmock' + +group 'rubocop' do + gem 'rubocop', require: false + gem 'rubocop-performance', require: false +end + +group 'test' do + gem 'simplecov', require: false +end diff --git a/Gemfile.lock b/Gemfile.lock index 362d7b5..397a927 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,15 +81,15 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) appraisal (2.5.0) bundler rake thor (>= 0.14.0) ast (2.4.2) base64 (0.2.0) - bigdecimal (3.1.6) + bigdecimal (3.1.8) builder (3.2.4) concurrent-ruby (1.2.3) connection_pool (2.4.1) @@ -105,14 +105,14 @@ GEM erubi (1.12.0) globalid (1.2.1) activesupport (>= 6.1) - hashdiff (1.1.0) + hashdiff (1.1.1) i18n (1.14.1) concurrent-ruby (~> 1.0) io-console (0.7.2) irb (1.11.2) rdoc reline (>= 0.4.2) - json (2.7.1) + json (2.7.2) language_server-protocol (3.17.0.3) loofah (2.22.0) crass (~> 1.0.2) @@ -148,14 +148,14 @@ GEM racc (~> 1.4) nokogiri (1.16.2-x86_64-linux) racc (~> 1.4) - parallel (1.24.0) - parser (3.3.0.5) + parallel (1.26.3) + parser (3.3.5.0) ast (~> 2.4.1) racc psych (5.1.2) stringio - public_suffix (5.0.4) - racc (1.7.3) + public_suffix (6.0.1) + racc (1.8.1) rack (3.0.9) rack-session (2.0.0) rack (>= 3.0.0) @@ -194,13 +194,13 @@ GEM thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.1.0) + rake (13.2.1) rdoc (6.6.2) psych (>= 4.0.0) - regexp_parser (2.9.0) + regexp_parser (2.9.2) reline (0.4.2) io-console (~> 0.5) - rexml (3.2.6) + rexml (3.3.8) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) @@ -214,22 +214,21 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-support (3.13.0) - rubocop (1.60.2) + rubocop (1.66.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.30.0, < 2.0) + regexp_parser (>= 2.4, < 3.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.30.0) - parser (>= 3.2.1.0) - rubocop-performance (1.20.2) + rubocop-ast (1.32.3) + parser (>= 3.3.1.0) + rubocop-performance (1.22.1) rubocop (>= 1.48.1, < 2.0) - rubocop-ast (>= 1.30.0, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) simplecov (0.22.0) @@ -243,8 +242,8 @@ GEM timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) - webmock (3.20.0) + unicode-display_width (2.6.0) + webmock (3.23.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) diff --git a/README.md b/README.md index 3c9921d..132eb72 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ <div align="center"> # Treblle +[![Build Status](https://github.com/Treblle/treblle-ruby/workflows/Tests/badge.svg)](https://github.com/Treblle/treblle-ruby/actions) [![Gem Version](https://badge.fury.io/rb/treblle.svg)](https://badge.fury.io/rb/treblle) <a href="https://docs.treblle.com/en/integrations" target="_blank">Integrations</a> <span>  •  </span> diff --git a/lib/treblle/errors/configuration_errors.rb b/lib/treblle/errors/configuration_errors.rb index 73d3cec..9489a97 100644 --- a/lib/treblle/errors/configuration_errors.rb +++ b/lib/treblle/errors/configuration_errors.rb @@ -2,19 +2,19 @@ module Treblle module Errors class ConfigurationError < StandardError def initialize(msg = "Configuration error") - super(msg) + super end end class MissingApiKeyError < ConfigurationError def initialize(msg = "API key is missing") - super(msg) + super end end class MissingProjectIdError < ConfigurationError def initialize(msg = "Project ID is missing") - super(msg) + super end end end diff --git a/lib/treblle/generate_payload.rb b/lib/treblle/generate_payload.rb index 64f5c1e..1abb354 100644 --- a/lib/treblle/generate_payload.rb +++ b/lib/treblle/generate_payload.rb @@ -8,10 +8,11 @@ class GeneratePayload SDK_LANG = 'ruby' TIME_FORMAT = '%Y-%m-%d %H:%M:%S' - def initialize(request:, response:, started_at:, configuration: Treblle.configuration) + def initialize(request:, response:, started_at:, load_time:, configuration: Treblle.configuration) @request = request @response = response @started_at = started_at + @load_time = load_time @configuration = configuration end @@ -21,18 +22,14 @@ def call private - attr_reader :request, :response, :started_at, :configuration + attr_reader :request, :response, :started_at, :load_time, :configuration def sanitize(body) Utils::HashSanitizer.sanitize(body, configuration.sensitive_attrs) end def timestamp - started_at.strftime(TIME_FORMAT) - end - - def load_time - Time.now - started_at + started_at.utc.strftime(TIME_FORMAT) end def payload diff --git a/lib/treblle/middleware.rb b/lib/treblle/middleware.rb index 28174ac..3cd6add 100644 --- a/lib/treblle/middleware.rb +++ b/lib/treblle/middleware.rb @@ -29,18 +29,25 @@ def call(env) attr_reader :configuration def call_with_treblle_monitoring(env) - started_at = Time.now + started_at = Time.now.utc response = @app.call(env) - handle_monitoring(env, response, started_at) + + load_time = Time.now.utc - started_at + handle_monitoring(env, response, started_at, load_time) response end - def handle_monitoring(env, rack_response, started_at) + def handle_monitoring(env, rack_response, started_at, load_time) request = RequestBuilder.new(env).build response = ResponseBuilder.new(rack_response).build - payload = GeneratePayload.new(request: request, response: response, started_at: started_at).call + payload = GeneratePayload.new( + request: request, + response: response, + started_at: started_at, + load_time: load_time + ).call Dispatcher.new(payload: payload).call rescue StandardError => e diff --git a/lib/treblle/utils/hash_sanitizer.rb b/lib/treblle/utils/hash_sanitizer.rb index 93c5f35..49a7206 100644 --- a/lib/treblle/utils/hash_sanitizer.rb +++ b/lib/treblle/utils/hash_sanitizer.rb @@ -32,7 +32,7 @@ def sanitize_array(array, sensitive_attrs) end def sanitize_value(key, value, sensitive_attrs) - sensitive_attrs.include?(key.to_s) ? '*' * value.to_s.length : value + sensitive_attrs.include?(key.to_s) ? "*****" : value end end end diff --git a/spec/lib/utils/hash_sanitizer_spec.rb b/spec/lib/utils/hash_sanitizer_spec.rb index bc100ab..7594cc7 100644 --- a/spec/lib/utils/hash_sanitizer_spec.rb +++ b/spec/lib/utils/hash_sanitizer_spec.rb @@ -33,7 +33,7 @@ context 'when given a hash with sensitive attributes' do let(:input_hash) { { name: 'John', password: 'secretpassword', credit_card: '1234567890123456' } } - let(:expected_subject) { { name: 'John', password: '**************', credit_card: '****************' } } + let(:expected_subject) { { name: 'John', password: '*****', credit_card: '*****' } } it 'replaces sensitive attribute values with asterisks' do expect(subject).to eq(expected_subject) @@ -42,7 +42,7 @@ context 'when given a hash with nested hashes' do let(:input_hash) { { user: { name: 'John', password: 'secretpassword' } } } - let(:expected_subject) { { user: { name: 'John', password: '**************' } } } + let(:expected_subject) { { user: { name: 'John', password: '*****' } } } it 'replaces sensitive attribute values with asterisks' do expect(subject).to eq(expected_subject) @@ -54,7 +54,7 @@ { users: [{ name: 'John', password: 'secretpassword' }, { name: 'Jane', password: 'anotherpassword' }] } end let(:expected_subject) do - { users: [{ name: 'John', password: '**************' }, { name: 'Jane', password: '***************' }] } + { users: [{ name: 'John', password: '*****' }, { name: 'Jane', password: '*****' }] } end it 'replaces sensitive attribute values with asterisks' do