Skip to content
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

Closed
wants to merge 6 commits into from

Conversation

gwincr11
Copy link
Contributor

@gwincr11 gwincr11 commented Feb 12, 2019

Motivation:

  • Currently we have 2 separate monkey patches in place for tracking
    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:

  • Add an enqueued at attribute and serialization tooling.
  • Add a method to get how long a job has been enqueued for.
  • Add a logging item to show how long a job was enqueued prior to the
    perform method firing.

Summary

Other Information

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.
@rails-bot rails-bot bot added the activejob label Feb 12, 2019
@rafaelfranca
Copy link
Member

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?

@@ -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
Copy link
Member

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?

@eileencodes eileencodes added this to the 6.0.0 milestone Feb 12, 2019
@rafaelfranca
Copy link
Member

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
Copy link
Member

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).

end

def enqueded_for
Time.now - enqueued_at
Copy link
Member

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).

Copy link
Member

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
Copy link
Member

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?

Copy link
Contributor Author

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?

Copy link
Contributor Author

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.

end

def enqueded_for
Time.now.utc - enqueued_at
Copy link
Member

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.

Copy link
Contributor Author

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.

@@ -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)
Copy link
Contributor

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.

@@ -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
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwincr11
Copy link
Contributor Author

I am not sure how to get the test to rebuild, it looks like it just failed to start?

@rafaelfranca
Copy link
Member

Thanks! Merged in ac68550

rafaelfranca added a commit that referenced this pull request Feb 14, 2019
Adding enque time tracking and logging
suketa added a commit to suketa/rails_sandbox that referenced this pull request Aug 16, 2019
Adding enque time tracking and logging
rails/rails#35238
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants