diff --git a/.dev_to/compose.yml b/.dev_to/compose.yml
index 6db3e51f..557748df 100644
--- a/.dev_to/compose.yml
+++ b/.dev_to/compose.yml
@@ -9,6 +9,7 @@ x-app: &app
environment: &env
NODE_ENV: ${NODE_ENV:-development}
RAILS_ENV: ${RAILS_ENV:-development}
+ RACK_ENV: ${RACK_ENV:-development}
tmpfs:
- /tmp
- /app/tmp/pids
diff --git a/.gitignore b/.gitignore
index 53c5b710..db33e9f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,3 +56,6 @@ package-lock.json
#sitemap
/public/sitemap.xml.gz
+
+#newrelic
+newrelic-infra/newrelic-infra.yml
diff --git a/.ruby-version b/.ruby-version
index bea438e9..47b322c9 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-3.3.1
+3.4.1
diff --git a/Envfile b/Envfile
index 944a3fac..2820e85a 100644
--- a/Envfile
+++ b/Envfile
@@ -53,6 +53,9 @@ variable :ALGOLIASEARCH_API_KEY, :String, default: only_in_test
variable :ALGOLIASEARCH_APPLICATION_ID, :String, default: only_in_test
variable :ALGOLIASEARCH_SEARCH_ONLY_KEY, :String, default: only_in_test
+# NewRelic
+variable :NEW_RELIC_LICENSE_KEY, :String, default: "Optional"
+
# AWS for images storages
variable :AWS_ID, :String, default: "Optional"
variable :AWS_SECRET, :String, default: "Optional"
diff --git a/Gemfile b/Gemfile
index b107eb92..300649f5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,6 +13,10 @@ group :production do
gem "nakayoshi_fork"
end
+gem 'newrelic_rpm'
+gem 'newrelic-infinite_tracing'
+gem 'rack-mini-profiler'
+
gem "psych", "< 4"
gem "skylight"
@@ -105,7 +109,7 @@ gem "validate_url", "~> 1.0"
gem "webpacker", "~> 3.6"
gem "webpush", "~> 0.3"
-group :development do
+group :development, :local_production do
gem "better_errors", "~> 2.5"
gem "binding_of_caller", "~> 0.8"
gem "brakeman", "~> 4.4", require: false
@@ -119,7 +123,7 @@ group :development do
gem "web-console", "~> 3.7"
end
-group :development, :test do
+group :development, :test, :local_production do
gem "capybara", "~> 3.13"
gem "derailed", "~> 0.1"
gem "erb_lint", "~> 0.0", require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 130d7472..27571167 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -505,12 +505,22 @@ GEM
google-apis-core (>= 0.11.0, < 2.a)
google-apis-discovery_v1 (~> 0.5)
thor (>= 0.20, < 2.a)
+ google-protobuf (3.25.6-aarch64-linux)
+ google-protobuf (3.25.6-x86_64-linux)
+ googleapis-common-protos-types (1.18.0)
+ google-protobuf (>= 3.18, < 5.a)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
+ grpc (1.65.2-aarch64-linux)
+ google-protobuf (>= 3.25, < 5.0)
+ googleapis-common-protos-types (~> 1.0)
+ grpc (1.65.2-x86_64-linux)
+ google-protobuf (>= 3.25, < 5.0)
+ googleapis-common-protos-types (~> 1.0)
guard (2.19.1)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
@@ -646,9 +656,16 @@ GEM
net-smtp (0.5.1)
net-protocol
netrc (0.11.0)
+ newrelic-infinite_tracing (9.17.0)
+ google-protobuf (< 4.0)
+ grpc (~> 1.34)
+ newrelic_rpm (= 9.17.0)
+ newrelic_rpm (9.17.0)
nio4r (2.7.4)
nokogiri (1.15.7-aarch64-linux)
racc (~> 1.4)
+ nokogiri (1.15.7-x86_64-linux)
+ racc (~> 1.4)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
@@ -726,6 +743,8 @@ GEM
rack (2.2.11)
rack-host-redirect (1.3.0)
rack
+ rack-mini-profiler (3.3.1)
+ rack (>= 1.2.0)
rack-protection (2.2.4)
rack
rack-proxy (0.7.7)
@@ -1011,6 +1030,7 @@ GEM
PLATFORMS
aarch64-linux
+ x86_64-linux
DEPENDENCIES
actionpack-action_caching (~> 1.2)
@@ -1081,6 +1101,8 @@ DEPENDENCIES
liquid (~> 4.0)
memory_profiler (~> 0.9)
nakayoshi_fork
+ newrelic-infinite_tracing
+ newrelic_rpm
nokogiri (~> 1.10)
octokit (~> 4.13)
omniauth (~> 1.9)
@@ -1098,6 +1120,7 @@ DEPENDENCIES
pusher (~> 1.3)
pusher-push-notifications (~> 1.0)
rack-host-redirect (~> 1.3)
+ rack-mini-profiler
rack-timeout (~> 0.5)
rails (~> 5.1.6)
rails-assets-airbrake-js-client (~> 1.5)!
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index fdad0526..195c8de6 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -83,7 +83,7 @@ def icon_url(name)
end
def cloudinary(url, width = nil, _quality = 80, _format = "jpg")
- return url if Rails.env.development? && (url.blank? || url.exclude?("http"))
+ return url if (Rails.env.development? || Rails.env.local_production?) && (url.blank? || url.exclude?("http"))
service_path = "https://res.cloudinary.com/practicaldev/image/fetch"
@@ -101,7 +101,7 @@ def cloudinary(url, width = nil, _quality = 80, _format = "jpg")
def cloud_cover_url(url)
return if url.blank?
return asset_path("triple-unicorn") if Rails.env.test?
- return url if Rails.env.development?
+ return url if (Rails.env.development? || Rails.env.local_production?)
width = 1000
height = 420
diff --git a/app/observers/article_observer.rb b/app/observers/article_observer.rb
index 17192106..ac3ec075 100644
--- a/app/observers/article_observer.rb
+++ b/app/observers/article_observer.rb
@@ -1,6 +1,6 @@
class ArticleObserver < ApplicationObserver
def after_save(article)
- return if Rails.env.development?
+ return if (Rails.env.development? || Rails.env.local_production?)
if article.published && article.published_at > 30.seconds.ago
SlackBot.delay.ping "New Article Published: #{article.title}\nhttps://dev.to#{article.path}",
diff --git a/app/observers/comment_observer.rb b/app/observers/comment_observer.rb
index 410a0029..3d282fc7 100644
--- a/app/observers/comment_observer.rb
+++ b/app/observers/comment_observer.rb
@@ -1,6 +1,6 @@
class CommentObserver < ApplicationObserver
def after_save(comment)
- return if Rails.env.development?
+ return if (Rails.env.development? || Rails.env.local_production?)
warned_user_ping(comment)
rescue StandardError
diff --git a/app/observers/organization_observer.rb b/app/observers/organization_observer.rb
index 5fb91cd0..27f3c7ba 100644
--- a/app/observers/organization_observer.rb
+++ b/app/observers/organization_observer.rb
@@ -1,6 +1,6 @@
class OrganizationObserver < ActiveRecord::Observer
def after_create(organization)
- return if Rails.env.development?
+ return if (Rails.env.development? || Rails.env.local_production?)
SlackBot.delay.ping(
"New Org Created: #{organization.name}\nhttps://dev.to/#{organization.username}",
diff --git a/app/views/stories/_main_stories_feed.html.erb b/app/views/stories/_main_stories_feed.html.erb
index b6cd0a65..3e175010 100644
--- a/app/views/stories/_main_stories_feed.html.erb
+++ b/app/views/stories/_main_stories_feed.html.erb
@@ -55,7 +55,9 @@
<% if !user_signed_in? && i == 4 %>
<%= render "stories/sign_in_invitation" %>
<% end %>
- <%= render "articles/single_story", story: story %>
+ <% cache story do %>
+ <%= render "articles/single_story", story: story %>
+ <% end %>
<% end %>
<% end %>
<% if @stories.size > 1 %>
diff --git a/case-study.md b/case-study.md
new file mode 100644
index 00000000..6ded8d59
--- /dev/null
+++ b/case-study.md
@@ -0,0 +1,233 @@
+# Case Strudy
+
+## Подготовка
+
+- [x] запустить проект
+- [x] настроить NewRelic (docker compose -f docker-compose.yaml up -d)
+- [x] настроить rack-mini-profiler
+- [x] для нагрузки подготовил siege
+- [x] local_production
+- [] использовать альтернативу NewRelic
+
+## Оптимизация
+
+Сразу для того чтобы сравнить решил сравнивать вывод в NewRelic и RMP(по подробности данным всё же RMP более удобный, меньше повторяющейся информации и больше подробностей).
+
+Получил что при первой загруку страница запускалась где-то 3252.06 ms, при повторной ускорилось до 1300 - 1600.1 ms, из-за разных кэшей браузера и уже настроенных кэшей приложения.
+
+через RMP видно что проблема рендерингом main_stories_feed, а точнее _single_story
+
+
+```
+/ (1362.6 ms)
+
+event duration (ms) from start (ms) query time (ms)
+GET http://localhost:3000/ 36.3 +0.0
+ Executing: stories#index 103.1 +17.0 2 sql 5.1
+ Rendering: layouts/application.html.erb 169.8 +120.7
+ Rendering: articles/index.html.erb 124.4 +147.2 2 sql 23.9
+ Rendering: articles/_sidebar.html.erb 27.7 +162.3
+ Rendering: stories/_main_stories_feed.html.er... 368.9 +257.5
+ Rendering: articles/_single_story.html.erb 21.6 +275.3
+ Rendering: articles/_single_story.html.erb 18.3 +312.3
+ Rendering: articles/_single_story.html.erb 16.1 +344.4
+ Rendering: articles/_single_story.html.erb 16.8 +373.9
+ Rendering: articles/_single_story.html.erb 18.8 +419.8
+ Rendering: articles/_single_story.html.erb 59.2 +452.3
+ Rendering: articles/_single_story.html.erb 17.6 +532.9
+ Rendering: articles/_single_story.html.erb 19.3 +566.2
+ Rendering: articles/_single_story.html.erb 16.7 +599.8
+ Rendering: articles/_single_story.html.erb 15.7 +630.7
+ Rendering: articles/_single_story.html.erb 23.4 +660.1
+ Rendering: articles/_single_story.html.erb 21.3 +699.0
+ Rendering: articles/_single_story.html.erb 17.6 +742.9
+ Rendering: articles/_single_story.html.erb 19.5 +774.9
+ Rendering: articles/_single_story.html.erb 18.3 +810.2
+ Rendering: articles/_single_story.html.erb 17.9 +844.7
+ Rendering: articles/_single_story.html.erb 17.9 +876.7
+ Rendering: articles/_single_story.html.erb 17.4 +908.2
+ Rendering: articles/_single_story.html.erb 17.7 +939.9
+ Rendering: articles/_single_story.html.erb 16.1 +972.5
+ Rendering: articles/_single_story.html.erb 16.0 +1002.6
+ Rendering: articles/_single_story.html.erb 16.4 +1031.2
+ Rendering: articles/_single_story.html.erb 18.0 +1061.9
+ Rendering: articles/_single_story.html.erb 18.1 +1096.4
+ Rendering: articles/_sidebar_additional.html.... 28.2 +1128.8
+ Rendering: layouts/_styles.html.erb 14.6 +1200.4
+show time with childrensnapshots2.1 % in sql
+```
+
+
+при нагрузке через ab, сразу отваливается по таймауту, результаты получит не получилось.
+
+
+```
+romaS:~/ $ ab -n 100 -c 5 127.0.0.1:3000/
+This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
+Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
+Licensed to The Apache Software Foundation, http://www.apache.org/
+
+Benchmarking 127.0.0.1 (be patient)...apr_pollset_poll: The timeout specified has expired (70007)
+```
+
+
+
+Посмотревчто можно сделать, и учитывая совет из задачи мы понимаем что нам позволительно закэшировать `<%= render "articles/single_story", story: story %>`.
+Проверим эту гипотезу, добавляем кэширование
+
+
+Как результат первая загрузка не поменялас в среднем как и было 3252.06 ms, но при этом любая повторная загрузка уже выполняется в среднем за 588 ms. Что довольно силь что в 2.2 быстрее чем без использования кэшей. Так же успешно удалось назузить через `ab -n 100 -c 5 127.0.0.1:3000/`
+
+
+
+```
+
+ (588.4 ms)
+event duration (ms) from start (ms) query time (ms)
+GET http://localhost:3000/ 28.9 +0.0
+ Executing: stories#index 94.8 +10.0 2 sql 3.7
+ Rendering: layouts/application.html.erb 197.5 +105.2
+ Rendering: articles/index.html.erb 114.0 +139.3 2 sql 16.0
+ Rendering: articles/_sidebar.html.erb 31.6 +156.4
+ Rendering: stories/_main_stories_feed.html.er... 77.7 +242.8
+ Rendering: articles/_sidebar_additional.html.... 27.8 +335.2
+ Rendering: layouts/_styles.html.erb 14.6 +407.4
+show time with childrensnapshots3.3 % in sql
+
+```
+
+```
+
+romaS:~/ $ ab -n 100 -c 5 127.0.0.1:3000/
+
+This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
+Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
+Licensed to The Apache Software Foundation, http://www.apache.org/
+
+Benchmarking 127.0.0.1 (be patient).....done
+
+
+Server Software:
+Server Hostname: 127.0.0.1
+Server Port: 3000
+
+Document Path: /
+Document Length: 158268 bytes
+
+Concurrency Level: 5
+Time taken for tests: 209.115 seconds
+Complete requests: 100
+Failed requests: 99
+ (Connect: 0, Receive: 0, Length: 99, Exceptions: 0)
+Total transferred: 15946689 bytes
+HTML transferred: 15846641 bytes
+Requests per second: 0.48 [#/sec] (mean)
+Time per request: 10455.725 [ms] (mean)
+Time per request: 2091.145 [ms] (mean, across all concurrent requests)
+Transfer rate: 74.47 [Kbytes/sec] received
+
+Connection Times (ms)
+ min mean[+/-sd] median max
+Connect: 0 0 0.0 0 0
+Processing: 1701 10294 7288.4 8318 43677
+Waiting: 1697 10285 7288.8 8297 43675
+Total: 1701 10294 7288.5 8318 43677
+
+Percentage of the requests served within a certain time (ms)
+ 50% 8318
+ 66% 8570
+ 75% 9021
+ 80% 9435
+ 90% 15895
+ 95% 31402
+ 98% 43428
+ 99% 43677
+ 100% 43677 (longest request)
+```
+
+
+
+## Заключение
+Как вердикт проверка теории о использовании кэшей для `articles/single_story` принесла свои результаты и ускорила повторные загрузки страницы в 2 раза.
+
+
+
+
+# Доп подкючение local_production
+
+При создании local_production окружении и использовании его, видны следующие улучшения максимально приближённые к продовому окруэениею.
+ - время загрузки посторной страницы занимает теперь не 588.4 ms, а 129 ms
+ - при нагрузки через `ab -n 100 -c 5 127.0.0.1:3000/`, уменьшилось в 10 раз среднее время по всем показателям
+ было
+ ```
+ Time per request: 10455.725 [ms] (mean)
+ Time per request: 2091.145 [ms] (mean, across all concurrent requests)
+ ```
+ стало
+ ```
+ Time per request: 1043.882 [ms] (mean)
+ Time per request: 208.776 [ms] (mean, across all concurrent requests)
+ ```
+
+
+```
+/ (129.9 ms)
+event duration (ms) from start (ms) query time (ms)
+GET http://localhost:3000/ 46.0 +0.0
+ Executing: stories#index -29.6 +15.0 2 sql 4.0
+ Rendering: articles/index.html.erb 46.0 +39.4 2 sql 22.6
+ Rendering: stories/_main_stories_feed.html.er... 7.1 +85.7
+ Rendering: layouts/application.html.erb 58.8 +40.0
+show time with childrensnapshots20.5 % in sql
+client event duration (ms) from start (ms)
+Response 2.0 +160.0
+sharemore show trivial
+```
+
+```
+romaS:.dev_to/ (master✗) $ ab -n 100 -c 5 127.0.0.1:3000/
+This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
+Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
+Licensed to The Apache Software Foundation, http://www.apache.org/
+
+Benchmarking 127.0.0.1 (be patient).....done
+
+
+Server Software:
+Server Hostname: 127.0.0.1
+Server Port: 3000
+
+Document Path: /
+Document Length: 129969 bytes
+
+Concurrency Level: 5
+Time taken for tests: 20.878 seconds
+Complete requests: 100
+Failed requests: 99
+ (Connect: 0, Receive: 0, Length: 99, Exceptions: 0)
+Total transferred: 13115169 bytes
+HTML transferred: 13014935 bytes
+Requests per second: 4.79 [#/sec] (mean)
+Time per request: 1043.882 [ms] (mean)
+Time per request: 208.776 [ms] (mean, across all concurrent requests)
+Transfer rate: 613.47 [Kbytes/sec] received
+
+Connection Times (ms)
+ min mean[+/-sd] median max
+Connect: 0 0 0.0 0 0
+Processing: 394 968 548.3 787 2999
+Waiting: 392 958 549.7 779 2986
+Total: 394 968 548.3 787 2999
+
+Percentage of the requests served within a certain time (ms)
+ 50% 787
+ 66% 911
+ 75% 1017
+ 80% 1223
+ 90% 1844
+ 95% 2187
+ 98% 2959
+ 99% 2999
+ 100% 2999 (longest request)
+```
+
\ No newline at end of file
diff --git a/config/environments/development.rb b/config/environments/development.rb
index ad3b97cb..a4ff2ae4 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -98,6 +98,7 @@ def yarn_integrity_enabled?
config.after_initialize do
Bullet.enable = true
Bullet.console = true
+ Rack::MiniProfiler.config.authorization_mode = :allow_all
end
end
diff --git a/config/environments/local_production.rb b/config/environments/local_production.rb
new file mode 100644
index 00000000..ef39dabb
--- /dev/null
+++ b/config/environments/local_production.rb
@@ -0,0 +1,108 @@
+# rubocop:disable Metrics/BlockLength
+#
+def yarn_integrity_enabled?
+ ENV.fetch("YARN_INTEGRITY_ENABLED", "true") == "true"
+end
+
+Rails.application.configure do
+ # Verifies that versions and hashed value of the package contents in the project's package.json
+ config.webpacker.check_yarn_integrity = yarn_integrity_enabled?
+
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = true
+
+ # Do not eager load code on boot.
+ config.eager_load = true
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+
+ # Enable/disable caching. By default caching is disabled.
+ if Rails.root.join("tmp/caching-dev.txt").exist?
+ config.action_controller.perform_caching = true
+
+ config.cache_store = :memory_store
+ config.public_file_server.headers = {
+ "Cache-Control" => "public, max-age=172800"
+ }
+ else
+ config.action_controller.perform_caching = false
+
+ config.cache_store = :null_store
+ end
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+ # Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
+ config.assets.debug = false
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = false
+ config.assets_compile = false
+
+ # Supress logger output for asset requests.
+ config.assets.quiet = true
+
+ # Adds additional error checking when serving assets at runtime.
+ # Checks for improperly declared sprockets dependencies.
+ # Raises helpful error messages.
+ config.assets.raise_runtime_errors = true
+
+ config.action_mailer.perform_caching = false
+
+ config.web_console.development_only = false
+
+ config.app_domain = "localhost:3000"
+
+ config.action_mailer.default_url_options = { host: "localhost:3000" }
+ config.action_mailer.delivery_method = :smtp
+ config.action_mailer.perform_deliveries = true
+ config.action_mailer.default_url_options = { host: config.app_domain }
+ config.action_mailer.smtp_settings = {
+ address: "smtp.gmail.com",
+ port: "587",
+ enable_starttls_auto: true,
+ user_name: '<%= ENV["DEVELOPMENT_EMAIL_USERNAME"] %>',
+ password: '<%= ENV["DEVELOPMENT_EMAIL_PASSWORD"] %>',
+ authentication: :plain,
+ domain: "localhost:3000"
+ }
+
+ config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews"
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+
+ config.public_file_server.enabled = true
+
+ config.file_watcher = ActiveSupport::EventedFileUpdateChecker
+
+ # Install the Timber.io logger
+ send_logs_to_timber = ENV["SEND_LOGS_TO_TIMBER"] || "false" # <---- set to false to stop sending dev logs to Timber.io
+ log_device = send_logs_to_timber == "true" ? Timber::LogDevices::HTTP.new(ENV["TIMBER"]) : STDOUT
+ logger = Timber::Logger.new(log_device)
+ logger.level = config.log_level
+ config.logger = ActiveSupport::TaggedLogging.new(logger)
+
+ config.after_initialize do
+ Bullet.enable = true
+ Bullet.console = true
+ Rack::MiniProfiler.config.authorization_mode = :allow_all
+ end
+end
+
+# rubocop:enable Metrics/BlockLength
diff --git a/config/initializers/airbrake.rb b/config/initializers/airbrake.rb
index 0a3fffc7..c530ddc8 100644
--- a/config/initializers/airbrake.rb
+++ b/config/initializers/airbrake.rb
@@ -41,7 +41,7 @@
# environments.
# NOTE: This option *does not* work if you don't set the 'environment' option.
# https://github.com/airbrake/airbrake-ruby#ignore_environments
- c.ignore_environments = %w[test development]
+ c.ignore_environments = %w[test development local_production]
# A list of parameters that should be filtered out of what is sent to
# Airbrake. By default, all "password" attributes will have their contents
diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb
index 9e191ac1..f90ec1ed 100644
--- a/config/initializers/carrierwave.rb
+++ b/config/initializers/carrierwave.rb
@@ -3,7 +3,7 @@
require "carrierwave/storage/fog"
CarrierWave.configure do |config|
- if Rails.env.development? || Rails.env.test?
+ if (Rails.env.development? || Rails.env.local_production?) || Rails.env.test?
config.storage = :file
else
# config.fog_provider = 'fog-aws'
diff --git a/config/initializers/delayed_job.rb b/config/initializers/delayed_job.rb
index 4c0241a0..202e0790 100644
--- a/config/initializers/delayed_job.rb
+++ b/config/initializers/delayed_job.rb
@@ -1,4 +1,4 @@
-Delayed::Worker.destroy_failed_jobs = !Rails.env.development?
+Delayed::Worker.destroy_failed_jobs = !(Rails.env.development? || Rails.env.local_production?)
Delayed::Worker.sleep_delay = 60
Delayed::Worker.max_attempts = 10
Delayed::Worker.max_run_time = 30.minutes
diff --git a/config/initializers/honeycomb.rb b/config/initializers/honeycomb.rb
index 0ac4787a..f1810bad 100644
--- a/config/initializers/honeycomb.rb
+++ b/config/initializers/honeycomb.rb
@@ -3,7 +3,7 @@
key = ApplicationConfig["HONEYCOMB_API_KEY"]
dataset = "dev.to-#{Rails.env}"
-$libhoney = if Rails.env.development? || Rails.env.test?
+$libhoney = if (Rails.env.development? || Rails.env.local_production?) || Rails.env.test?
Libhoney::NullClient.new
else
Libhoney::Client.new(
diff --git a/config/initializers/reverse_markdown.rb b/config/initializers/reverse_markdown.rb
index 86e6500d..22c2a167 100644
--- a/config/initializers/reverse_markdown.rb
+++ b/config/initializers/reverse_markdown.rb
@@ -4,7 +4,7 @@
# Because files are eagerloaded in production, this fix is only
# applicable in development (and test, when needed)
-if Rails.env.development? || Rails.env.test?
+if (Rails.env.development? || Rails.env.local_production?) || Rails.env.test?
Rails.application.config.to_prepare do
Dir.glob(Rails.root.join("app/lib/reverse_markdown/converters/*.rb")).sort.each do |filename|
require_dependency filename
diff --git a/config/initializers/timber.rb b/config/initializers/timber.rb
index 726d3f22..fcfdc412 100644
--- a/config/initializers/timber.rb
+++ b/config/initializers/timber.rb
@@ -12,7 +12,7 @@
config = Timber::Config.instance
config.integrations.action_view.silence = true
-config.integrations.active_record.silence = !Rails.env.development?
+config.integrations.active_record.silence = !(Rails.env.development? || Rails.env.local_production?)
config.integrations.rack.http_events.collapse_into_single_event = true
# Add additional configuration here.
diff --git a/config/initializers/timeout.rb b/config/initializers/timeout.rb
index 076288f3..d578d877 100644
--- a/config/initializers/timeout.rb
+++ b/config/initializers/timeout.rb
@@ -1,7 +1,7 @@
-if Rails.env.development? && ENV["RACK_TIMEOUT_WAIT_TIMEOUT"].nil?
+if (Rails.env.development? || Rails.env.local_production?) && ENV["RACK_TIMEOUT_WAIT_TIMEOUT"].nil?
ENV["RACK_TIMEOUT_WAIT_TIMEOUT"] = "100000"
ENV["RACK_TIMEOUT_SERVICE_TIMEOUT"] = "100000"
end
-Rack::Timeout.unregister_state_change_observer(:logger) if Rails.env.development?
+Rack::Timeout.unregister_state_change_observer(:logger) if (Rails.env.development? || Rails.env.local_production?)
Rack::Timeout::Logger.disable
diff --git a/config/newrelic.yml b/config/newrelic.yml
new file mode 100644
index 00000000..ad267869
--- /dev/null
+++ b/config/newrelic.yml
@@ -0,0 +1,69 @@
+#
+# This file configures the New Relic Agent. New Relic monitors Ruby, Java,
+# .NET, PHP, Python, Node, and Go applications with deep visibility and low
+# overhead. For more information, visit www.newrelic.com.
+#
+# Generated October 28, 2022
+#
+# This configuration file is custom generated for NewRelic Administration
+#
+# For full documentation of agent configuration options, please refer to
+# https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration
+
+common: &default_settings
+ # Required license key associated with your New Relic account.
+ license_key: <%= ENV['NEW_RELIC_LICENSE_KEY'] %>
+
+ # Your application name. Renaming here affects where data displays in New
+ # Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications
+ app_name: 'dev_to_local'
+
+ distributed_tracing:
+ enabled: true
+
+ # To disable the agent regardless of other settings, uncomment the following:
+
+ # agent_enabled: false
+
+ # Logging level for log/newrelic_agent.log
+ log_level: info
+
+ application_logging:
+ # If `true`, all logging-related features for the agent can be enabled or disabled
+ # independently. If `false`, all logging-related features are disabled.
+ enabled: true
+ forwarding:
+ # If `true`, the agent captures log records emitted by this application.
+ enabled: true
+ # Defines the maximum number of log records to buffer in memory at a time.
+ max_samples_stored: 10000
+ metrics:
+ # If `true`, the agent captures metrics related to logging for this application.
+ enabled: true
+ local_decorating:
+ # If `true`, the agent decorates logs with metadata to link to entities, hosts, traces, and spans.
+ # This requires a log forwarder to send your log files to New Relic.
+ # This should not be used when forwarding is enabled.
+ enabled: false
+
+# Environment-specific settings are in this section.
+# RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
+# If your application has other named environments, configure them here.
+development:
+ <<: *default_settings
+ app_name: 'dev_to_local (Development)'
+
+test:
+ <<: *default_settings
+ # It doesn't make sense to report to New Relic from automated test runs.
+ monitor_mode: false
+
+staging:
+ <<: *default_settings
+ app_name: 'dev_to_local (Staging)'
+
+production:
+ <<: *default_settings
+
+local_production:
+ <<: *default_settings
diff --git a/config/sample_application.yml b/config/sample_application.yml
index a829dae5..0e1c7d05 100644
--- a/config/sample_application.yml
+++ b/config/sample_application.yml
@@ -15,3 +15,5 @@ PUSHER_APP_ID:
PUSHER_KEY:
PUSHER_SECRET:
PUSHER_CLUSTER:
+
+NEW_RELIC_LICENCE_KEY:
\ No newline at end of file
diff --git a/config/secrets.yml b/config/secrets.yml
index 73f5e05c..181bd560 100644
--- a/config/secrets.yml
+++ b/config/secrets.yml
@@ -16,6 +16,9 @@ development:
test:
secret_key_base: 42dd7834039ebbea271af22635a6782ee15e519b14629c5276bfcdd4cff841e9926994784bb43a335a8f8c9739bb254ea3afe831839d4dc65654ec7516ec25f0
+local_production:
+ secret_key_base: a60edc976c913b19fd9fc8118936fbe1df2b07f4eecc5ad32f975e33cd4ea36b150c1ce933b681b90874a46568041629003dcbfc07238f7dca91741bcd1ec870
+
# Do not keep production secrets in the repository,
# instead read values from the environment.
diff --git a/config/webpacker.yml b/config/webpacker.yml
index 2dfcd170..18ef8e71 100644
--- a/config/webpacker.yml
+++ b/config/webpacker.yml
@@ -54,3 +54,12 @@ production:
# Cache manifest.json for performance
cache_manifest: true
+
+local_production:
+ <<: *default
+
+ # Production depends on precompilation of packs prior to booting for performance.
+ compile: false
+
+ # Cache manifest.json for performance
+ cache_manifest: true
\ No newline at end of file
diff --git a/dip.yml b/dip.yml
index 05d96de5..431b903f 100644
--- a/dip.yml
+++ b/dip.yml
@@ -3,7 +3,7 @@ version: '7.1'
# Define default environment variables to pass
# to Docker Compose
environment:
- RAILS_ENV: development
+ RAILS_ENV: <%= ENV.fetch('RAILS_ENV', 'development') %>
compose:
files:
diff --git a/newrelic-infra/docker-compose.yaml b/newrelic-infra/docker-compose.yaml
new file mode 100644
index 00000000..8f64959e
--- /dev/null
+++ b/newrelic-infra/docker-compose.yaml
@@ -0,0 +1,17 @@
+version: '3'
+
+services:
+ agent:
+ container_name: newrelic-infra
+ build:
+ context: .
+ dockerfile: newrelic-infra.dockerfile
+ cap_add:
+ - SYS_PTRACE
+ network_mode: host
+ pid: host
+ privileged: true
+ volumes:
+ - "/:/host:ro"
+ - "/var/run/docker.sock:/var/run/docker.sock"
+ restart: unless-stopped
diff --git a/newrelic-infra/newrelic-infra.dockerfile b/newrelic-infra/newrelic-infra.dockerfile
new file mode 100644
index 00000000..05bb7e74
--- /dev/null
+++ b/newrelic-infra/newrelic-infra.dockerfile
@@ -0,0 +1,2 @@
+FROM newrelic/infrastructure:latest
+ADD newrelic-infra.yml /etc/newrelic-infra.yml