diff options
author | Alex Groleau <agroleau@gitlab.com> | 2019-08-27 12:41:39 -0400 |
---|---|---|
committer | Alex Groleau <agroleau@gitlab.com> | 2019-08-27 12:41:39 -0400 |
commit | aa01f092829facd1044ad02f334422b7dbdc8b0e (patch) | |
tree | a754bf2497820432df7da0f2108bb7527a8dd7b8 /config/initializers | |
parent | a1d9c9994a9a4d79b824c3fd9322688303ac8b03 (diff) | |
parent | 6b10779053ff4233c7a64c5ab57754fce63f6710 (diff) | |
download | gitlab-ce-aa01f092829facd1044ad02f334422b7dbdc8b0e.tar.gz |
Merge branch 'master' of gitlab_gitlab:gitlab-org/gitlab-cerunner-metrics-extractor
Diffstat (limited to 'config/initializers')
37 files changed, 253 insertions, 673 deletions
diff --git a/config/initializers/0_inflections.rb b/config/initializers/0_inflections.rb index 4d1f4917275..d317825c1b8 100644 --- a/config/initializers/0_inflections.rb +++ b/config/initializers/0_inflections.rb @@ -19,6 +19,7 @@ ActiveSupport::Inflector.inflections do |inflect| project_registry file_registry job_artifact_registry + container_repository_registry vulnerability_feedback vulnerabilities_feedback group_view diff --git a/config/initializers/0_inject_enterprise_edition_module.rb b/config/initializers/0_inject_enterprise_edition_module.rb new file mode 100644 index 00000000000..b3ebb44ef25 --- /dev/null +++ b/config/initializers/0_inject_enterprise_edition_module.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'active_support/inflector' + +module InjectEnterpriseEditionModule + def prepend_if_ee(constant, with_descendants: false) + return unless Gitlab.ee? + + ee_module = constant.constantize + prepend(ee_module) + + if with_descendants + descendants.each { |descendant| descendant.prepend(ee_module) } + end + end + + def extend_if_ee(constant) + extend(constant.constantize) if Gitlab.ee? + end + + def include_if_ee(constant) + include(constant.constantize) if Gitlab.ee? + end +end + +Module.prepend(InjectEnterpriseEditionModule) diff --git a/config/initializers/0_license.rb b/config/initializers/0_license.rb index f750022dfdf..19c71c34904 100644 --- a/config/initializers/0_license.rb +++ b/config/initializers/0_license.rb @@ -10,7 +10,7 @@ Gitlab.ee do end # Needed to run migration - if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.data_source_exists?('licenses') + if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('licenses') message = LicenseHelper.license_message(signed_in: true, is_admin: true, in_html: false) if ::License.block_changes? && message.present? warn "WARNING: #{message}" diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 0b8a6607250..81433b620bc 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -1,5 +1,6 @@ require_relative '../settings' require_relative '../object_store_settings' +require_relative '../smime_signature_settings' # Default settings Settings['ldap'] ||= Settingslogic.new({}) @@ -55,7 +56,7 @@ if Settings.ldap['enabled'] || Rails.env.test? server['tls_options'] ||= {} if server['ssl_version'] || server['ca_file'] - Rails.logger.warn 'DEPRECATED: LDAP options `ssl_version` and `ca_file` should be nested within `tls_options`' + Rails.logger.warn 'DEPRECATED: LDAP options `ssl_version` and `ca_file` should be nested within `tls_options`' # rubocop:disable Gitlab/RailsLogger end if server['ssl_version'] @@ -83,6 +84,7 @@ Settings['omniauth'] ||= Settingslogic.new({}) Settings.omniauth['enabled'] = true if Settings.omniauth['enabled'].nil? Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil? Settings.omniauth['allow_single_sign_on'] = false if Settings.omniauth['allow_single_sign_on'].nil? +Settings.omniauth['allow_bypass_two_factor'] = false if Settings.omniauth['allow_bypass_two_factor'].nil? Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_providers'].nil? Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block_auto_created_users'].nil? Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? @@ -171,6 +173,7 @@ Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab' Settings.gitlab['email_reply_to'] ||= ENV['GITLAB_EMAIL_REPLY_TO'] || "noreply@#{Settings.gitlab.host}" Settings.gitlab['email_subject_suffix'] ||= ENV['GITLAB_EMAIL_SUBJECT_SUFFIX'] || "" +Settings.gitlab['email_smime'] = SmimeSignatureSettings.parse(Settings.gitlab['email_smime']) Settings.gitlab['base_url'] ||= Settings.__send__(:build_base_gitlab_url) Settings.gitlab['url'] ||= Settings.__send__(:build_gitlab_url) Settings.gitlab['user'] ||= 'git' @@ -200,6 +203,7 @@ Settings.gitlab.default_projects_features['visibility_level'] = Settings.__sen Settings.gitlab['domain_whitelist'] ||= [] Settings.gitlab['import_sources'] ||= Gitlab::ImportSources.values Settings.gitlab['trusted_proxies'] ||= [] +Settings.gitlab['content_security_policy'] ||= Gitlab::ContentSecurityPolicy::ConfigLoader.default_settings_hash Settings.gitlab['no_todos_messages'] ||= YAML.load_file(Rails.root.join('config', 'no_todos_messages.yml')) Settings.gitlab['impersonation_enabled'] ||= true if Settings.gitlab['impersonation_enabled'].nil? Settings.gitlab['usage_ping_enabled'] = true if Settings.gitlab['usage_ping_enabled'].nil? @@ -217,6 +221,7 @@ Gitlab.ee do Settings['elasticsearch'] ||= Settingslogic.new({}) Settings.elasticsearch['enabled'] = false if Settings.elasticsearch['enabled'].nil? Settings.elasticsearch['url'] = ENV['ELASTIC_URL'] || "http://localhost:9200" + Settings.elasticsearch['indexer_path'] ||= Gitlab::Utils.which('gitlab-elasticsearch-indexer') end # @@ -258,6 +263,7 @@ Settings.registry['key'] ||= nil Settings.registry['issuer'] ||= nil Settings.registry['host_port'] ||= [Settings.registry['host'], Settings.registry['port']].compact.join(':') Settings.registry['path'] = Settings.absolute(Settings.registry['path'] || File.join(Settings.shared['path'], 'registry')) +Settings.registry['notifications'] ||= [] # # Error Reporting and Logging with Sentry @@ -294,6 +300,12 @@ Gitlab.ee do Settings['geo'] ||= Settingslogic.new({}) # For backwards compatibility, default to gitlab_url and if so, ensure it ends with "/" Settings.geo['node_name'] = Settings.geo['node_name'].presence || Settings.gitlab['url'].chomp('/').concat('/') + + # + # Registry replication + # + Settings.geo['registry_replication'] ||= Settingslogic.new({}) + Settings.geo.registry_replication['enabled'] ||= false end # @@ -471,6 +483,9 @@ Gitlab.ee do Settings.cron_jobs['geo_repository_verification_secondary_scheduler_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['geo_repository_verification_secondary_scheduler_worker']['cron'] ||= '*/1 * * * *' Settings.cron_jobs['geo_repository_verification_secondary_scheduler_worker']['job_class'] ||= 'Geo::RepositoryVerification::Secondary::SchedulerWorker' + Settings.cron_jobs['geo_container_repository_sync_worker'] ||= Settingslogic.new({}) + Settings.cron_jobs['geo_container_repository_sync_worker']['cron'] ||= '*/1 * * * *' + Settings.cron_jobs['geo_container_repository_sync_worker']['job_class'] ||= 'Geo::ContainerRepositorySyncDispatchWorker' Settings.cron_jobs['historical_data_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['historical_data_worker']['cron'] ||= '0 12 * * *' Settings.cron_jobs['historical_data_worker']['job_class'] = 'HistoricalDataWorker' diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb index 741c8ef1ca0..143b34b5368 100644 --- a/config/initializers/7_prometheus_metrics.rb +++ b/config/initializers/7_prometheus_metrics.rb @@ -1,5 +1,4 @@ require 'prometheus/client' -require 'prometheus/client/support/unicorn' # Keep separate directories for separate processes def prometheus_default_multiproc_dir @@ -17,13 +16,13 @@ def prometheus_default_multiproc_dir end Prometheus::Client.configure do |config| - config.logger = Rails.logger + config.logger = Rails.logger # rubocop:disable Gitlab/RailsLogger config.initial_mmap_file_size = 4 * 1024 config.multiprocess_files_dir = ENV['prometheus_multiproc_dir'] || prometheus_default_multiproc_dir - config.pid_provider = Prometheus::Client::Support::Unicorn.method(:worker_pid_provider) + config.pid_provider = Prometheus::PidProvider.method(:worker_id) end Gitlab::Application.configure do |config| @@ -33,6 +32,9 @@ end Sidekiq.configure_server do |config| config.on(:startup) do + # webserver metrics are cleaned up in config.ru: `warmup` block + Prometheus::CleanupMultiprocDirService.new.execute + Gitlab::Metrics::SidekiqMetricsExporter.instance.start end end @@ -52,22 +54,3 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled? end end end - -def cleanup_prometheus_multiproc_dir - # The following is necessary to ensure stale Prometheus metrics don't - # accumulate over time. It needs to be done in this hook as opposed to - # inside an init script to ensure metrics files aren't deleted after new - # unicorn workers start after a SIGUSR2 is received. - if dir = ::Prometheus::Client.configuration.multiprocess_files_dir - old_metrics = Dir[File.join(dir, '*.db')] - FileUtils.rm_rf(old_metrics) - end -end - -Gitlab::Cluster::LifecycleEvents.on_master_start do - cleanup_prometheus_multiproc_dir -end - -Gitlab::Cluster::LifecycleEvents.on_master_restart do - cleanup_prometheus_multiproc_dir -end diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb index 3dd12c7e64d..8ef9ff6b7fc 100644 --- a/config/initializers/8_devise.rb +++ b/config/initializers/8_devise.rb @@ -81,7 +81,7 @@ Devise.setup do |config| # You can use this to let your user access some features of your application # without confirming the account, but blocking it after a certain period # (ie 2 days). - # config.allow_unconfirmed_access_for = 2.days + config.allow_unconfirmed_access_for = 30.days # Defines which key will be used when confirming an account # config.confirmation_keys = [ :email ] diff --git a/config/initializers/action_mailer_hooks.rb b/config/initializers/action_mailer_hooks.rb index f1b3c1f8ae8..02ca6ef13bf 100644 --- a/config/initializers/action_mailer_hooks.rb +++ b/config/initializers/action_mailer_hooks.rb @@ -10,3 +10,8 @@ ActionMailer::Base.register_interceptors( ) ActionMailer::Base.register_observer(::Gitlab::Email::Hook::DeliveryMetricsObserver) + +if Gitlab.config.gitlab.email_enabled && Gitlab.config.gitlab.email_smime.enabled + ActionMailer::Base.register_interceptor(::Gitlab::Email::Hook::SmimeSignatureInterceptor) + Gitlab::AppLogger.debug "S/MIME signing of outgoing emails enabled" +end diff --git a/config/initializers/active_record_data_types.rb b/config/initializers/active_record_data_types.rb index e95157bfde5..846f28e6f66 100644 --- a/config/initializers/active_record_data_types.rb +++ b/config/initializers/active_record_data_types.rb @@ -1,83 +1,45 @@ # ActiveRecord custom data type for storing datetimes with timezone information. # See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11229 -if Gitlab::Database.postgresql? - require 'active_record/connection_adapters/postgresql_adapter' +require 'active_record/connection_adapters/postgresql_adapter' - module ActiveRecord::ConnectionAdapters::PostgreSQL::OID - # Add the class `DateTimeWithTimeZone` so we can map `timestamptz` to it. - class DateTimeWithTimeZone < DateTime - def type - :datetime_with_timezone - end +module ActiveRecord::ConnectionAdapters::PostgreSQL::OID + # Add the class `DateTimeWithTimeZone` so we can map `timestamptz` to it. + class DateTimeWithTimeZone < DateTime + def type + :datetime_with_timezone end end +end - module RegisterDateTimeWithTimeZone - # Run original `initialize_type_map` and then register `timestamptz` as a - # `DateTimeWithTimeZone`. - # - # Apparently it does not matter that the original `initialize_type_map` - # aliases `timestamptz` to `timestamp`. - # - # When schema dumping, `timestamptz` columns will be output as - # `t.datetime_with_timezone`. - def initialize_type_map(mapping) - super mapping - - mapping.register_type 'timestamptz' do |_, _, sql_type| - precision = extract_precision(sql_type) - ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone.new(precision: precision) - end - end - end - - class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - prepend RegisterDateTimeWithTimeZone - - # Add column type `datetime_with_timezone` so we can do this in - # migrations: - # - # add_column(:users, :datetime_with_timezone) - # - NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamptz' } - end -elsif Gitlab::Database.mysql? - require 'active_record/connection_adapters/mysql2_adapter' - - module RegisterDateTimeWithTimeZone - # Run original `initialize_type_map` and then register `timestamp` as a - # `MysqlDateTimeWithTimeZone`. - # - # When schema dumping, `timestamp` columns will be output as - # `t.datetime_with_timezone`. - def initialize_type_map(mapping) - super mapping - - mapping.register_type(/timestamp/i) do |sql_type| - precision = extract_precision(sql_type) - ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlDateTimeWithTimeZone.new(precision: precision) - end +module RegisterDateTimeWithTimeZone + # Run original `initialize_type_map` and then register `timestamptz` as a + # `DateTimeWithTimeZone`. + # + # Apparently it does not matter that the original `initialize_type_map` + # aliases `timestamptz` to `timestamp`. + # + # When schema dumping, `timestamptz` columns will be output as + # `t.datetime_with_timezone`. + def initialize_type_map(mapping = type_map) + super mapping + + mapping.register_type 'timestamptz' do |_, _, sql_type| + precision = extract_precision(sql_type) + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone.new(precision: precision) end end +end - class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter - prepend RegisterDateTimeWithTimeZone - - # Add the class `DateTimeWithTimeZone` so we can map `timestamp` to it. - class MysqlDateTimeWithTimeZone < ActiveRecord::Type::DateTime - def type - :datetime_with_timezone - end - end +class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter + prepend RegisterDateTimeWithTimeZone - # Add column type `datetime_with_timezone` so we can do this in - # migrations: - # - # add_column(:users, :datetime_with_timezone) - # - NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamp' } - end + # Add column type `datetime_with_timezone` so we can do this in + # migrations: + # + # add_column(:users, :datetime_with_timezone) + # + NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamptz' } end # Ensure `datetime_with_timezone` columns are correctly written to schema.rb diff --git a/config/initializers/active_record_lifecycle.rb b/config/initializers/active_record_lifecycle.rb index 7fa37121efc..61f1d299960 100644 --- a/config/initializers/active_record_lifecycle.rb +++ b/config/initializers/active_record_lifecycle.rb @@ -7,7 +7,7 @@ if defined?(ActiveRecord::Base) && !Sidekiq.server? ActiveSupport.on_load(:active_record) do ActiveRecord::Base.establish_connection - Rails.logger.debug("ActiveRecord connection established") + Rails.logger.debug("ActiveRecord connection established") # rubocop:disable Gitlab/RailsLogger end end end @@ -18,6 +18,6 @@ if defined?(ActiveRecord::Base) # as there's no need for the master process to hold a connection ActiveRecord::Base.connection.disconnect! - Rails.logger.debug("ActiveRecord connection disconnected") + Rails.logger.debug("ActiveRecord connection disconnected") # rubocop:disable Gitlab/RailsLogger end end diff --git a/config/initializers/active_record_migration.rb b/config/initializers/active_record_migration.rb deleted file mode 100644 index 04c06be7834..00000000000 --- a/config/initializers/active_record_migration.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'active_record/migration' - -module ActiveRecord - class Migration - # data_source_exists? is not available in 4.2.10, table_exists deprecated in 5.0 - def table_exists?(table_name) - ActiveRecord::Base.connection.data_source_exists?(table_name) - end - end -end diff --git a/config/initializers/active_record_mysql_timestamp.rb b/config/initializers/active_record_mysql_timestamp.rb deleted file mode 100644 index af74c4ff6fb..00000000000 --- a/config/initializers/active_record_mysql_timestamp.rb +++ /dev/null @@ -1,30 +0,0 @@ -# Make sure that MySQL won't try to use CURRENT_TIMESTAMP when the timestamp -# column is NOT NULL. See https://gitlab.com/gitlab-org/gitlab-ce/issues/36405 -# And also: https://bugs.mysql.com/bug.php?id=75098 -# This patch was based on: -# https://github.com/rails/rails/blob/15ef55efb591e5379486ccf53dd3e13f416564f6/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb#L34-L36 - -if Gitlab::Database.mysql? - require 'active_record/connection_adapters/abstract/schema_creation' - - module MySQLTimestampFix - def add_column_options!(sql, options) - # By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values, - # and assigning NULL assigns the current timestamp. To permit a TIMESTAMP - # column to contain NULL, explicitly declare it with the NULL attribute. - # See http://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html - if sql.end_with?('timestamp') && !options[:primary_key] - if options[:null] != false - sql << ' NULL' - elsif options[:column].default.nil? - sql << ' DEFAULT 0' - end - end - - super - end - end - - ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation - .prepend(MySQLTimestampFix) -end diff --git a/config/initializers/active_record_preloader.rb b/config/initializers/active_record_preloader.rb index 3b16014f302..a293909149e 100644 --- a/config/initializers/active_record_preloader.rb +++ b/config/initializers/active_record_preloader.rb @@ -1,9 +1,22 @@ module ActiveRecord module Associations class Preloader + class NullPreloader + def self.new(klass, owners, reflection, preload_scope) + self + end + + def self.run(preloader) + end + + def self.preloaded_records + [] + end + end + module NoCommitPreloader - def preloader_for(reflection, owners, rhs_klass) - return NullPreloader if rhs_klass == ::Commit + def preloader_for(reflection, owners) + return NullPreloader if owners.first.association(reflection.name).klass == ::Commit super end diff --git a/config/initializers/active_record_query_cache.rb b/config/initializers/active_record_query_cache.rb new file mode 100644 index 00000000000..61505a1edd3 --- /dev/null +++ b/config/initializers/active_record_query_cache.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +ActiveRecord::ConnectionAdapters::ConnectionPool.prepend Gitlab::Patch::ActiveRecordQueryCache diff --git a/config/initializers/active_record_verbose_query_logs.rb b/config/initializers/active_record_verbose_query_logs.rb deleted file mode 100644 index 1c5fbc8e830..00000000000 --- a/config/initializers/active_record_verbose_query_logs.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -# This is backport of https://github.com/rails/rails/pull/26815/files -# Enabled by default for every non-production environment - -module ActiveRecord - class LogSubscriber - module VerboseQueryLogs - def debug(progname = nil, &block) - return unless super - - log_query_source - end - - def log_query_source - source_line, line_number = extract_callstack(caller_locations) - - if source_line - if defined?(::Rails.root) - app_root = "#{::Rails.root}/".freeze - source_line = source_line.sub(app_root, "") - end - - logger.debug(" ↳ #{source_line}:#{line_number}") - end - end - - def extract_callstack(callstack) - line = callstack.find do |frame| - frame.absolute_path && !ignored_callstack(frame.absolute_path) - end - - offending_line = line || callstack.first - [ - offending_line.path, - offending_line.lineno, - offending_line.label - ] - end - - LOG_SUBSCRIBER_FILE = ActiveRecord::LogSubscriber.method(:logger).source_location.first - RAILS_GEM_ROOT = File.expand_path("../../../..", LOG_SUBSCRIBER_FILE) + "/" - APP_CONFIG_ROOT = File.expand_path("..", __dir__) + "/" - - def ignored_callstack(path) - path.start_with?(APP_CONFIG_ROOT, RAILS_GEM_ROOT, RbConfig::CONFIG["rubylibdir"]) - end - end - - if Rails.version.start_with?("5.2") - raise "Remove this monkey patch: #{__FILE__}" - else - prepend(VerboseQueryLogs) unless Rails.env.production? - end - end -end diff --git a/config/initializers/ar_mysql_jsonb_support.rb b/config/initializers/ar_mysql_jsonb_support.rb deleted file mode 100644 index 63a0b05119a..00000000000 --- a/config/initializers/ar_mysql_jsonb_support.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -require 'active_record/connection_adapters/abstract_mysql_adapter' -require 'active_record/connection_adapters/mysql/schema_definitions' - -# MySQL (5.6) and MariaDB (10.1) are currently supported versions within GitLab, -# Since they do not support native `json` datatype we force to emulate it as `text` - -if Gitlab::Database.mysql? - module ActiveRecord - module ConnectionAdapters - class AbstractMysqlAdapter - JSON_DATASIZE = 1.megabyte - - NATIVE_DATABASE_TYPES.merge!( - json: { name: "text", limit: JSON_DATASIZE }, - jsonb: { name: "text", limit: JSON_DATASIZE } - ) - end - - module MySQL - module ColumnMethods - # We add `jsonb` helper, as `json` is already defined for `MySQL` since Rails 5 - def jsonb(*args, **options) - args.each { |name| column(name, :json, options) } - end - end - end - end - end -end diff --git a/config/initializers/ar_native_database_types.rb b/config/initializers/ar_native_database_types.rb deleted file mode 100644 index 6d397661f75..00000000000 --- a/config/initializers/ar_native_database_types.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'active_record/connection_adapters/abstract_mysql_adapter' - -module ActiveRecord - module ConnectionAdapters - class AbstractMysqlAdapter - NATIVE_DATABASE_TYPES.merge!( - bigserial: { name: 'bigint(20) auto_increment PRIMARY KEY' }, - serial: { name: 'int auto_increment PRIMARY KEY' } - ) - end - end -end diff --git a/config/initializers/ar_speed_up_migration_checking.rb b/config/initializers/ar_speed_up_migration_checking.rb index f98b246db0b..c4ffcc54cb2 100644 --- a/config/initializers/ar_speed_up_migration_checking.rb +++ b/config/initializers/ar_speed_up_migration_checking.rb @@ -2,17 +2,14 @@ if Rails.env.test? require 'active_record/migration' module ActiveRecord - class Migrator - class << self - alias_method :migrations_unmemoized, :migrations + class MigrationContext + alias_method :migrations_unmemoized, :migrations - # This method is called a large number of times per rspec example, and - # it reads + parses `db/migrate/*` each time. Memoizing it can save 0.5 - # seconds per spec. - def migrations(paths) - @migrations ||= {} - (@migrations[paths] ||= migrations_unmemoized(paths)).dup - end + # This method is called a large number of times per rspec example, and + # it reads + parses `db/migrate/*` each time. Memoizing it can save 0.5 + # seconds per spec. + def migrations + @migrations ||= migrations_unmemoized end end end diff --git a/config/initializers/config_initializers_active_record_locking.rb b/config/initializers/config_initializers_active_record_locking.rb index 608d63223a3..915247826e9 100644 --- a/config/initializers/config_initializers_active_record_locking.rb +++ b/config/initializers/config_initializers_active_record_locking.rb @@ -22,10 +22,11 @@ module ActiveRecord # Patched because when `lock_version` is read as `0`, it may actually be `NULL` in the DB. possible_previous_lock_value = previous_lock_value.to_i == 0 ? [nil, 0] : previous_lock_value - affected_rows = self.class.unscoped._update_record( - arel_attributes_with_values(attribute_names), - self.class.primary_key => id_in_database, - locking_column => possible_previous_lock_value + affected_rows = self.class.unscoped.where( + locking_column => possible_previous_lock_value, + self.class.primary_key => id_in_database + ).update_all( + attributes_with_values_for_update(attribute_names) ) if affected_rows != 1 diff --git a/config/initializers/connection_fix.rb b/config/initializers/connection_fix.rb deleted file mode 100644 index d0b1444f607..00000000000 --- a/config/initializers/connection_fix.rb +++ /dev/null @@ -1,32 +0,0 @@ -# from http://gist.github.com/238999 -# -# If your workers are inactive for a long period of time, they'll lose -# their MySQL connection. -# -# This hack ensures we re-connect whenever a connection is -# lost. Because, really. why not? -# -# Stick this in RAILS_ROOT/config/initializers/connection_fix.rb (or somewhere similar) -# -# From: -# http://coderrr.wordpress.com/2009/01/08/activerecord-threading-issues-and-resolutions/ - -if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) - module ActiveRecord::ConnectionAdapters - class Mysql2Adapter - alias_method :execute_without_retry, :execute - - def execute(*args) - execute_without_retry(*args) - rescue ActiveRecord::StatementInvalid => e - if e.message =~ /server has gone away/i - warn "Lost connection to MySQL server during query" - reconnect! - retry - else - raise e - end - end - end - end -end diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 00000000000..608d0401a96 --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +csp_settings = Settings.gitlab.content_security_policy + +if csp_settings['enabled'] + # See https://guides.rubyonrails.org/security.html#content-security-policy + Rails.application.config.content_security_policy do |policy| + directives = csp_settings.fetch('directives', {}) + loader = ::Gitlab::ContentSecurityPolicy::ConfigLoader.new(directives) + loader.load(policy) + end + + Rails.application.config.content_security_policy_report_only = csp_settings['report_only'] + Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) } +end diff --git a/config/initializers/deprecations.rb b/config/initializers/deprecations.rb index 14616e726d9..0d096e34eb7 100644 --- a/config/initializers/deprecations.rb +++ b/config/initializers/deprecations.rb @@ -2,7 +2,7 @@ if Rails.env.development? || ENV['GITLAB_LEGACY_PATH_LOG_MESSAGE'] deprecator = ActiveSupport::Deprecation.new('11.0', 'GitLab') deprecator.behavior = -> (message, callstack) { - Rails.logger.warn("#{message}: #{callstack[1..20].join}") + Rails.logger.warn("#{message}: #{callstack[1..20].join}") # rubocop:disable Gitlab/RailsLogger } ActiveSupport::Deprecation.deprecate_methods(Gitlab::GitalyClient::StorageSettings, :legacy_disk_path, deprecator: deprecator) diff --git a/config/initializers/elastic_client_setup.rb b/config/initializers/elastic_client_setup.rb index 2ecb7956007..a1abb29838b 100644 --- a/config/initializers/elastic_client_setup.rb +++ b/config/initializers/elastic_client_setup.rb @@ -5,46 +5,42 @@ require 'gitlab/current_settings' Gitlab.ee do + require 'elasticsearch/model' + + ### Modified from elasticsearch-model/lib/elasticsearch/model.rb + + [ + Elasticsearch::Model::Client::ClassMethods, + Elasticsearch::Model::Naming::ClassMethods, + Elasticsearch::Model::Indexing::ClassMethods, + Elasticsearch::Model::Searching::ClassMethods + ].each do |mod| + Elasticsearch::Model::Proxy::ClassMethodsProxy.include mod + end + + [ + Elasticsearch::Model::Client::InstanceMethods, + Elasticsearch::Model::Naming::InstanceMethods, + Elasticsearch::Model::Indexing::InstanceMethods, + Elasticsearch::Model::Serializing::InstanceMethods + ].each do |mod| + Elasticsearch::Model::Proxy::InstanceMethodsProxy.include mod + end + + Elasticsearch::Model::Proxy::InstanceMethodsProxy.class_eval <<-CODE, __FILE__, __LINE__ + 1 + def as_indexed_json(options={}) + target.respond_to?(:as_indexed_json) ? target.__send__(:as_indexed_json, options) : super + end + CODE + + ### Monkey patches + Elasticsearch::Model::Response::Records.prepend GemExtensions::Elasticsearch::Model::Response::Records Elasticsearch::Model::Adapter::Multiple::Records.prepend GemExtensions::Elasticsearch::Model::Adapter::Multiple::Records Elasticsearch::Model::Indexing::InstanceMethods.prepend GemExtensions::Elasticsearch::Model::Indexing::InstanceMethods - - module Elasticsearch - module Model - module Client - # This mutex is only used to synchronize *creation* of a new client, so - # all including classes can share the same client instance - CLIENT_MUTEX = Mutex.new - - cattr_accessor :cached_client - cattr_accessor :cached_config - - module ClassMethods - # Override the default ::Elasticsearch::Model::Client implementation to - # return a client configured from application settings. All including - # classes will use the same instance, which is refreshed automatically - # if the settings change. - # - # _client is present to match the arity of the overridden method, where - # it is also not used. - # - # @return [Elasticsearch::Transport::Client] - def client(_client = nil) - store = ::Elasticsearch::Model::Client - - store::CLIENT_MUTEX.synchronize do - config = Gitlab::CurrentSettings.elasticsearch_config - - if store.cached_client.nil? || config != store.cached_config - store.cached_client = ::Gitlab::Elastic::Client.build(config) - store.cached_config = config - end - end - - store.cached_client - end - end - end - end - end + Elasticsearch::Model::Adapter::ActiveRecord::Importing.prepend GemExtensions::Elasticsearch::Model::Adapter::ActiveRecord::Importing + Elasticsearch::Model::Client::InstanceMethods.prepend GemExtensions::Elasticsearch::Model::Client + Elasticsearch::Model::Client::ClassMethods.prepend GemExtensions::Elasticsearch::Model::Client + Elasticsearch::Model::ClassMethods.prepend GemExtensions::Elasticsearch::Model::Client + Elasticsearch::Model.singleton_class.prepend GemExtensions::Elasticsearch::Model::Client end diff --git a/config/initializers/httpclient_patch.rb b/config/initializers/httpclient_patch.rb new file mode 100644 index 00000000000..22cc5605d9b --- /dev/null +++ b/config/initializers/httpclient_patch.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# By default, httpclient (and hence anything that uses rack-oauth2) +# ignores the system-wide SSL certificate configuration in favor of its +# own cacert.pem. This makes it impossible to use custom certificates +# without patching that file. Until +# https://github.com/nahi/httpclient/pull/386 is merged, we work around +# this limitation by forcing the HTTPClient SSL store to use the default +# system configuration. +module HTTPClient::SSLConfigDefaultPaths + def initialize(client) + super + + set_default_paths + end +end + +HTTPClient::SSLConfig.prepend HTTPClient::SSLConfigDefaultPaths diff --git a/config/initializers/invisible_captcha.rb b/config/initializers/invisible_captcha.rb new file mode 100644 index 00000000000..5177c730596 --- /dev/null +++ b/config/initializers/invisible_captcha.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +InvisibleCaptcha.setup do |config| + config.honeypots = %w(firstname lastname) + config.timestamp_enabled = true + config.timestamp_threshold = 4 +end diff --git a/config/initializers/load_balancing.rb b/config/initializers/load_balancing.rb index 029c0ff4277..a49bcbe1f96 100644 --- a/config/initializers/load_balancing.rb +++ b/config/initializers/load_balancing.rb @@ -3,7 +3,7 @@ # We need to run this initializer after migrations are done so it doesn't fail on CI Gitlab.ee do - if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.data_source_exists?('licenses') + if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('licenses') if Gitlab::Database::LoadBalancing.enable? Gitlab::Database.disable_prepared_statements diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb index 1ad93e14f7e..346725e4080 100644 --- a/config/initializers/lograge.rb +++ b/config/initializers/lograge.rb @@ -18,7 +18,7 @@ unless Sidekiq.server? .map { |k, v| { key: k, value: v } } payload = { - time: event.time.utc.iso8601(3), + time: Time.now.utc.iso8601(3), params: params, remote_ip: event.payload[:remote_ip], user_id: event.payload[:user_id], @@ -27,12 +27,7 @@ unless Sidekiq.server? queue_duration: event.payload[:queue_duration] } - gitaly_calls = Gitlab::GitalyClient.get_request_count - - if gitaly_calls > 0 - payload[:gitaly_calls] = gitaly_calls - payload[:gitaly_duration] = Gitlab::GitalyClient.query_time_ms - end + ::Gitlab::InstrumentationHelper.add_instrumentation_data(payload) payload[:response] = event.payload[:response] if event.payload[:response] payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id diff --git a/config/initializers/mysql_ignore_postgresql_options.rb b/config/initializers/mysql_ignore_postgresql_options.rb deleted file mode 100644 index 9a569be7674..00000000000 --- a/config/initializers/mysql_ignore_postgresql_options.rb +++ /dev/null @@ -1,49 +0,0 @@ -# This patches ActiveRecord so indexes created using the MySQL adapter ignore -# any PostgreSQL specific options (e.g. `using: :gin`). -# -# These patches do the following for MySQL: -# -# 1. Indexes created using the :opclasses option are ignored (as they serve no -# purpose on MySQL). -# 2. When creating an index with `using: :gin` the `using` option is discarded -# as :gin is not a valid value for MySQL. -# 3. The `:opclasses` option is stripped from add_index_options in case it's -# used anywhere other than in the add_index methods. - -if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) - module ActiveRecord - module ConnectionAdapters - class Mysql2Adapter < AbstractMysqlAdapter - alias_method :__gitlab_add_index, :add_index - alias_method :__gitlab_add_index_sql, :add_index_sql - alias_method :__gitlab_add_index_options, :add_index_options - - def add_index(table_name, column_name, options = {}) - unless options[:opclasses] - __gitlab_add_index(table_name, column_name, options) - end - end - - def add_index_sql(table_name, column_name, options = {}) - unless options[:opclasses] - __gitlab_add_index_sql(table_name, column_name, options) - end - end - - def add_index_options(table_name, column_name, options = {}) - if options[:using] && options[:using] == :gin - options = options.dup - options.delete(:using) - end - - if options[:opclasses] - options = options.dup - options.delete(:opclasses) - end - - __gitlab_add_index_options(table_name, column_name, options) - end - end - end - end -end diff --git a/config/initializers/mysql_set_length_for_binary_indexes.rb b/config/initializers/mysql_set_length_for_binary_indexes.rb deleted file mode 100644 index 552f3a20a95..00000000000 --- a/config/initializers/mysql_set_length_for_binary_indexes.rb +++ /dev/null @@ -1,30 +0,0 @@ -# This patches ActiveRecord so indexes for binary columns created using the -# MySQL adapter apply a length of 20. Otherwise MySQL can't create an index on -# binary columns. - -module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema - # This method is used in Rails 5 schema loading as t.index - def index(column_names, options = {}) - # Ignore indexes that use opclasses, - # also see config/initializers/mysql_ignore_postgresql_options.rb - if options[:opclasses] - warn "WARNING: index on columns #{column_names} uses unsupported option, skipping." - return - end - - options[:length] ||= {} - Array(column_names).each do |column_name| - column = columns.find { |c| c.name == column_name } - - if column&.type == :binary - options[:length][column_name] = 20 - end - end - - super(column_names, options) - end -end - -if defined?(ActiveRecord::ConnectionAdapters::MySQL::TableDefinition) - ActiveRecord::ConnectionAdapters::MySQL::TableDefinition.send(:prepend, MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema) -end diff --git a/config/initializers/octokit.rb b/config/initializers/octokit.rb new file mode 100644 index 00000000000..b3749258ec5 --- /dev/null +++ b/config/initializers/octokit.rb @@ -0,0 +1 @@ +Octokit.middleware.insert_after Octokit::Middleware::FollowRedirects, Gitlab::Octokit::Middleware diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb index d492b60705d..f9055285e5c 100644 --- a/config/initializers/peek.rb +++ b/config/initializers/peek.rb @@ -1,47 +1,13 @@ -Rails.application.config.peek.adapter = :redis, { client: ::Redis.new(Gitlab::Redis::Cache.params) } - -Peek.into Peek::Views::Host +require 'peek/adapters/redis' -if Gitlab::Database.mysql? - require 'peek-mysql2' - PEEK_DB_CLIENT = ::Mysql2::Client - PEEK_DB_VIEW = Peek::Views::Mysql2 -elsif Gitlab::Database.postgresql? - require 'peek-pg' - PEEK_DB_CLIENT = ::PG::Connection - PEEK_DB_VIEW = Peek::Views::PG +Peek::Adapters::Redis.prepend ::Gitlab::PerformanceBar::RedisAdapterWhenPeekEnabled - # Remove once we have https://github.com/peek/peek-pg/pull/10 - module ::Peek::PGInstrumented - def exec_params(*args) - start = Time.now - super(*args) - ensure - duration = (Time.now - start) - PEEK_DB_CLIENT.query_time.update { |value| value + duration } - PEEK_DB_CLIENT.query_count.update { |value| value + 1 } - end - end -else - raise "Unsupported database adapter for peek!" -end +Rails.application.config.peek.adapter = :redis, { client: ::Redis.new(Gitlab::Redis::Cache.params) } -Peek.into PEEK_DB_VIEW +Peek.into Peek::Views::Host +Peek.into Peek::Views::ActiveRecord Peek.into Peek::Views::Gitaly -Peek.into Peek::Views::Rblineprof -Peek.into Peek::Views::Redis -Peek.into Peek::Views::GC -Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled? - -# rubocop:disable Naming/ClassAndModuleCamelCase -class PEEK_DB_CLIENT - class << self - attr_accessor :query_details - end - self.query_details = Concurrent::Array.new -end - -PEEK_DB_VIEW.prepend ::Gitlab::PerformanceBar::PeekQueryTracker +Peek.into Peek::Views::RedisDetailed +Peek.into Peek::Views::Rugged -require 'peek/adapters/redis' -Peek::Adapters::Redis.prepend ::Gitlab::PerformanceBar::RedisAdapterWhenPeekEnabled +Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled? diff --git a/config/initializers/postgresql_cte.rb b/config/initializers/postgresql_cte.rb index 56689bc8e74..68d53c4edbf 100644 --- a/config/initializers/postgresql_cte.rb +++ b/config/initializers/postgresql_cte.rb @@ -94,8 +94,8 @@ module ActiveRecord end end - def build_arel - arel = super() + def build_arel(aliases) + arel = super build_with(arel) if @values[:with] diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb deleted file mode 100644 index 7e912180820..00000000000 --- a/config/initializers/postgresql_opclasses_support.rb +++ /dev/null @@ -1,211 +0,0 @@ -# rubocop:disable all - -# These changes add support for PostgreSQL operator classes when creating -# indexes and dumping/loading schemas. Taken from Rails pull request -# https://github.com/rails/rails/pull/19090. -# -# License: -# -# Copyright (c) 2004-2016 David Heinemeier Hansson -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -require 'date' -require 'set' -require 'bigdecimal' -require 'bigdecimal/util' - -# As the Struct definition is changed in this PR/patch we have to first remove -# the existing one. -ActiveRecord::ConnectionAdapters.send(:remove_const, :IndexDefinition) - -module ActiveRecord - module ConnectionAdapters #:nodoc: - # Abstract representation of an index definition on a table. Instances of - # this type are typically created and returned by methods in database - # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes - attrs = [:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :comment, :opclasses] - - class IndexDefinition < Struct.new(*attrs) #:nodoc: - end - end -end - - -module ActiveRecord - module ConnectionAdapters # :nodoc: - module SchemaStatements - def add_index_options(table_name, column_name, options = {}) #:nodoc: - column_names = Array(column_name) - index_name = index_name(table_name, column: column_names) - - options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type, :opclasses) - - index_type = options[:unique] ? "UNIQUE" : "" - index_type = options[:type].to_s if options.key?(:type) - index_name = options[:name].to_s if options.key?(:name) - max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length - - if options.key?(:algorithm) - algorithm = index_algorithms.fetch(options[:algorithm]) { - raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}") - } - end - - using = "USING #{options[:using]}" if options[:using].present? - - if supports_partial_index? - index_options = options[:where] ? " WHERE #{options[:where]}" : "" - end - - if index_name.length > max_index_length - raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters" - end - if data_source_exists?(table_name) && index_name_exists?(table_name, index_name) - raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists" - end - index_columns = quoted_columns_for_index(column_names, options).join(", ") - - [index_name, index_type, index_columns, index_options, algorithm, using] - end - end - end -end - -module ActiveRecord - module ConnectionAdapters - module PostgreSQL - module SchemaStatements - # Returns an array of indexes for the given table. - def indexes(table_name, name = nil) - result = query(<<-SQL, 'SCHEMA') - SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid - FROM pg_class t - INNER JOIN pg_index d ON t.oid = d.indrelid - INNER JOIN pg_class i ON d.indexrelid = i.oid - WHERE i.relkind = 'i' - AND d.indisprimary = 'f' - AND t.relname = '#{table_name}' - AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) ) - ORDER BY i.relname - SQL - - result.map do |row| - index_name = row[0] - unique = row[1] - indkey = row[2].split(" ").map(&:to_i) - inddef = row[3] - oid = row[4] - - columns = Hash[query(<<-SQL, "SCHEMA")] - SELECT a.attnum, a.attname - FROM pg_attribute a - WHERE a.attrelid = #{oid} - AND a.attnum IN (#{indkey.join(",")}) - SQL - - column_names = columns.values_at(*indkey).compact - - unless column_names.empty? - # add info on sort order for columns (only desc order is explicitly specified, asc is the default) - desc_order_columns = inddef.scan(/(\w+) DESC/).flatten - orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {} - where = inddef.scan(/WHERE (.+)$/).flatten[0] - using = inddef.scan(/USING (.+?) /).flatten[0].to_sym - opclasses = Hash[inddef.scan(/\((.+?)\)(?:$| WHERE )/).flatten[0].split(',').map do |column_and_opclass| - column, opclass = column_and_opclass.split(' ').map(&:strip) - end.reject do |column, opclass| - ['desc', 'asc'].include?(opclass&.downcase) - end.map do |column, opclass| - [column, opclass] if opclass - end.compact] - - index_attrs = [table_name, index_name, unique, column_names, [], orders, where, nil, using, nil, opclasses] - - IndexDefinition.new(*index_attrs) - end - end.compact - end - - def add_index(table_name, column_name, options = {}) #:nodoc: - index_name, index_type, index_columns_and_opclasses, index_options, index_algorithm, index_using = add_index_options(table_name, column_name, options) - execute "CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns_and_opclasses})#{index_options}" - end - - protected - - def quoted_columns_for_index(column_names, options = {}) - column_opclasses = options[:opclasses] || {} - column_names.map {|name| "#{quote_column_name(name)} #{column_opclasses[name]}"} - - quoted_columns = Hash[column_names.map { |name| [name.to_sym, "#{quote_column_name(name)} #{column_opclasses[name]}"] }] - add_options_for_index_columns(quoted_columns, options).values - end - end - end - end -end - -module ActiveRecord - class SchemaDumper - private - - def indexes(table, stream) - if (indexes = @connection.indexes(table)).any? - add_index_statements = indexes.map do |index| - table_name = remove_prefix_and_suffix(index.table).inspect - " add_index #{([table_name]+index_parts(index)).join(', ')}" - end - - stream.puts add_index_statements.sort.join("\n") - stream.puts - end - end - - def indexes_in_create(table, stream) - if (indexes = @connection.indexes(table)).any? - index_statements = indexes.map do |index| - " t.index #{index_parts(index).join(', ')}" - end - stream.puts index_statements.sort.join("\n") - end - end - - def index_parts(index) - index_parts = [ - index.columns.inspect, - "name: #{index.name.inspect}", - ] - index_parts << "unique: true" if index.unique - index_parts << "length: { #{format_options(index.lengths)} }" if index.lengths.present? - index_parts << "order: { #{format_options(index.orders)} }" if index.orders.present? - index_parts << "where: #{index.where.inspect}" if index.where - index_parts << "using: #{index.using.inspect}" if index.using - index_parts << "type: #{index.type.inspect}" if index.type - index_parts << "opclasses: #{index.opclasses.inspect}" if index.opclasses.present? - index_parts << "comment: #{index.comment.inspect}" if index.comment - index_parts - end - - def format_options(options) - options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ") - end - end -end diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb index 7eb34bd69e5..b43fff24bb0 100644 --- a/config/initializers/rack_attack_logging.rb +++ b/config/initializers/rack_attack_logging.rb @@ -7,9 +7,9 @@ ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, r rack_attack_info = { message: 'Rack_Attack', env: req.env['rack.attack.match_type'], - ip: req.ip, + remote_ip: req.ip, request_method: req.request_method, - fullpath: req.fullpath + path: req.fullpath } if %w(throttle_authenticated_api throttle_authenticated_web).include? req.env['rack.attack.matched'] diff --git a/config/initializers/rack_timeout.rb b/config/initializers/rack_timeout.rb index 58f46b55725..246cf3482a4 100644 --- a/config/initializers/rack_timeout.rb +++ b/config/initializers/rack_timeout.rb @@ -14,8 +14,8 @@ if defined?(::Puma) && !Rails.env.test? Gitlab::Application.configure do |config| config.middleware.insert_before(Rack::Runtime, Rack::Timeout, - service_timeout: 60, - wait_timeout: 90) + service_timeout: ENV.fetch('GITLAB_RAILS_RACK_TIMEOUT', 60).to_i, + wait_timeout: ENV.fetch('GITLAB_RAILS_WAIT_TIMEOUT', 90).to_i) end observer = Gitlab::Cluster::RackTimeoutObserver.new diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index f9ef5d66bfa..9f3e104bc2b 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -28,16 +28,20 @@ if Rails.env.development? end enable_json_logs = Gitlab.config.sidekiq.log_format == 'json' +enable_sidekiq_monitor = ENV.fetch("SIDEKIQ_MONITOR_WORKER", 0).to_i.nonzero? Sidekiq.configure_server do |config| config.redis = queues_config_hash config.server_middleware do |chain| + chain.add Gitlab::SidekiqMiddleware::Monitor if enable_sidekiq_monitor + chain.add Gitlab::SidekiqMiddleware::Metrics if Settings.monitoring.sidekiq_exporter chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS'] && !enable_json_logs chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'] chain.add Gitlab::SidekiqMiddleware::RequestStoreMiddleware unless ENV['SIDEKIQ_REQUEST_STORE'] == '0' chain.add Gitlab::SidekiqMiddleware::BatchLoader chain.add Gitlab::SidekiqMiddleware::CorrelationLogger + chain.add Gitlab::SidekiqMiddleware::InstrumentationLogger chain.add Gitlab::SidekiqStatus::ServerMiddleware end @@ -55,6 +59,8 @@ Sidekiq.configure_server do |config| # Clear any connections that might have been obtained before starting # Sidekiq (e.g. in an initializer). ActiveRecord::Base.clear_all_connections! + + Gitlab::SidekiqMonitor.instance.start if enable_sidekiq_monitor end if enable_reliable_fetch? @@ -72,7 +78,7 @@ Sidekiq.configure_server do |config| cron_jobs[k]['class'] = cron_jobs[k].delete('job_class') else cron_jobs.delete(k) - Rails.logger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.") + Rails.logger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.") # rubocop:disable Gitlab/RailsLogger end end Sidekiq::Cron::Job.load_from_hash! cron_jobs @@ -83,7 +89,7 @@ Sidekiq.configure_server do |config| Rails.application.config.database_configuration[Rails.env] db_config['pool'] = Sidekiq.options[:concurrency] ActiveRecord::Base.establish_connection(db_config) - Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{ActiveRecord::Base.connection.pool.instance_variable_get('@size')}") + Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{ActiveRecord::Base.connection.pool.instance_variable_get('@size')}") # rubocop:disable Gitlab/RailsLogger Gitlab.ee do Gitlab::Mirror.configure_cron_job! @@ -94,7 +100,7 @@ Sidekiq.configure_server do |config| Rails.configuration.geo_database['pool'] = Sidekiq.options[:concurrency] Geo::TrackingBase.establish_connection(Rails.configuration.geo_database) - Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{Geo::TrackingBase.connection_pool.size} (Geo tracking database)") + Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{Geo::TrackingBase.connection_pool.size} (Geo tracking database)") # rubocop:disable Gitlab/RailsLogger end end diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb index 3c8779f238f..5b55a06692e 100644 --- a/config/initializers/tracing.rb +++ b/config/initializers/tracing.rb @@ -21,9 +21,13 @@ if Labkit::Tracing.enabled? end end + # Instrument Redis + Labkit::Tracing::Redis.instrument + # Instrument Rails Labkit::Tracing::Rails::ActiveRecordSubscriber.instrument Labkit::Tracing::Rails::ActionViewSubscriber.instrument + Labkit::Tracing::Rails::ActiveSupportSubscriber.instrument # In multi-processed clustered architectures (puma, unicorn) don't # start tracing until the worker processes are spawned. This works diff --git a/config/initializers/zz_metrics.rb b/config/initializers/zz_metrics.rb index 5aa6f73c5c5..af4aec7b355 100644 --- a/config/initializers/zz_metrics.rb +++ b/config/initializers/zz_metrics.rb @@ -6,6 +6,7 @@ # that we can stub it for testing, as it is only called when metrics are # enabled. # +# rubocop:disable Metrics/AbcSize def instrument_classes(instrumentation) instrumentation.instrument_instance_methods(Gitlab::Shell) @@ -53,7 +54,7 @@ def instrument_classes(instrumentation) instrumentation.instrument_methods(Banzai::Querying) instrumentation.instrument_instance_methods(Banzai::ObjectRenderer) - instrumentation.instrument_instance_methods(Banzai::Redactor) + instrumentation.instrument_instance_methods(Banzai::ReferenceRedactor) [Issuable, Mentionable, Participable].each do |klass| instrumentation.instrument_instance_methods(klass) @@ -86,12 +87,38 @@ def instrument_classes(instrumentation) instrumentation.instrument_methods(Gitlab::Highlight) instrumentation.instrument_instance_methods(Gitlab::Highlight) + Gitlab.ee do + instrumentation.instrument_methods(Elasticsearch::Git::Repository) + instrumentation.instrument_instance_methods(Elasticsearch::Git::Repository) + + instrumentation.instrument_instance_methods(Search::GlobalService) + instrumentation.instrument_instance_methods(Search::ProjectService) + + instrumentation.instrument_instance_methods(Gitlab::Elastic::SearchResults) + instrumentation.instrument_instance_methods(Gitlab::Elastic::ProjectSearchResults) + instrumentation.instrument_instance_methods(Gitlab::Elastic::Indexer) + instrumentation.instrument_instance_methods(Gitlab::Elastic::SnippetSearchResults) + instrumentation.instrument_methods(Gitlab::Elastic::Helper) + + instrumentation.instrument_instance_methods(Elastic::ApplicationVersionedSearch) + instrumentation.instrument_instance_methods(Elastic::ProjectsSearch) + instrumentation.instrument_instance_methods(Elastic::RepositoriesSearch) + instrumentation.instrument_instance_methods(Elastic::SnippetsSearch) + instrumentation.instrument_instance_methods(Elastic::WikiRepositoriesSearch) + + instrumentation.instrument_instance_methods(Gitlab::BitbucketImport::Importer) + instrumentation.instrument_instance_methods(Bitbucket::Connection) + + instrumentation.instrument_instance_methods(Geo::RepositorySyncWorker) + end + # This is a Rails scope so we have to instrument it manually. instrumentation.instrument_method(Project, :visible_to_user) # Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159 instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits) end +# rubocop:enable Metrics/AbcSize # With prometheus enabled by default this breaks all specs # that stubs methods using `any_instance_of` for the models reloaded here. |