]> gitweb.michael.orlitzky.com - djbdns-logparse.git/blob - djbdns/io.py
a3e6e430e8a7e7a19890b7d94af36eff3e42b86d
[djbdns-logparse.git] / djbdns / io.py
1 r"""
2 Functions that perform input/output. This forms a layer between the
3 executable itself and the more libraryish modules.
4 """
5 from subprocess import Popen, PIPE
6 from typing import TextIO
7 from djbdns.dnscache import handle_dnscache_log
8 from djbdns.tinydns import handle_tinydns_log
9
10 def parse_logfile(file : TextIO):
11 r"""
12 Process a single log ``file``.
13
14 Parameters
15 ----------
16
17 file : typing.TextIO
18 An open log file, or stdin.
19
20 Examples
21 --------
22
23 >>> line = "@4000000063227a320c4f3114 7f000001:9d61:be69 - 0001 www.example.com\n"
24 >>> from tempfile import NamedTemporaryFile
25 >>> with NamedTemporaryFile(mode="w", delete=False) as f:
26 ... _ = f.write(line)
27 >>> f = open(f.name, 'r')
28 >>> parse_logfile(f)
29 2022-09-14 21:04:40.206516500 dropped query (no authority) from 127.0.0.1:40289 (id 48745): a www.example.com
30 >>> f.close()
31 >>> from os import remove
32 >>> remove(f.name)
33
34 """
35 # Open a pipe to tai64nlocal. We'll write lines of our input file
36 # (the log file) to it, and read back the same lines but with
37 # friendly timestamps in them.
38 with Popen(["tai64nlocal"],
39 stdin=PIPE,
40 stdout=PIPE,
41 text=True,
42 bufsize=0) as tai:
43
44 if not tai.stdin or not tai.stdout:
45 # Mypy tells me that this can happen, based on the type
46 # annotations in the standard library I guess?
47 return
48
49 for line in file:
50 tai.stdin.write(line)
51 line = tai.stdout.readline()
52
53 friendly_line = handle_tinydns_log(line)
54 if not friendly_line:
55 friendly_line = handle_dnscache_log(line)
56 if not friendly_line:
57 friendly_line = line
58
59 try:
60 print(friendly_line)
61 except BrokenPipeError:
62 # If our stdout is being piped to another process and if
63 # that process closes the pipe, this error will be raised
64 # the next time we try to write to stdout.
65 break