New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding enque time tracking and logging #35238
Conversation
Motivation: - Currently we have 2 seperate monkey patches in place for tracking enqueded time for 2 seperate workers. It seems that activejob could be a source of truth for how long an item has been enqued so that we can easily use it for consistent monitoring across workers/apps to ensure that jobs are running at an acceptable speed. Changes: - Add an enqueded at attribute and serilization tooling. - Add a method to get how long a job has been enqueded for. - Add a logging item to show how long a job was enqued prior to the perform method firing.
Should we take retries in consideration? Let say a job needs to be retried 10 times, is the time on queue the same as the difference between the first time it was enqueued and the time it is being executed or should we just consider the last time it was retried? |
activejob/lib/active_job/core.rb
Outdated
@@ -97,7 +100,8 @@ def serialize | |||
"executions" => executions, | |||
"exception_executions" => exception_executions, | |||
"locale" => I18n.locale.to_s, | |||
"timezone" => Time.zone.try(:name) | |||
"timezone" => Time.zone.try(:name), | |||
"enqueued_at" => Time.now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should use the UTC time?
I just checked our application and we don't take in consideration retries, so this is enough for me. |
"Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)}" + args_info(job) | ||
end | ||
info do | ||
"#{job.class.name} (Job ID: #{job.job_id}) waited in the queue for #{job.enqueded_for}ms" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make the wait time part of the other log message? Then we don't need to have two info
blocks.
I believe the job = event...
line was moved inside the info block for performance (so it doesn't get executed unless the logger is in info mode).
activejob/lib/active_job/core.rb
Outdated
end | ||
|
||
def enqueded_for | ||
Time.now - enqueued_at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually need to calculate how long the job has been in the queue? I would expect the log messages to have a timestamp. If the log message has a time stamp, we can just log the "enqueued time" and whatever reads the log messages can calculate how long the message sat in the queue. Logging just the duration means that we lose the "enqueued_at" information (or we have to take the log timestamp and subtract the duration to back in to the value).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In our application we only lock the enqueued_at.
test "serialize stores the enqueued_at time" do | ||
job = HelloJob.new | ||
type = job.serialize["enqueued_at"].class | ||
assert_equal Time, type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if returning a Time object from serialize is a good idea. It will work in JSON-based adapters but the problem is that the roundtrip of this value will return a String, so maybe it better to be explicit about the string conversion we want to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a Rails preferred format for this sort of data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to be a string then added a test to make sure it could be parsed.
activejob/lib/active_job/core.rb
Outdated
end | ||
|
||
def enqueded_for | ||
Time.now.utc - enqueued_at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this working? enqueued_at
will be a string and when I try Time.now.utc - JSON.load(JSON.dump(Time.now.utc))
I get an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I will remove it per @tenderlove's suggestion.
…g, and serialize the timestamp as a string
activejob/test/cases/logging_test.rb
Outdated
@@ -115,6 +115,8 @@ def test_perform_job_logging | |||
perform_enqueued_jobs do | |||
LoggingJob.perform_later "Dummy" | |||
assert_match(/Performing LoggingJob \(Job ID: .*?\) from .*? with arguments:.*Dummy/, @logger.messages) | |||
|
|||
assert_match(/added to queue at /, @logger.messages) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s just say “enqueued at”, so we keep the language the same.
activejob/lib/active_job/core.rb
Outdated
@@ -97,7 +100,8 @@ def serialize | |||
"executions" => executions, | |||
"exception_executions" => exception_executions, | |||
"locale" => I18n.locale.to_s, | |||
"timezone" => Time.zone.try(:name) | |||
"timezone" => Time.zone.try(:name), | |||
"enqueued_at" => Time.now.utc.to_s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mayb Time.now.utc.iso8601
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure how to get the test to rebuild, it looks like it just failed to start? |
Thanks! Merged in ac68550 |
Adding enque time tracking and logging
Adding enque time tracking and logging rails/rails#35238
Motivation:
enqueued time for 2 separate workers. It seems that activejob could be
a source of truth for how long an item has been enqueued so that we can
easily use it for consistent monitoring across workers/apps to ensure
that jobs are running at an acceptable speed.
Changes:
perform method firing.
Summary
Other Information