0

I can currently make a request to my rails controller and I use send_file to download my production.log file. The file has gotten huge and I rarely need the entire file so I would like to download only part of the file like the last 20k lines. Is there a way to do this without reading the last n lines and writing those to another file and then sending that newly created file?

Here is the code I have at the moment:

def download_production_log
    send_file("#{Rails.root}/log/production.log")
end
Cannon Moyer
  • 3,014
  • 3
  • 31
  • 75

2 Answers2

2

One idea is to execute tail in your file.

I find out that there is a gem for that already.

Check this out.

1

Is there a way to do this without reading the last n lines...

Yes, you don't need to save the last n lines to a file to serve it. You might want to, for performance reasons, but you don't have to.

The trick is: how do you determine what are the last n lines, without reading the whole file? This is not possible, not without some scanning. If lines were fixed size, that'd be another story. But as it is, the easiest way (in my opinion) would be to open file and read only the last 64kb of data (or whatever amount you need).

There's a very good change that this chunk of data will start in the middle of some log line. So you just discard head of this data block until (and including) first newline. What will remain is whole log lines. Not exactly 20k, but similar (if you calculate your average log line length and use it to calculate how big a block to read).

Then you can use rails' send_data to send that block as if it were a real file.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367