diff --git a/app/models/upload.rb b/app/models/upload.rb index a6af7a8b8699b8b79fbf65469d2894d4ac576f86..e01e9c6a4f0d41e35dde902a10230b53603cef78 100644 --- a/app/models/upload.rb +++ b/app/models/upload.rb @@ -12,6 +12,7 @@ class Upload < ActiveRecord::Base validates :uploader, presence: true scope :with_files_stored_locally, -> { where(store: ObjectStorage::Store::LOCAL) } + scope :with_files_stored_remotely, -> { where(store: ObjectStorage::Store::REMOTE) } before_save :calculate_checksum!, if: :foreground_checksummable? after_commit :schedule_checksum, if: :checksummable? @@ -46,7 +47,18 @@ class Upload < ActiveRecord::Base end def exist? - File.exist?(absolute_path) + exist = File.exist?(absolute_path) + + # Help sysadmins find missing upload files + if persisted? && !exist + if Gitlab::Sentry.enabled? + Raven.capture_message("Upload file does not exist", extra: self.attributes) + end + + Gitlab::Metrics.counter(:upload_file_does_not_exist_total, 'The number of times an upload record could not find its file').increment + end + + exist end def uploader_context diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index c6fd7ef7360edcbe08780cc276803e59f99cee8c..5700f640e4c006f46f00b27316df46e4a7474591 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -45,6 +45,7 @@ The following metrics are available: | redis_ping_success | Gauge | 9.4 | Whether or not the last redis ping succeeded | | redis_ping_latency_seconds | Gauge | 9.4 | Round trip time of the redis ping | | user_session_logins_total | Counter | 9.4 | Counter of how many users have logged in | +| upload_file_does_not_exist | Counter | 10.7 | Number of times an upload record could not find its file | | failed_login_captcha_total | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login | | successful_login_captcha_total | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login | diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb index e3544b84b502502e8347cba9d1d6544bf2bb2dac..5a0df9fbbb044b48454e9a9fe866b92c98ddc31c 100644 --- a/spec/models/upload_spec.rb +++ b/spec/models/upload_spec.rb @@ -112,10 +112,51 @@ describe Upload do expect(upload).to exist end - it 'returns false when the file does not exist' do - upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL) + context 'when the file does not exist' do + it 'returns false' do + upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL) - expect(upload).not_to exist + expect(upload).not_to exist + end + + context 'when the record is persisted' do + it 'sends a message to Sentry' do + upload = create(:upload, :issuable_upload) + + expect(Gitlab::Sentry).to receive(:enabled?).and_return(true) + expect(Raven).to receive(:capture_message).with("Upload file does not exist", extra: upload.attributes) + + upload.exist? + end + + it 'increments a metric counter to signal a problem' do + upload = create(:upload, :issuable_upload) + + counter = double(:counter) + expect(counter).to receive(:increment) + expect(Gitlab::Metrics).to receive(:counter).with(:upload_file_does_not_exist_total, 'The number of times an upload record could not find its file').and_return(counter) + + upload.exist? + end + end + + context 'when the record is not persisted' do + it 'does not send a message to Sentry' do + upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL) + + expect(Raven).not_to receive(:capture_message) + + upload.exist? + end + + it 'does not increment a metric counter' do + upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL) + + expect(Gitlab::Metrics).not_to receive(:counter) + + upload.exist? + end + end end end