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