29 """ |
29 """ |
30 Get a set of dates, telling which days in the given month (as a datetime) have logs available |
30 Get a set of dates, telling which days in the given month (as a datetime) have logs available |
31 """ |
31 """ |
32 |
32 |
33 abstract |
33 abstract |
34 |
34 |
|
35 def get_search (self, query) : |
|
36 """ |
|
37 Search the logs for the given query |
|
38 """ |
|
39 |
|
40 abstract |
|
41 |
35 class LogFile (object) : |
42 class LogFile (object) : |
36 """ |
43 """ |
37 A file containing LogEvents |
44 A file containing LogEvents |
38 |
45 |
39 XXX: modify to implement LogSource? |
46 XXX: modify to implement LogSource? |
284 yield dtz.date() |
291 yield dtz.date() |
285 |
292 |
286 # one day sdrawkcab |
293 # one day sdrawkcab |
287 dtz -= ONE_DAY |
294 dtz -= ONE_DAY |
288 |
295 |
289 def get_latest (self, count) : |
296 def _iter_logfile_reverse (self, dt=None, max_files=100) : |
290 """ |
297 """ |
291 Uses _iter_backwards + _get_logfile_date to read the yield the given lines from as many logfiles as needed |
298 Yields a series of LogFile objects, iterating backwards in time starting at the given datetime, or the |
292 """ |
299 current date, if none given. |
293 |
300 |
294 # iterate backwards from now |
301 Reads/probes at most max_files files. |
295 day_iter = self._iter_date_reverse() |
302 """ |
296 |
303 |
297 # number of files read |
304 # start counting at zero... |
298 files = 0 |
305 file_count = 0 |
299 |
306 |
300 # only read up to 100 files or so |
307 # iterate backwards over days |
301 MAX_FILES = 100 |
308 for day in self._iter_date_reverse(dt) : |
302 |
309 # stop if we've handled enough files by now |
303 # read the events into here |
310 if file_count > max_files : |
304 lines = [] |
311 break |
305 |
312 |
306 # loop until done |
313 # try and open the next logfile |
307 while len(lines) < count : |
|
308 logfile = None |
314 logfile = None |
309 |
315 |
310 # get next logfile |
316 file_count += 1 |
311 files += 1 |
317 logfile = self._get_logfile_date(day) |
312 |
318 |
313 # open |
319 # no logfile there? |
314 logfile = self._get_logfile_date(day_iter.next()) |
|
315 |
|
316 if not logfile : |
320 if not logfile : |
317 if files > MAX_FILES : |
321 # if we didn't find any logfiles at all, terminate rudely |
|
322 if file_count > max_files : |
318 raise Exception("No recent logfiles found") |
323 raise Exception("No recent logfiles found") |
319 |
324 |
320 else : |
325 else : |
321 # skip to next day |
326 # skip to next day |
322 continue |
327 continue |
323 |
328 |
|
329 # yield it |
|
330 yield logfile |
|
331 |
|
332 def get_latest (self, count) : |
|
333 """ |
|
334 Uses _iter_backwards + _get_logfile_date to read the yield the given lines from as many logfiles as needed |
|
335 """ |
|
336 |
|
337 # iterate over logfiles |
|
338 iter = self._iter_logfile_reverse() |
|
339 |
|
340 # read the events into here |
|
341 lines = [] |
|
342 |
|
343 # loop until done |
|
344 while len(lines) < count : |
|
345 # next logfile |
|
346 logfile = iter.next() |
|
347 |
324 # read the events |
348 # read the events |
325 # XXX: use a queue |
349 # XXX: use a queue |
326 lines = list(logfile.read_latest(count)) + lines |
350 lines = list(logfile.read_latest(count)) + lines |
327 |
351 |
328 # return the events |
352 # return the events |