Python从日志文件解析

时间:2017-07-13 17:41:47

标签: json python-3.x parsing logging

我有一个庞大的日志文件。我如何只使用json字符串,只有当下一行中有错误但在前一行中的'_____GP D __之后?

2017-04-22T11:27:11+06:00 smth.com pgp: [16136]: INFO:modules.gp.helpers.parameter_getter:_____GP D_____
2017-04-22T11:27:11+06:00 smth.com pgp: [16136]: {'D': 't12', 'telephone': None, 'from_time': '2016-04-22 11:30', 'C': 'C12', 'to_time': '2016-04-22 11:40', 'email': None}
2017-04-22T11:27:11+06:00 smth.com pgp: [16136]: INFO:tornado.access:200 POST /gp/C (192.168.1.240) 15.77ms

2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: INFO:modules.security.authentication:LOADING USER...
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: INFO:modules.gp.helpers.parameter_getter:_____GP D_____
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: {'D': 'testim12', 'telephone': None, 'from_time': '2017-04-20 17:30', 'C': 'CnGP13', 'to_time': '2017-04-22 21:40', 'email': None}
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: ERROR:modules.common.actionexception:ActionError: [{'from': 'time is already passed'}]
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: Traceback (most recent call last):
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]:   File "/app/src/modules/base/actions/base_action.py", line 96, in do_action
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]:     self._produce_response()
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: modules.common.actionexception.ActionValidationErr: []

例如来自我希望的这个日志文件

'{'D':'testim12','电话':无,'from_time':'2017-04-20 17:30','C':'CnGP13','to_time':'2017-04 -22 21:40','email':无}'。

只有当我有一个例外时,在下一行中出现'ERROR:modules.common.actionexception:ActionError:'?我该怎么做?

3 个答案:

答案 0 :(得分:0)

你可以使用这个,其中JSON字符串在捕获组1中

(?m)^.*?_____GP[ ]D_____.*\r?\n\s*^[^{\r\n]+(.+)\r?\n\s*^.*?ERROR:.*

https://regex101.com/r/UQ8gni/2

解释

 (?m)                          # Modifiers: multi-line
 ^ .*? _____GP [ ] D_____ .*   # Line that starts error block
 \r? \n \s*                    # Required newline 
 ^ [^{\r\n]+                   # Up to start of Json string
 ( .+ )                        # (1), Json string
 \r? \n \s*                    # Required newline 
 ^ .*? ERROR: .*               # Line that ends error block

答案 1 :(得分:0)

这与one you had yesterday的问题相同,只是在选择行之前进行额外检查 - 例如检查下一行是否包含]: ERROR:字符串:

found_line = None  # store for our matched line
with open("input.log", "r") as f:  # open your log file
    for line in f:  # read it line by line
        if line.rstrip()[-14:] == "_____GP D_____":  # if a line ends with our string...
            found_line = next(f).rstrip()  # grab the next line as our potential candidate
            if next(f).find("]: ERROR:") != -1:  # if the next line contains an error marker
                break  # match found, break out as we don't need to search any more...
            else:  # the next line wasn't an error...
                found_line = None  # ... reset the potential result and continue searching

但是,由于您的found_line实际上会包含整行(包括时间戳),因此您需要先将其删除,这一切都取决于记录器的设置方式。根据您的数据,合理的方法是跳过第一个39字符(<date-time> smth.com pgp:)并在下一个冒号后拾取所有内容,假设以下括号中的数字可以更改(如果不是 - 您可以删除第一个n字符并完成它:)

if found_line:
    found_line = found_line[found_line.find(":", 39) + 1:].strip()

小心,那个&#39;错误&#39;如果某些记录的数据包含该确切模式,则检查可能会失败 - 如果您想要使用它,您可以尝试使用我们用于将JSON从日志行中取出的类似技术并检查它是否以{{1开头}}

你也应该尝试自己做事而不是盲目地从SO中复制代码 - 你不会以这种方式学到很多东西。

答案 2 :(得分:0)

使用生成器功能:

def getjson (f):
    for line in filter(lambda x: '_GP D_' in x, f):
        line1 = next(f)
        line2 = next(f).split(' ', 4)
        if line2[4].startswith('ERROR'):
            yield line1.rstrip().split(' ', 4)[4]

with open('input.log', 'r') as f:
    for json in getjson(f):
        print(json)

生成器的一个兴趣是它将捕获由next() 引起的最终stopIteration异常(例如,当_G PD_行之后少于2行时。) 并停止。

请注意,此方法假定_G PD_行至少分隔两行。