Commit b8fbd34d authored by Sean McGivern's avatar Sean McGivern

Declare loggable non-numeric arguments in worker classes

Having these in a hash in the SidekiqProcessor has a few problems:

1. It's very far away from the definition of `perform`, so it's hard to
   verify.
2. That also makes it harder to notice.
3. The big hash is more prone to conflicts or ordering issues.

This adds a `loggable_arguments` method to `ApplicationWorker`. When
called with any arguments, it acts as a getter. When called with no
arguments, it acts as a getter.

The arguments have to be declared by position, because we don't know
what they're called in Sidekiq. There is also no need to mark numeric
arguments as loggable as they are loggable anyway.
parent 8dbf036e
......@@ -9,6 +9,7 @@ class AuthorizedKeysWorker
urgency :high
weight 2
idempotent!
loggable_arguments 0
def perform(action, *args)
return unless Gitlab::CurrentSettings.authorized_keys_enabled?
......
......@@ -5,6 +5,7 @@ class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :database
urgency :throttled
loggable_arguments 0, 1
# The minimum amount of time between processing two jobs of the same migration
# class.
......
......@@ -5,6 +5,7 @@ class CleanupContainerRepositoryWorker # rubocop:disable Scalability/IdempotentW
queue_namespace :container_repository
feature_category :container_registry
loggable_arguments 2
attr_reader :container_repository, :current_user
......
......@@ -6,6 +6,7 @@ class ClusterInstallAppWorker # rubocop:disable Scalability/IdempotentWorker
include ClusterApplications
worker_has_external_dependencies!
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -6,6 +6,7 @@ class ClusterPatchAppWorker # rubocop:disable Scalability/IdempotentWorker
include ClusterApplications
worker_has_external_dependencies!
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -9,6 +9,7 @@ class ClusterUpdateAppWorker # rubocop:disable Scalability/IdempotentWorker
include ExclusiveLeaseGuard
sidekiq_options retry: 3, dead: false
loggable_arguments 0, 3
LEASE_TIMEOUT = 10.minutes.to_i
......
......@@ -6,6 +6,7 @@ class ClusterUpgradeAppWorker # rubocop:disable Scalability/IdempotentWorker
include ClusterApplications
worker_has_external_dependencies!
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -10,6 +10,7 @@ class ClusterWaitForAppInstallationWorker # rubocop:disable Scalability/Idempote
worker_has_external_dependencies!
worker_resource_boundary :cpu
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -8,6 +8,8 @@ class ClusterWaitForAppUpdateWorker # rubocop:disable Scalability/IdempotentWork
INTERVAL = 10.seconds
TIMEOUT = 20.minutes
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
::Clusters::Applications::CheckUpgradeProgressService.new(app).execute
......
......@@ -6,6 +6,7 @@ class ClusterWaitForIngressIpAddressWorker # rubocop:disable Scalability/Idempot
include ClusterApplications
worker_has_external_dependencies!
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -6,6 +6,8 @@ module Clusters
include ApplicationWorker
include ClusterQueue
loggable_arguments 1
def perform(cluster_id, service_name)
cluster = Clusters::Cluster.find_by_id(cluster_id)
return unless cluster
......
......@@ -6,6 +6,8 @@ module Clusters
include ApplicationWorker
include ClusterQueue
loggable_arguments 1
def perform(cluster_id, service_name)
cluster = Clusters::Cluster.find_by_id(cluster_id)
raise cluster_missing_error(service_name) unless cluster
......
......@@ -8,6 +8,7 @@ module Clusters
include ClusterApplications
worker_has_external_dependencies!
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -12,6 +12,7 @@ module Clusters
worker_has_external_dependencies!
worker_resource_boundary :cpu
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
......
......@@ -76,6 +76,22 @@ module ApplicationWorker
get_sidekiq_options['queue'].to_s
end
# Set/get which arguments can be logged and sent to Sentry.
#
# Numeric arguments are logged by default, so there is no need to
# list those.
#
# Non-numeric arguments must be listed by position, as Sidekiq
# cannot see argument names.
#
def loggable_arguments(*args)
if args.any?
@loggable_arguments = args
else
@loggable_arguments || []
end
end
def queue_size
Sidekiq::Queue.new(queue).size
end
......
......@@ -7,6 +7,7 @@ module ReactiveCacheableWorker
include ApplicationWorker
feature_category_not_owned!
loggable_arguments 0
def self.context_for_arguments(arguments)
class_name, *_other_args = arguments
......
......@@ -5,8 +5,8 @@ class CreateCommitSignatureWorker
feature_category :source_code_management
weight 2
idempotent!
loggable_arguments 0
# rubocop: disable CodeReuse/ActiveRecord
def perform(commit_shas, project_id)
......
......@@ -8,6 +8,7 @@ class CreatePipelineWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :continuous_integration
urgency :high
worker_resource_boundary :cpu
loggable_arguments 2, 3, 4
def perform(project_id, user_id, ref, source, params = {})
project = Project.find(project_id)
......
......@@ -4,6 +4,7 @@ class DeleteStoredFilesWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
feature_category_not_owned!
loggable_arguments 0
def perform(class_name, keys)
klass = begin
......
......@@ -4,6 +4,7 @@ class DeleteUserWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
feature_category :authentication_and_authorization
loggable_arguments 2
def perform(current_user_id, delete_user_id, options = {})
delete_user = User.find(delete_user_id)
......
......@@ -5,6 +5,7 @@ class ExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :issue_tracking
worker_resource_boundary :cpu
loggable_arguments 2
def perform(current_user_id, project_id, params)
@current_user = User.find(current_user_id)
......
......@@ -5,6 +5,7 @@ class FileHookWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: false
feature_category :integrations
loggable_arguments 0
def perform(file_name, data)
success, message = Gitlab::FileHook.execute(file_name, data)
......
......@@ -5,6 +5,7 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: false
feature_category :gitaly
loggable_arguments 1, 2, 3
# Timeout set to 24h
LEASE_TIMEOUT = 86400
......
......@@ -12,6 +12,7 @@ module Gitlab
sidekiq_options dead: false
feature_category :importers
loggable_arguments 1, 2
# The known importer stages and their corresponding Sidekiq workers.
STAGES = {
......
......@@ -8,6 +8,8 @@ module Gitlab
include Gitlab::JiraImport::QueueOptions
include Gitlab::Import::DatabaseHelpers
loggable_arguments 3
def perform(project_id, jira_issue_id, issue_attributes, waiter_key)
issue_id = create_issue(issue_attributes, project_id)
JiraImport.cache_issue_mapping(issue_id, jira_issue_id, project_id)
......
......@@ -7,6 +7,7 @@ class GitlabShellWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :source_code_management
urgency :high
weight 2
loggable_arguments 0
def perform(action, *arg)
# Gitlab::Shell is being removed but we need to continue to process jobs
......
......@@ -5,6 +5,7 @@ class GroupExportWorker # rubocop:disable Scalability/IdempotentWorker
include ExceptionBacktrace
feature_category :importers
loggable_arguments 2
def perform(current_user_id, group_id, params = {})
current_user = User.find(current_user_id)
......
......@@ -5,6 +5,7 @@ module HashedStorage
include ApplicationWorker
queue_namespace :hashed_storage
loggable_arguments 1
attr_reader :project_id
......
......@@ -5,6 +5,7 @@ module HashedStorage
include ApplicationWorker
queue_namespace :hashed_storage
loggable_arguments 1
attr_reader :project_id
......
......@@ -9,6 +9,7 @@ module MailScheduler
feature_category :issue_tracking
worker_resource_boundary :cpu
loggable_arguments 0
def perform(meth, *args)
check_arguments!(args)
......
......@@ -6,6 +6,7 @@ class MergeWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :source_code_management
urgency :high
weight 5
loggable_arguments 2
def perform(merge_request_id, current_user_id, params)
params = params.with_indifferent_access
......
......@@ -7,6 +7,7 @@ module ObjectStorage
sidekiq_options retry: 5
feature_category_not_owned!
loggable_arguments 0, 1, 2, 3
def perform(uploader_class_name, subject_class_name, file_field, subject_id)
uploader_class = uploader_class_name.constantize
......
......@@ -7,6 +7,7 @@ module ObjectStorage
include ObjectStorageQueue
feature_category_not_owned!
loggable_arguments 0, 1, 2, 3
SanityCheckError = Class.new(StandardError)
......
......@@ -5,6 +5,7 @@ class PagesWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
feature_category :pages
loggable_arguments 0, 1
def perform(action, *arg)
send(action, *arg) # rubocop:disable GitlabSecurity/PublicSend
......
......@@ -7,6 +7,7 @@ class PipelineProcessWorker # rubocop:disable Scalability/IdempotentWorker
queue_namespace :pipeline_processing
feature_category :continuous_integration
urgency :high
loggable_arguments 1
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id, build_ids = nil)
......
......@@ -7,6 +7,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
urgency :high
worker_resource_boundary :cpu
weight 5
loggable_arguments 0, 1, 2, 3
def perform(gl_repository, identifier, changes, push_options = {})
container, project, repo_type = Gitlab::GlRepository.parse(gl_repository)
......
......@@ -13,8 +13,8 @@ class ProcessCommitWorker
feature_category :source_code_management
urgency :high
weight 3
idempotent!
loggable_arguments 2, 3
# project_id - The ID of the project this commit belongs to.
# user_id - The ID of the user that pushed the commit.
......
......@@ -4,11 +4,11 @@
class ProjectCacheWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
urgency :high
LEASE_TIMEOUT = 15.minutes.to_i
feature_category :source_code_management
urgency :high
loggable_arguments 1, 2, 3
# project_id - The ID of the project for which to flush the cache.
# files - An Array containing extra types of files to refresh such as
......
......@@ -8,6 +8,7 @@ class ProjectExportWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :importers
worker_resource_boundary :memory
urgency :throttled
loggable_arguments 2, 3
def perform(current_user_id, project_id, after_export_strategy = {}, params = {})
current_user = User.find(current_user_id)
......
......@@ -4,8 +4,8 @@ class PropagateIntegrationWorker
include ApplicationWorker
feature_category :integrations
idempotent!
loggable_arguments 1
def perform(integration_id, overwrite)
Admin::PropagateIntegrationService.propagate(
......
......@@ -7,6 +7,7 @@ class RebaseWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :source_code_management
weight 2
loggable_arguments 2
def perform(merge_request_id, current_user_id, skip_ci = false)
current_user = User.find(current_user_id)
......
......@@ -12,6 +12,8 @@ module RepositoryCheck
attr_reader :shard_name
loggable_arguments 0
def perform(shard_name)
@shard_name = shard_name
......
......@@ -5,6 +5,7 @@ class RepositoryRemoveRemoteWorker # rubocop:disable Scalability/IdempotentWorke
include ExclusiveLeaseGuard
feature_category :source_code_management
loggable_arguments 1
LEASE_TIMEOUT = 1.hour
......
......@@ -10,6 +10,7 @@ class RepositoryUpdateRemoteMirrorWorker # rubocop:disable Scalability/Idempoten
sidekiq_options retry: 3, dead: false
feature_category :source_code_management
loggable_arguments 1
LOCK_WAIT_TIME = 30.seconds
MAX_TRIES = 3
......
......@@ -5,6 +5,8 @@ module TodosDestroyer
include ApplicationWorker
include TodosDestroyerQueue
loggable_arguments 2
def perform(user_id, entity_id, entity_type)
::Todos::Destroy::EntityLeaveService.new(user_id, entity_id, entity_type).execute
end
......
......@@ -5,6 +5,7 @@ class UpdateExternalPullRequestsWorker # rubocop:disable Scalability/IdempotentW
feature_category :source_code_management
weight 3
loggable_arguments 2
def perform(project_id, user_id, ref)
project = Project.find_by_id(project_id)
......
......@@ -7,6 +7,7 @@ class UpdateMergeRequestsWorker # rubocop:disable Scalability/IdempotentWorker
urgency :high
worker_resource_boundary :cpu
weight 3
loggable_arguments 2, 3, 4
LOG_TIME_THRESHOLD = 90 # seconds
......
......@@ -5,6 +5,7 @@ class WebHookWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :integrations
worker_has_external_dependencies!
loggable_arguments 2
sidekiq_options retry: 4, dead: false
......
......@@ -32,8 +32,7 @@ gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "1"}
This does not log all job arguments. To avoid logging sensitive
information (for instance, password reset tokens), it logs numeric
arguments for all workers, with overrides for some specific workers
where their arguments are not sensitive. Permitted non-numeric arguments
for specific workers can be seen in the [Sidekiq Processor source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/error_tracking/processor/sidekiq_processor.rb).
where their arguments are not sensitive.
Example log output:
......
......@@ -518,6 +518,34 @@ job needs to be scheduled with.
The `context_proc` which needs to return a hash with the context
information for the job.
## Arguments logging
When [`SIDEKIQ_LOG_ARGUMENTS`](../administration/troubleshooting/sidekiq.md#log-arguments-to-sidekiq-jobs)
is enabled, Sidekiq job arguments will be logged.
By default, the only arguments logged are numeric arguments, because
arguments of other types could contain sensitive information. To
override this, use `loggable_arguments` inside a worker with the indexes
of the arguments to be logged. (Numeric arguments do not need to be
specified here.)
For example:
```ruby
class MyWorker
include ApplicationWorker
loggable_arguments 1, 3
# object_id will be logged as it's numeric
# string_a will be logged due to the loggable_arguments call
# string_b will be filtered from logs
# string_c will be logged due to the loggable_arguments call
def perform(object_id, string_a, string_b, string_c)
end
end
```
## Tests
Each Sidekiq worker must be tested using RSpec, just like any other class. These
......@@ -591,7 +619,7 @@ to be merged and deployed before additional changes are merged.
1. In a further merge request, update `ExampleWorker.perform_async` calls to
use the new argument.
##### Parameter hash
##### Parameter hash
This approach will not require multiple deployments if an existing worker already
utilizes a parameter hash.
......
......@@ -5,8 +5,8 @@ module Analytics
include ApplicationWorker
feature_category :code_analytics
idempotent!
loggable_arguments 0
def perform(operation, merge_request_id, execute_kwargs = {})
::MergeRequest.find_by_id(merge_request_id).try do |merge_request|
......
......@@ -18,6 +18,7 @@ module Geo
include ::Gitlab::Utils::StrongMemoize
sidekiq_options retry: false
loggable_arguments 0
attr_reader :shard_name, :start_time, :loops
end
......
......@@ -8,6 +8,7 @@ class ElasticCommitIndexerWorker
sidekiq_options retry: 2
urgency :throttled
idempotent!
loggable_arguments 1, 2, 3
# Performs the commits and blobs indexation
#
......
......@@ -7,6 +7,7 @@ class ElasticIndexerWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 2
feature_category :global_search
urgency :throttled
loggable_arguments 0, 1, 4
def perform(operation, class_name, record_id, es_id, options = {})
return true unless Gitlab::CurrentSettings.elasticsearch_indexing?
......
......@@ -5,6 +5,7 @@ class ElasticNamespaceIndexerWorker # rubocop:disable Scalability/IdempotentWork
feature_category :global_search
sidekiq_options retry: 2
loggable_arguments 1
def perform(namespace_id, operation)
return true unless Gitlab::CurrentSettings.elasticsearch_indexing?
......
......@@ -5,6 +5,7 @@ class ElasticNamespaceRolloutWorker # rubocop:disable Scalability/IdempotentWork
feature_category :global_search
sidekiq_options retry: 2
loggable_arguments 0, 2
ROLLOUT = 'rollout'
ROLLBACK = 'rollback'
......
......@@ -18,6 +18,8 @@ module Geo
OPERATIONS = [:resync_repositories, :reverify_repositories].freeze
DELAY_INTERVAL = 10.seconds.to_i # base delay for scheduling batch execution
loggable_arguments 0
def perform(operation)
return fail_invalid_operation!(operation) unless OPERATIONS.include?(operation.to_sym)
......
......@@ -14,6 +14,8 @@ module Geo
BATCH_SIZE = 250
OPERATIONS = [:resync_repositories, :reverify_repositories].freeze
loggable_arguments 0, 1
def perform(operation, range)
case operation.to_sym
when :resync_repositories
......
......@@ -9,6 +9,7 @@ module Geo
sidekiq_options retry: 3, dead: false
idempotent!
loggable_arguments 0
def perform(replicable_name, replicable_id)
replicator = ::Gitlab::Geo::Replicator.for_replicable_params(replicable_name: replicable_name, replicable_id: replicable_id)
......
......@@ -7,6 +7,7 @@ module Geo
include ::Gitlab::Geo::LogHelpers
sidekiq_options retry: 3, dead: false
loggable_arguments 0, 1, 2
def perform(replicable_name, event_name, payload)
Geo::EventService.new(replicable_name, event_name, payload).execute
......
......@@ -6,6 +6,7 @@ module Geo
include GeoQueue
sidekiq_options retry: 3, dead: false
loggable_arguments 0
def perform(object_type, object_id)
Geo::FileDownloadService.new(object_type.to_sym, object_id).execute
......
......@@ -6,6 +6,8 @@ module Geo
include GeoQueue
include ::Gitlab::Geo::LogHelpers
loggable_arguments 0, 2
def perform(object_type, object_db_id, file_path = nil)
log_info('Executing Geo::FileRegistryRemovalService', id: object_db_id, type: object_type, file_path: file_path)
......
......@@ -6,6 +6,8 @@ module Geo
include Gitlab::Geo::LogHelpers
include GeoQueue
loggable_arguments 0
def perform(file_path)
remove_file!(file_path)
end
......
......@@ -5,6 +5,8 @@ module Geo
include ApplicationWorker
include GeoQueue
loggable_arguments 1, 2
def perform(project_id, old_attachments_path, new_attachments_path)
Geo::HashedStorageAttachmentsMigrationService.new(
project_id,
......
......@@ -5,6 +5,8 @@ module Geo
include ApplicationWorker
include GeoQueue
loggable_arguments 1, 2, 2
def perform(project_id, old_disk_path, new_disk_path, old_storage_version)
Geo::HashedStorageMigrationService.new(
project_id,
......
......@@ -14,6 +14,8 @@ module Geo
Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
end
loggable_arguments 1
# rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, options = {})
options.symbolize_keys!
......
......@@ -5,6 +5,8 @@ module Geo
include ApplicationWorker
include GeoQueue
loggable_arguments 1, 2
def perform(project_id, old_disk_path, new_disk_path)
Geo::RenameRepositoryService.new(project_id, old_disk_path, new_disk_path).execute
end
......
......@@ -7,6 +7,8 @@ module Geo
include ::Gitlab::Geo::LogHelpers
include ::Gitlab::Utils::StrongMemoize
loggable_arguments 1, 2, 3
def perform(project_id, name, disk_path, storage_name)
return unless current_node.secondary?
......
......@@ -3,6 +3,7 @@
module Geo
class RepositoryShardSyncWorker < Geo::Scheduler::Secondary::SchedulerWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: false
loggable_arguments 0
attr_accessor :shard_name
......
......@@ -5,6 +5,7 @@ module Geo
module Primary
class ShardWorker < Geo::Scheduler::Primary::SchedulerWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: false
loggable_arguments 0
attr_accessor :shard_name
......
......@@ -10,6 +10,8 @@ module Geo
# rubocop:enable Scalability/CronWorkerContext
attr_accessor :shard_name
loggable_arguments 0
def perform(shard_name)
@shard_name = shard_name
......
......@@ -4,6 +4,8 @@ class GeoRepositoryDestroyWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
include GeoQueue
loggable_arguments 1, 2, 3
def perform(id, name, disk_path, storage_name)
Geo::RepositoryDestroyService.new(id, name, disk_path, storage_name).execute
end
......
......@@ -6,6 +6,7 @@ module JiraConnect
queue_namespace :jira_connect
feature_category :integrations
loggable_arguments 1, 2
def perform(project_id, branch_name, commit_shas)
project = Project.find_by_id(project_id)
......
......@@ -6,6 +6,7 @@ class LdapGroupSyncWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :authentication_and_authorization
worker_has_external_dependencies!
weight 2
loggable_arguments 0, 1
# rubocop: disable CodeReuse/ActiveRecord
def perform(group_ids, provider = nil)
......
......@@ -7,11 +7,6 @@ module Gitlab
module Processor
class SidekiqProcessor < ::Raven::Processor
FILTERED_STRING = '[FILTERED]'
PERMITTED_ARGUMENTS = Hash.new(Set.new).merge(
'PostReceive' => [0, 1, 2, 3],
'SystemHookPushWorker' => [1],
'WebHookWorker' => [2]
).transform_values!(&:to_set).freeze
def self.filter_arguments(args, klass)
args.lazy.with_index.map do |arg, i|
......@@ -19,7 +14,7 @@ module Gitlab
when Numeric
arg
else
if PERMITTED_ARGUMENTS[klass].include?(i)
if permitted_arguments_for_worker(klass).include?(i)
arg
else
FILTERED_STRING
......@@ -28,6 +23,16 @@ module Gitlab
end
end
def self.permitted_arguments_for_worker(klass)
@permitted_arguments_for_worker ||= {}
@permitted_arguments_for_worker[klass] ||=
begin
klass.constantize&.loggable_arguments&.to_set
rescue
Set.new
end
end
def self.loggable_arguments(args, klass)
Gitlab::Utils::LogLimitedArray
.log_limited_array(filter_arguments(args, klass))
......
# frozen_string_literal: true
require 'fast_spec_helper'
require 'spec_helper'
require 'rspec-parameterized'
require 'raven'
RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
after do
if described_class.instance_variable_defined?(:@permitted_arguments_for_worker)
described_class.remove_instance_variable(:@permitted_arguments_for_worker)
end
end
describe '.filter_arguments' do
it 'returns a lazy enumerator' do
filtered = described_class.filter_arguments([1, 'string'], 'TestWorker')
......@@ -26,13 +30,9 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
with_them do
before do
permitted_arguments = Hash.new(Set.new).merge(
'NoPermittedArguments' => [],
'OnePermittedArgument' => [1],
'AllPermittedArguments' => [0, 1, 2, 3]
).transform_values!(&:to_set)
stub_const("#{described_class}::PERMITTED_ARGUMENTS", permitted_arguments)
stub_const('NoPermittedArguments', double(loggable_arguments: []))
stub_const('OnePermittedArgument', double(loggable_arguments: [1]))
stub_const('AllPermittedArguments', double(loggable_arguments: [0, 1, 2, 3]))
end
it do
......@@ -43,6 +43,45 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
end
end
describe '.permitted_arguments_for_worker' do
it 'returns the loggable_arguments for a worker class as a set' do
stub_const('TestWorker', double(loggable_arguments: [1, 1]))
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq([1].to_set)
end
it 'returns an empty set when the worker class does not exist' do
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq(Set.new)
end
it 'returns an empty set when the worker class does not respond to loggable_arguments' do
stub_const('TestWorker', 1)
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq(Set.new)
end
it 'returns an empty set when loggable_arguments cannot be converted to a set' do
stub_const('TestWorker', double(loggable_arguments: 1))
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq(Set.new)
end
it 'memoizes the results' do
worker_class = double
stub_const('TestWorker', worker_class)
expect(worker_class).to receive(:loggable_arguments).once.and_return([])
described_class.permitted_arguments_for_worker('TestWorker')
described_class.permitted_arguments_for_worker('TestWorker')
end
end
describe '.loggable_arguments' do
it 'filters and limits the arguments, then converts to strings' do
half_limit = Gitlab::Utils::LogLimitedArray::MAXIMUM_ARRAY_LENGTH / 2
......
......@@ -73,9 +73,9 @@ describe Gitlab::SidekiqLogging::JSONFormatter do
context 'when the job has non-integer arguments' do
it 'only allows permitted non-integer arguments through' do
hash_input['args'] = [1, 'foo', 'bar']
hash_input['class'] = 'SystemHookPushWorker'
hash_input['class'] = 'WebHookWorker'
expect(subject['args']).to eq(['1', 'foo', '[FILTERED]'])
expect(subject['args']).to eq(['1', '[FILTERED]', 'bar'])
end
end
......
......@@ -40,6 +40,12 @@ describe 'Every Sidekiq worker' do
end
end
it 'has a value for loggable_arguments' do
workers_without_defaults.each do |worker|
expect(worker.klass.loggable_arguments).to be_an(Array)
end
end
describe "feature category declarations" do
let(:feature_categories) do
YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:to_sym).to_set
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment