Instrument EmailDigestArticleCollector (#13153)

* Instrument EmailDigestArticleCollector

On DEV, since we skip this with sidekiq-cron and instead process them
inline using Heroku Scheduler (which is not instrumented), we miss out
on all instrumentation for this process and have no idea how long it
takes to process each user.

With this instrumentation in place, we can see how long it takes to
process each user and aggregate them to see how long it takes to process
all users.

This commit also adds an Instrumentation mixin that we can use to
instrument blocks easily:

    instrument "MyClass.my_method", tags: { article: article.id } do |span|
      # ...
    end

* Add Instrumentation mixin

Oops, completely forgot to commit this file
This commit is contained in:
Jamie Gaskins 2021-03-29 09:33:32 -04:00 committed by GitHub
parent 25c3f79d30
commit 5a0a46887c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 29 deletions

View file

@ -1,39 +1,47 @@
class EmailDigestArticleCollector
include Instrumentation
ARTICLES_TO_SEND = "EmailDigestArticleCollector#articles_to_send".freeze
def initialize(user)
@user = user
end
def articles_to_send
return [] unless should_receive_email?
# rubocop:disable Metrics/BlockLength
instrument ARTICLES_TO_SEND, tags: %W[user_id:#{@user.id}] do
return [] unless should_receive_email?
articles = if user_has_followings?
experience_level_rating = (@user.experience_level || 5)
experience_level_rating_min = experience_level_rating - 3.6
experience_level_rating_max = experience_level_rating + 3.6
articles = if user_has_followings?
experience_level_rating = (@user.experience_level || 5)
experience_level_rating_min = experience_level_rating - 3.6
experience_level_rating_max = experience_level_rating + 3.6
@user.followed_articles
.select(:title, :description, :path)
.published
.where("published_at > ?", cutoff_date)
.where(email_digest_eligible: true)
.where.not(user_id: @user.id)
.where("score > ?", 12)
.where("experience_level_rating > ? AND experience_level_rating < ?",
experience_level_rating_min, experience_level_rating_max)
.order(score: :desc)
.limit(6)
else
Article.select(:title, :description, :path)
.published
.where("published_at > ?", cutoff_date)
.where(featured: true, email_digest_eligible: true)
.where.not(user_id: @user.id)
.where("score > ?", 25)
.order(score: :desc)
.limit(6)
end
@user.followed_articles
.select(:title, :description, :path)
.published
.where("published_at > ?", cutoff_date)
.where(email_digest_eligible: true)
.where.not(user_id: @user.id)
.where("score > ?", 12)
.where("experience_level_rating > ? AND experience_level_rating < ?",
experience_level_rating_min, experience_level_rating_max)
.order(score: :desc)
.limit(6)
else
Article.select(:title, :description, :path)
.published
.where("published_at > ?", cutoff_date)
.where(featured: true, email_digest_eligible: true)
.where.not(user_id: @user.id)
.where("score > ?", 25)
.order(score: :desc)
.limit(6)
end
articles.length < 3 ? [] : articles
articles.length < 3 ? [] : articles
end
# rubocop:enable Metrics/BlockLength
end
private
@ -81,7 +89,10 @@ class EmailDigestArticleCollector
end
def last_user_emails
@last_user_emails ||= @user.email_messages.select(:sent_at,
:opened_at).where(mailer: "DigestMailer#digest_email").limit(10)
@last_user_emails ||= @user
.email_messages
.select(:sent_at, :opened_at)
.where(mailer: "DigestMailer#digest_email")
.limit(10)
end
end

View file

@ -0,0 +1,7 @@
module Instrumentation
def instrument(operation, tags: [], &block)
# TODO: (@jgaskins): Extract the knowledge of which tracing library
# we're using, like we did with ForemStatsDriver
Datadog.tracer.trace operation, tags: tags, &block
end
end