Commit c093193b authored by Sean McGivern's avatar Sean McGivern 🎄

Merge branch 'feature/gb/email-delivery-metrics' into 'master'

Add emails delivery metrics

Closes #49214

See merge request gitlab-org/gitlab-ce!20638
parents ddae884c 3ab6880c
---
title: Add emails delivery Prometheus metrics
merge_request: 20638
author:
type: added
unless Gitlab.config.gitlab.email_enabled
ActionMailer::Base.register_interceptor(::Gitlab::Email::Hook::DisableEmailInterceptor)
ActionMailer::Base.logger = nil
end
ActionMailer::Base.register_interceptors(
::Gitlab::Email::Hook::AdditionalHeadersInterceptor,
::Gitlab::Email::Hook::EmailTemplateInterceptor,
::Gitlab::Email::Hook::DeliveryMetricsObserver
)
ActionMailer::Base.register_observer(::Gitlab::Email::Hook::DeliveryMetricsObserver)
ActionMailer::Base.register_interceptor(AdditionalEmailHeadersInterceptor)
# Interceptor in lib/disable_email_interceptor.rb
unless Gitlab.config.gitlab.email_enabled
ActionMailer::Base.register_interceptor(DisableEmailInterceptor)
ActionMailer::Base.logger = nil
end
# Interceptor in lib/email_template_interceptor.rb
ActionMailer::Base.register_interceptor(EmailTemplateInterceptor)
class AdditionalEmailHeadersInterceptor
def self.delivering_email(message)
message.header['Auto-Submitted'] ||= 'auto-generated'
message.header['X-Auto-Response-Suppress'] ||= 'All'
end
end
# Read about interceptors in http://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails
class DisableEmailInterceptor
def self.delivering_email(message)
message.perform_deliveries = false
Rails.logger.info "Emails disabled! Interceptor prevented sending mail #{message.subject}"
end
end
# Read about interceptors in http://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails
class EmailTemplateInterceptor
def self.delivering_email(message)
# Remove HTML part if HTML emails are disabled.
unless Gitlab::CurrentSettings.html_emails_enabled
message.parts.delete_if do |part|
part.content_type.start_with?('text/html')
end
end
end
end
module Gitlab
module Email
module Hook
class AdditionalHeadersInterceptor
def self.delivering_email(message)
message.header['Auto-Submitted'] ||= 'auto-generated'
message.header['X-Auto-Response-Suppress'] ||= 'All'
end
end
end
end
end
module Gitlab
module Email
module Hook
class DeliveryMetricsObserver
extend Gitlab::Utils::StrongMemoize
def self.delivering_email(_message)
delivery_attempts_counter.increment
end
def self.delivered_email(_message)
delivered_emails_counter.increment
end
def self.delivery_attempts_counter
strong_memoize(:delivery_attempts_counter) do
Gitlab::Metrics.counter(:gitlab_emails_delivery_attempts_total,
'Counter of total emails delivery attempts')
end
end
def self.delivered_emails_counter
strong_memoize(:delivered_emails_counter) do
Gitlab::Metrics.counter(:gitlab_emails_delivered_total,
'Counter of total emails delievered')
end
end
end
end
end
end
module Gitlab
module Email
module Hook
class DisableEmailInterceptor
def self.delivering_email(message)
message.perform_deliveries = false
Rails.logger.info "Emails disabled! Interceptor prevented sending mail #{message.subject}"
end
end
end
end
end
module Gitlab
module Email
module Hook
class EmailTemplateInterceptor
##
# Remove HTML part if HTML emails are disabled.
#
def self.delivering_email(message)
unless Gitlab::CurrentSettings.html_emails_enabled
message.parts.delete_if do |part|
part.content_type.start_with?('text/html')
end
end
end
end
end
end
end
require 'spec_helper' require 'spec_helper'
describe AdditionalEmailHeadersInterceptor do describe Gitlab::Email::Hook::AdditionalHeadersInterceptor do
let(:mail) do let(:mail) do
ActionMailer::Base.mail(to: 'test@mail.com', from: 'info@mail.com', body: 'hello') ActionMailer::Base.mail(to: 'test@mail.com', from: 'info@mail.com', body: 'hello')
end end
......
require 'spec_helper'
describe Gitlab::Email::Hook::DeliveryMetricsObserver do
let(:email) do
ActionMailer::Base.mail(to: 'test@example.com',
from: 'info@example.com',
body: 'hello')
end
context 'when email has been delivered' do
it 'increments both email delivery metrics' do
expect(described_class.delivery_attempts_counter).to receive(:increment)
expect(described_class.delivered_emails_counter).to receive(:increment)
email.deliver_now
end
end
context 'when email has not been delivered due to an error' do
before do
allow(email.delivery_method).to receive(:deliver!)
.and_raise(StandardError, 'Some SMTP error')
end
it 'increments only delivery attempt metric' do
expect(described_class.delivery_attempts_counter)
.to receive(:increment)
expect(described_class.delivered_emails_counter)
.not_to receive(:increment)
expect { email.deliver_now }
.to raise_error(StandardError, 'Some SMTP error')
end
end
end
require 'spec_helper' require 'spec_helper'
describe DisableEmailInterceptor do describe Gitlab::Email::Hook::DisableEmailInterceptor do
before do before do
Mail.register_interceptor(described_class) Mail.register_interceptor(described_class)
end end
......
...@@ -1366,7 +1366,8 @@ describe Notify do ...@@ -1366,7 +1366,8 @@ describe Notify do
it 'only sends the text template' do it 'only sends the text template' do
stub_application_setting(html_emails_enabled: false) stub_application_setting(html_emails_enabled: false)
EmailTemplateInterceptor.delivering_email(multipart_mail) Gitlab::Email::Hook::EmailTemplateInterceptor
.delivering_email(multipart_mail)
expect(multipart_mail).to have_part_with('text/plain') expect(multipart_mail).to have_part_with('text/plain')
expect(multipart_mail).not_to have_part_with('text/html') expect(multipart_mail).not_to have_part_with('text/html')
...@@ -1377,7 +1378,8 @@ describe Notify do ...@@ -1377,7 +1378,8 @@ describe Notify do
it 'sends a multipart message' do it 'sends a multipart message' do
stub_application_setting(html_emails_enabled: true) stub_application_setting(html_emails_enabled: true)
EmailTemplateInterceptor.delivering_email(multipart_mail) Gitlab::Email::Hook::EmailTemplateInterceptor
.delivering_email(multipart_mail)
expect(multipart_mail).to have_part_with('text/plain') expect(multipart_mail).to have_part_with('text/plain')
expect(multipart_mail).to have_part_with('text/html') expect(multipart_mail).to have_part_with('text/html')
......
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