+ # Test for hard cap on total output and for log throttling. Returns whether
+ # the log line should go to output or not. Modifies "line" in place to
+ # replace it with an error if a logging limit is tripped.
+ def rate_limit running_job, line
+ if running_job[:bytes_logged] > Rails.configuration.crunch_limit_log_bytes_per_job
+ # Don't log anything if the hard cap has already been exceeded
+ return false
+ end
+
+ now = Time.now
+ throttle_period = Rails.configuration.crunch_log_throttle_period
+
+ #puts "Handle line at #{now - running_job[:log_throttle_timestamp]}, buf bytes #{line.size}, so far #{running_job[:log_throttle_bytes_so_far]}, throttled #{running_job[:log_throttle_bytes_skipped]}"
+
+ if running_job[:log_throttle_bytes_skipped] > 0
+ # We've skipped some log in the current time period already, so continue to
+ # skip the log
+ running_job[:log_throttle_bytes_skipped] += line.size
+ return false
+ end
+
+ # Count lines and bytes logged in this period, and total bytes logged for the job
+ running_job[:log_throttle_lines_so_far] += 1
+ running_job[:log_throttle_bytes_so_far] += line.size
+ running_job[:bytes_logged] += line.size
+
+ if running_job[:log_throttle_bytes_so_far] > Rails.configuration.crunch_log_throttle_bytes or
+ running_job[:log_throttle_lines_so_far] > Rails.configuration.crunch_log_throttle_lines
+ # We've exceeded the per-period throttle, so start skipping
+ running_job[:log_throttle_bytes_skipped] += line.size
+
+ # Replace log line with a message about skipping the log
+ remaining_time = throttle_period - (now - running_job[:log_throttle_timestamp])
+ if running_job[:log_throttle_bytes_so_far] > Rails.configuration.crunch_log_throttle_bytes
+ line.replace "Exceeded crunch_log_throttle_bytes rate of #{Rails.configuration.crunch_log_throttle_bytes} bytes per #{throttle_period} seconds, logging will be silenced for the next #{remaining_time.round} seconds\n"
+ else
+ line.replace "Exceeded crunch_log_throttle_lines rate of #{Rails.configuration.crunch_log_throttle_lines} lines per #{throttle_period} seconds, logging will be silenced for the next #{remaining_time.round} seconds\n"
+ end
+ end
+
+ if running_job[:bytes_logged] > Rails.configuration.crunch_limit_log_bytes_per_job
+ # Replace log line with a message about truncating the log
+ line.replace "Exceed hard job log cap crunch_limit_log_bytes_per_job of #{Rails.configuration.crunch_limit_log_bytes_per_job}. Subsequent logs will be truncated."
+ end
+
+ true
+ end
+