From e935ecc5ac045691263bfa4bde8731a9fbff6345 Mon Sep 17 00:00:00 2001 From: usernaimandrey Date: Sun, 23 Feb 2025 02:38:30 +0300 Subject: [PATCH 1/3] week 4 optimisation (Shlyapnikov) --- .dev_to/Dockerfile | 2 +- .dev_to/compose.yml | 25 +++ .dev_to/dev_to.mk | 3 + .dev_to/prometheus.yml | 11 + .gitignore | 2 + Gemfile | 15 +- Gemfile.lock | 33 ++- Makefile | 2 + Procfile | 2 +- Procfile.dev | 4 +- app/views/articles/tag_index.html.erb | 210 +++++++++--------- app/views/stories/_main_stories_feed.html.erb | 4 +- benchmark.md | 121 ++++++++++ config/application.rb | 4 +- config/environments/local_production.rb | 105 +++++++++ config/initializers/airbrake.rb | 2 +- config/initializers/prometheus.rb | 10 + config/initializers/rails_performance.rb | 62 ++++++ config/newrelic.yml | 70 ++++++ config/puma.rb | 6 + config/routes.rb | 4 + config/secrets.yml | 3 +- config/webpacker.yml | 5 +- dip.yml | 3 +- 24 files changed, 580 insertions(+), 128 deletions(-) create mode 100644 .dev_to/dev_to.mk create mode 100644 .dev_to/prometheus.yml create mode 100644 benchmark.md create mode 100644 config/environments/local_production.rb create mode 100644 config/initializers/prometheus.rb create mode 100644 config/initializers/rails_performance.rb create mode 100644 config/newrelic.yml diff --git a/.dev_to/Dockerfile b/.dev_to/Dockerfile index e05cd541..ebbdec10 100644 --- a/.dev_to/Dockerfile +++ b/.dev_to/Dockerfile @@ -25,7 +25,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ ARG PG_MAJOR RUN curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | \ gpg --dearmor -o /usr/share/keyrings/postgres-archive-keyring.gpg \ - && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/postgres-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt/" \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/postgres-archive-keyring.gpg] https://apt-archive.postgresql.org/pub/repos/apt" \ $DISTRO_NAME-pgdg main $PG_MAJOR | tee /etc/apt/sources.list.d/postgres.list > /dev/null RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ diff --git a/.dev_to/compose.yml b/.dev_to/compose.yml index ec0af700..4253c5d5 100644 --- a/.dev_to/compose.yml +++ b/.dev_to/compose.yml @@ -12,6 +12,8 @@ x-app: &app tmpfs: - /tmp - /app/tmp/pids + stdin_open: true + tty: true x-backend: &backend <<: *app @@ -52,6 +54,29 @@ x-backend: &backend condition: service_healthy services: + dockerhost: + image: qoomon/docker-host + cap_add: [ 'NET_ADMIN', 'NET_RAW' ] + mem_limit: 8M + restart: on-failure + prometheus: + depends_on: [ dockerhost ] + image: prom/prometheus:0.18.0 + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + command: + - '-config.file=/etc/prometheus/prometheus.yml' + ports: + - '9090:9090' + grafana: + image: grafana/grafana:3.0.0-beta7 + environment: + - GF_SECURITY_ADMIN_PASSWORD=pass + depends_on: + - prometheus + ports: + - "3030:3000" + rails: <<: *backend command: bundle exec rails diff --git a/.dev_to/dev_to.mk b/.dev_to/dev_to.mk new file mode 100644 index 00000000..98fc2f87 --- /dev/null +++ b/.dev_to/dev_to.mk @@ -0,0 +1,3 @@ +start_local_production: + RAILS_ENV=local_production dip rails assets:precompile + RAILS_ENV=local_production dip compose up diff --git a/.dev_to/prometheus.yml b/.dev_to/prometheus.yml new file mode 100644 index 00000000..de2a3fe6 --- /dev/null +++ b/.dev_to/prometheus.yml @@ -0,0 +1,11 @@ +global: + scrape_interval: 5s + external_labels: + monitor: 'my-monitor' +scrape_configs: + - job_name: 'prometheus' + target_groups: + - targets: ['localhost:9090'] + - job_name: 'devdev' + target_groups: + - targets: ['dockerhost:9394'] diff --git a/.gitignore b/.gitignore index 53c5b710..ff6f1634 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,5 @@ package-lock.json #sitemap /public/sitemap.xml.gz +*/.env +.env diff --git a/Gemfile b/Gemfile index d55a1cad..8cf60fc9 100644 --- a/Gemfile +++ b/Gemfile @@ -60,6 +60,7 @@ gem "kaminari", "~> 1.1" gem "libhoney", "~> 1.11" gem "liquid", "~> 4.0" gem "nokogiri", "~> 1.10" +gem 'newrelic_rpm' gem "octokit", "~> 4.13" gem "omniauth", "~> 1.9" gem "omniauth-github", "~> 1.3" @@ -89,7 +90,13 @@ gem "sdoc", "~> 1.0", group: :doc gem "serviceworker-rails", "~> 0.5" gem "share_meow_client", "~> 0.1" gem "sitemap_generator", "~> 6.0" -gem "skylight", "~> 3.1" +gem "skylight" +gem "prometheus_exporter" +# gem "pg_query" +# gem 'yabeda-prometheus' +gem 'dotenv-rails' +gem 'rack-mini-profiler' +gem "pghero" gem "slack-notifier", "~> 2.3" gem "sprockets", "~> 3.7" gem "staccato", "~> 0.5" @@ -103,7 +110,7 @@ gem "validate_url", "~> 1.0" gem "webpacker", "~> 3.5" 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 @@ -117,7 +124,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 @@ -136,7 +143,7 @@ group :development, :test do end group :test do - gem "approvals", "~> 0.0" + # gem "approvals", "~> 0.0" gem "chromedriver-helper", "~> 2.1" gem "database_cleaner", "~> 1.7" gem "factory_bot_rails", "~> 4.11" diff --git a/Gemfile.lock b/Gemfile.lock index 84c23147..af9a39d5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,9 +82,9 @@ GEM nokogiri railties safely_block (>= 0.1.1) - airbrake (8.1.4) - airbrake-ruby (~> 3.2) - airbrake-ruby (3.2.5) + airbrake (8.3.2) + airbrake-ruby (~> 4.1) + airbrake-ruby (4.15.0) rbtree3 (~> 0.5) algoliasearch (1.26.0) httpclient (~> 2.8, >= 2.8.3) @@ -97,9 +97,6 @@ GEM json (~> 1.8) ancestry (3.0.5) activerecord (>= 3.2.0) - approvals (0.0.24) - nokogiri (~> 1.6) - thor (~> 0.18) archive-zip (0.11.0) io-like (~> 0.3.0) arel (8.0.0) @@ -248,6 +245,10 @@ GEM docile (1.3.1) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) + dotenv (2.8.1) + dotenv-rails (2.8.1) + dotenv (= 2.8.1) + railties (>= 3.2) draper (3.0.1) actionpack (~> 5.0) activemodel (~> 5.0) @@ -599,6 +600,7 @@ GEM net-http-persistent (3.0.0) connection_pool (~> 2.2) netrc (0.11.0) + newrelic_rpm (9.17.0) nio4r (2.3.1) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) @@ -637,7 +639,11 @@ GEM parser (2.6.0.0) ast (~> 2.4.0) pg (1.1.4) + pghero (2.8.3) + activerecord (>= 5) powerpack (0.1.2) + prometheus_exporter (2.1.0) + webrick pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) @@ -664,6 +670,8 @@ GEM rack (2.0.6) rack-host-redirect (1.3.0) rack + rack-mini-profiler (3.1.1) + rack (>= 1.2.0) rack-protection (2.0.4) rack rack-proxy (0.6.5) @@ -683,7 +691,7 @@ GEM bundler (>= 1.3.0) railties (= 5.1.6.2) sprockets-rails (>= 2.0.0) - rails-assets-airbrake-js-client (1.5.0) + rails-assets-airbrake-js-client (1.6.6) rails-controller-testing (1.0.4) actionpack (>= 5.0.1.x) actionview (>= 5.0.1.x) @@ -706,7 +714,7 @@ GEM rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) - rbtree3 (0.5.0) + rbtree3 (0.7.1) rbvmomi (1.11.6) builder (~> 3.0) json (>= 1.8) @@ -915,6 +923,7 @@ GEM webpush (0.3.2) hkdf (~> 0.2) jwt + webrick (1.9.1) websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) @@ -939,7 +948,6 @@ DEPENDENCIES algoliasearch-rails (~> 1.21) algorithmia (~> 1.0) ancestry (~> 3.0) - approvals (~> 0.0) autoprefixer-rails (~> 9.4) aws-sdk-lambda (~> 1.16) better_errors (~> 2.5) @@ -963,6 +971,7 @@ DEPENDENCIES derailed (~> 0.1) derailed_benchmarks (~> 1.3) devise (~> 4.6) + dotenv-rails draper (~> 3.0) email_validator (~> 1.6) emoji_regex (~> 1.0) @@ -996,6 +1005,7 @@ DEPENDENCIES liquid (~> 4.0) memory_profiler (~> 0.9) nakayoshi_fork + newrelic_rpm nokogiri (~> 1.10) octokit (~> 4.13) omniauth (~> 1.9) @@ -1003,6 +1013,8 @@ DEPENDENCIES omniauth-twitter (~> 1.4) parallel_tests (~> 2.27) pg (~> 1.1) + pghero + prometheus_exporter pry (~> 0.12) pry-byebug (~> 3.7) pry-rails (~> 0.3) @@ -1012,6 +1024,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)! @@ -1040,7 +1053,7 @@ DEPENDENCIES simplecov (~> 0.16) sinatra (~> 2.0) sitemap_generator (~> 6.0) - skylight (~> 3.1) + skylight slack-notifier (~> 2.3) sprockets (~> 3.7) staccato (~> 0.5) diff --git a/Makefile b/Makefile index 97e82a01..08063477 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +include .dev_to/dev_to.mk + .PHONY: run run: diff --git a/Procfile b/Procfile index ae689ef5..a3a8e11c 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,2 @@ web: bin/start-pgbouncer bundle exec puma -C config/puma.rb -worker: bundle exec rake jobs:work \ No newline at end of file +worker: bundle exec rake jobs:work diff --git a/Procfile.dev b/Procfile.dev index f6093523..a3558538 100644 --- a/Procfile.dev +++ b/Procfile.dev @@ -1,3 +1,3 @@ web: bin/rails s -p 3000 -webpacker: ./bin/webpack-dev-server -job: bin/rake jobs:work + +prometheus_exporter: bundle exec prometheus_exporter diff --git a/app/views/articles/tag_index.html.erb b/app/views/articles/tag_index.html.erb index fa6854cb..6023ad94 100644 --- a/app/views/articles/tag_index.html.erb +++ b/app/views/articles/tag_index.html.erb @@ -1,113 +1,115 @@ -<%= content_for :page_meta do %> - <%= render "articles/tags/meta" %> -<% end %> - -
-
-

- <% if @tag_model && @tag_model.pretty_name.present? %> - <%= @tag_model.pretty_name %> - <% else %> - <%= @tag %> - <% end %> - <% if @tag_model %> - - <% end %> -

+<%= cache @tag_model do%> + <%= content_for :page_meta do %> + <%= render "articles/tags/meta" %> + <% end %> + + -
-
" - data-articles-since="<%= Timeframer.new(params[:timeframe]).datetime.to_i %>"> - <%= render "articles/tags/sidebar" %> -
- <% if @tag_model && @tag_model.supported %> - - <% end %> -
-
- -
- <% if ["week", "month", "year", "infinity", "latest"].exclude?(params[:timeframe]) %> - - <% elsif timeframe_check('week') %> - - <% elsif timeframe_check('month') %> - - <% elsif timeframe_check('year') %> - - <% elsif timeframe_check('infinity') %> - - <% elsif timeframe_check('latest') %> - - <% end %> + .on-page-nav-controls .separator { + border-color: <%= HexComparer.new([@tag_model.bg_color_hex || "#ffffff"], 4).accent %> !important; + } + + <% end %> +
+
+ +
+ <% if ["week", "month", "year", "infinity", "latest"].exclude?(params[:timeframe]) %> + + <% elsif timeframe_check('week') %> + + <% elsif timeframe_check('month') %> + + <% elsif timeframe_check('year') %> + + <% elsif timeframe_check('infinity') %> + + <% elsif timeframe_check('latest') %> + + <% end %> +
+ +
- - -
-
- <% if @stories.any? %> - <%= render "articles/tags/main_feed" %> - <% end %> -
-
- loading... +
+ <% if @stories.any? %> + <%= render "articles/tags/main_feed" %> + <% end %> +
+
+ loading... +
+ <%= render "articles/tags/sidebar_additional" %>
- <%= render "articles/tags/sidebar_additional" %> -
-<%= render "stories/narrow_nav_menu" %> -<%= render "stories/stories_list_script" %> + <%= render "stories/narrow_nav_menu" %> + <%= render "stories/stories_list_script" %> +<%end%> diff --git a/app/views/stories/_main_stories_feed.html.erb b/app/views/stories/_main_stories_feed.html.erb index b6cd0a65..1bb23c18 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 ['single_story', story], expires_in: 24.hours do %> + <%= render "articles/single_story", story: story %> + <% end %> <% end %> <% end %> <% if @stories.size > 1 %> diff --git a/benchmark.md b/benchmark.md new file mode 100644 index 00000000..96406319 --- /dev/null +++ b/benchmark.md @@ -0,0 +1,121 @@ +## До оптимизации + +```bash +Server Software: +Server Hostname: localhost +Server Port: 3000 + +Document Path: / +Document Length: 159427 bytes + +Concurrency Level: 5 +Time taken for tests: 33.310 seconds +Complete requests: 100 +Failed requests: 99 + (Connect: 0, Receive: 0, Length: 99, Exceptions: 0) +Total transferred: 16069032 bytes +HTML transferred: 15970086 bytes +Requests per second: 3.00 [#/sec] (mean) +Time per request: 1665.483 [ms] (mean) +Time per request: 333.097 [ms] (mean, across all concurrent requests) +Transfer rate: 471.11 [Kbytes/sec] received + +Connection Times (ms) + min mean[+/-sd] median max +Connect: 0 0 0.0 0 0 +Processing: 817 1623 220.8 1622 2054 +Waiting: 817 1618 220.0 1618 2045 +Total: 817 1623 220.8 1622 2054 + +Percentage of the requests served within a certain time (ms) + 50% 1622 + 66% 1722 + 75% 1756 + 80% 1804 + 90% 1881 + 95% 1956 + 98% 2017 + 99% 2054 + 100% 2054 (longest request) +``` + +## После того как закешировали паршл + +```bash +Server Software: +Server Hostname: localhost +Server Port: 3000 + +Document Path: / +Document Length: 160220 bytes + +Concurrency Level: 5 +Time taken for tests: 31.519 seconds +Complete requests: 100 +Failed requests: 67 + (Connect: 0, Receive: 0, Length: 67, Exceptions: 0) +Total transferred: 16123231 bytes +HTML transferred: 16022065 bytes +Requests per second: 3.17 [#/sec] (mean) +Time per request: 1575.967 [ms] (mean) +Time per request: 315.193 [ms] (mean, across all concurrent requests) +Transfer rate: 499.55 [Kbytes/sec] received + +Connection Times (ms) + min mean[+/-sd] median max +Connect: 0 0 0.1 0 1 +Processing: 286 1549 188.3 1558 1919 +Waiting: 286 1544 186.5 1551 1909 +Total: 286 1549 188.3 1558 1919 + +Percentage of the requests served within a certain time (ms) + 50% 1558 + 66% 1602 + 75% 1636 + 80% 1651 + 90% 1753 + 95% 1807 + 98% 1851 + 99% 1919 + 100% 1919 (longest request) + ``` + + ## на local_production окружении с кешированием и прекомпиляци ассетов + +```bash +Server Software: +Server Hostname: localhost +Server Port: 3000 + +Document Path: / +Document Length: 135209 bytes + +Concurrency Level: 5 +Time taken for tests: 8.778 seconds +Complete requests: 100 +Failed requests: 0 +Total transferred: 13563200 bytes +HTML transferred: 13520900 bytes +Requests per second: 11.39 [#/sec] (mean) +Time per request: 438.925 [ms] (mean) +Time per request: 87.785 [ms] (mean, across all concurrent requests) +Transfer rate: 1508.84 [Kbytes/sec] received + +Connection Times (ms) + min mean[+/-sd] median max +Connect: 0 0 0.0 0 0 +Processing: 123 429 101.5 427 682 +Waiting: 122 411 101.9 398 663 +Total: 123 429 101.5 427 682 + +Percentage of the requests served within a certain time (ms) + 50% 427 + 66% 469 + 75% 499 + 80% 518 + 90% 556 + 95% 624 + 98% 665 + 99% 682 + 100% 682 (longest request) +``` diff --git a/config/application.rb b/config/application.rb index 1b4c391f..6e13b014 100644 --- a/config/application.rb +++ b/config/application.rb @@ -5,7 +5,7 @@ # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) - +Dotenv::Railtie.load module PracticalDeveloper class Application < Rails::Application config.load_defaults 5.1 @@ -30,6 +30,8 @@ class Application < Rails::Application config.autoload_paths += Dir["#{config.root}/app/black_box/"] config.autoload_paths += Dir["#{config.root}/app/sanitizers"] config.autoload_paths += Dir["#{config.root}/lib/"] + config.skylight.environments << "development" + config.skylight.environments << "local_production" config.active_record.observers = :article_observer, :reaction_observer, :comment_observer config.active_job.queue_adapter = :delayed_job diff --git a/config/environments/local_production.rb b/config/environments/local_production.rb new file mode 100644 index 00000000..817c7d6a --- /dev/null +++ b/config/environments/local_production.rb @@ -0,0 +1,105 @@ +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 + + config.web_console.development_only = false + + # 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.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 + 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/prometheus.rb b/config/initializers/prometheus.rb new file mode 100644 index 00000000..c6cf583f --- /dev/null +++ b/config/initializers/prometheus.rb @@ -0,0 +1,10 @@ +if Rails.env != "test" + require 'prometheus_exporter/middleware' + require 'prometheus_exporter/client' + + prometheus_client = PrometheusExporter::Client.new(host: 'localhost') + PrometheusExporter::Client.default = prometheus_client + + # This reports stats per request like HTTP status and timings + Rails.application.middleware.unshift PrometheusExporter::Middleware +end diff --git a/config/initializers/rails_performance.rb b/config/initializers/rails_performance.rb new file mode 100644 index 00000000..552ba2d2 --- /dev/null +++ b/config/initializers/rails_performance.rb @@ -0,0 +1,62 @@ +RailsPerformance.setup do |config| + config.redis = Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0") # or Redis::Namespace.new("rails-performance", redis: Redis.new), see below in README + config.duration = 4.hours + + config.debug = false # currently not used> + config.enabled = true + + # configure Recent tab (time window and limit of requests) + # config.recent_requests_time_window = 60.minutes + # config.recent_requests_limit = nil # or 1000 + + # configure Slow Requests tab (time window, limit of requests and threshold) + # config.slow_requests_time_window = 4.hours # time window for slow requests + # config.slow_requests_limit = 500 # number of max rows + # config.slow_requests_threshold = 500 # number of ms + + # default path where to mount gem, + # alternatively you can mount the RailsPerformance::Engine in your routes.rb + config.mount_at = '/rails/performance' + + # protect your Performance Dashboard with HTTP BASIC password + config.http_basic_authentication_enabled = false + config.http_basic_authentication_user_name = 'rails_performance' + config.http_basic_authentication_password = 'password12' + + # if you need an additional rules to check user permissions + config.verify_access_proc = proc { |controller| true } + # for example when you have `current_user` + # config.verify_access_proc = proc { |controller| controller.current_user && controller.current_user.admin? } + + # You can ignore endpoints with Rails standard notation controller#action + # config.ignored_endpoints = ['HomeController#contact'] + + # You can ignore request paths by specifying the beginning of the path. + # For example, all routes starting with '/admin' can be ignored: + config.ignored_paths = ['/rails/performance', '/admin'] + + # store custom data for the request + # config.custom_data_proc = proc do |env| + # request = Rack::Request.new(env) + # { + # email: request.env['warden'].user&.email, # if you are using Devise for example + # user_agent: request.env['HTTP_USER_AGENT'] + # } + # end + + # config home button link + config.home_link = '/' + + # To skip some Rake tasks from monitoring + config.skipable_rake_tasks = ['webpacker:compile'] + + # To monitor rake tasks performance, you need to include rake tasks + # config.include_rake_tasks = false + + # To monitor custom events with `RailsPerformance.measure` block + # config.include_custom_events = true + + # To monitor system resources (CPU, memory, disk) + # to enabled add required gems (see README) + # config.system_monitor_duration = 24.hours +end if defined?(RailsPerformance) diff --git a/config/newrelic.yml b/config/newrelic.yml new file mode 100644 index 00000000..67f87360 --- /dev/null +++ b/config/newrelic.yml @@ -0,0 +1,70 @@ +# +# 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['NEWRELICK_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: 'app_devto' + + 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: ' (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: ' (Staging)' + +production: + <<: *default_settings + +local_production: + <<: *default_settings diff --git a/config/puma.rb b/config/puma.rb index 3d5df906..fa0d7054 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,3 +1,9 @@ +# require 'prometheus_exporter/instrumentation' +# PrometheusExporter::Instrumentation::ActiveRecord.start( +# custom_labels: { type: "puma_worker" }, +# config_labels: [:database, :host] +# ) + workers Integer(ENV["WEB_CONCURRENCY"] || 2) threads_count = Integer(ENV["MAX_THREADS"] || 5) threads threads_count, threads_count diff --git a/config/routes.rb b/config/routes.rb index 8ba426bb..7364a735 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,6 +7,10 @@ registrations: "registrations" } + mount PgHero::Engine, at: "pghero" + + + authenticated :user, ->(user) { user.admin? } do mount DelayedJobWeb, at: "/delayed_job" end diff --git a/config/secrets.yml b/config/secrets.yml index 73f5e05c..ae0e21d8 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -16,7 +16,8 @@ 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. production: diff --git a/config/webpacker.yml b/config/webpacker.yml index 2dfcd170..4fad4c5c 100644 --- a/config/webpacker.yml +++ b/config/webpacker.yml @@ -46,7 +46,7 @@ test: # Compile test packs to a separate directory public_output_path: packs-test -production: +production: &production <<: *default # Production depends on precompilation of packs prior to booting for performance. @@ -54,3 +54,6 @@ production: # Cache manifest.json for performance cache_manifest: true + +local_production: + <<: *production diff --git a/dip.yml b/dip.yml index 05d96de5..b1cf30d1 100644 --- a/dip.yml +++ b/dip.yml @@ -3,7 +3,8 @@ version: '7.1' # Define default environment variables to pass # to Docker Compose environment: - RAILS_ENV: development + RAILS_ENV: <%= ENV.fetch('RAILS_ENV', 'development') %> + RACK_ENV: <%= ENV.fetch('RACK_ENV', 'development') %> compose: files: From 9872d44a8210ca6f531bd5e7a4968e1f964dc0e4 Mon Sep 17 00:00:00 2001 From: usernaimandrey Date: Sun, 23 Feb 2025 20:20:25 +0300 Subject: [PATCH 2/3] rebenchmark --- benchmark.md | 55 ++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/benchmark.md b/benchmark.md index 96406319..66dacbdf 100644 --- a/benchmark.md +++ b/benchmark.md @@ -39,48 +39,43 @@ Percentage of the requests served within a certain time (ms) 100% 2054 (longest request) ``` -## После того как закешировали паршл +## После того как закешировали паршл среднее время ответа уменьшилось в 2,5 раза ```bash -Server Software: +Server Software: Server Hostname: localhost Server Port: 3000 - Document Path: / -Document Length: 160220 bytes - +Document Length: 143451 bytes Concurrency Level: 5 -Time taken for tests: 31.519 seconds +Time taken for tests: 2.669 seconds Complete requests: 100 -Failed requests: 67 - (Connect: 0, Receive: 0, Length: 67, Exceptions: 0) -Total transferred: 16123231 bytes -HTML transferred: 16022065 bytes -Requests per second: 3.17 [#/sec] (mean) -Time per request: 1575.967 [ms] (mean) -Time per request: 315.193 [ms] (mean, across all concurrent requests) -Transfer rate: 499.55 [Kbytes/sec] received - +Failed requests: 0 +Total transferred: 14387400 bytes +HTML transferred: 14345100 bytes +Requests per second: 37.46 [#/sec] (mean) +Time per request: 832.472 [ms] (mean) +Time per request: 145.694 [ms] (mean, across all concurrent requests) +Transfer rate: 5263.34 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max -Connect: 0 0 0.1 0 1 -Processing: 286 1549 188.3 1558 1919 -Waiting: 286 1544 186.5 1551 1909 -Total: 286 1549 188.3 1558 1919 - +Connect: 0 0 0.2 0 1 +Processing: 68 124 26.5 115 206 +Waiting: 66 122 26.1 112 205 +Total: 68 125 26.5 116 206 Percentage of the requests served within a certain time (ms) - 50% 1558 - 66% 1602 - 75% 1636 - 80% 1651 - 90% 1753 - 95% 1807 - 98% 1851 - 99% 1919 - 100% 1919 (longest request) + 50% 116 + 66% 135 + 75% 143 + 80% 146 + 90% 157 + 95% 175 + 98% 198 + 99% 206 + 100% 206 (longest request) ``` - ## на local_production окружении с кешированием и прекомпиляци ассетов + ## на local_production окружении с кешированием и прекомпиляци ассетов срднее время ответа уменьшилось почти в 5 раз ```bash Server Software: From 7c8c272973136eb3ab9b250aee26b4b9b8b84b98 Mon Sep 17 00:00:00 2001 From: usernaimandrey Date: Sun, 23 Feb 2025 20:23:59 +0300 Subject: [PATCH 3/3] rebenchmark --- config/puma.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/puma.rb b/config/puma.rb index fa0d7054..ffb335ca 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,8 +1,8 @@ -# require 'prometheus_exporter/instrumentation' -# PrometheusExporter::Instrumentation::ActiveRecord.start( -# custom_labels: { type: "puma_worker" }, -# config_labels: [:database, :host] -# ) +require 'prometheus_exporter/instrumentation' +PrometheusExporter::Instrumentation::ActiveRecord.start( + custom_labels: { type: "puma_worker" }, + config_labels: [:database, :host] +) workers Integer(ENV["WEB_CONCURRENCY"] || 2) threads_count = Integer(ENV["MAX_THREADS"] || 5)