tobiko/tobiko/shell/files/_logs.py

112 lines
3.7 KiB
Python

# Copyright (c) 2020 Red Hat, Inc.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import absolute_import
import collections
import os
from tobiko.shell import grep
from tobiko.shell import find
from tobiko.shell import sh
class LogFileDigger(object):
def __init__(self, filename, **execute_params):
self.filename = filename
self.execute_params = execute_params
self.logfiles = set()
self.found = set()
def find_lines(self, pattern, new_lines=False):
log_files = self.list_log_files()
try:
lines = frozenset(
grep.grep_files(pattern=pattern, files=log_files,
**self.execute_params))
except grep.NoMatchingLinesFound:
if new_lines:
return frozenset()
else:
lines -= self.found
self.found.update(lines)
if new_lines:
return lines
return frozenset(self.found)
def find_new_lines(self, pattern):
return self.find_lines(pattern=pattern, new_lines=True)
def list_log_files(self):
file_path, file_name = os.path.split(self.filename)
return find.find_files(path=file_path,
name=file_name,
**self.execute_params)
class JournalLogDigger(LogFileDigger):
def find_lines(self, pattern, new_lines=False):
dump_log_cmd = [
"journalctl", "--unit", self.filename,
"--since", "5 minutes ago"]
try:
lines = frozenset(
grep.grep_lines(pattern=pattern,
command=dump_log_cmd,
**self.execute_params))
except grep.NoMatchingLinesFound:
if new_lines:
return frozenset()
else:
lines -= self.found
self.found.update(lines)
if new_lines:
return lines
return frozenset(self.found)
class MultihostLogFileDigger(object):
def __init__(self, filename, ssh_clients=None,
file_digger_class=LogFileDigger,
**execute_params):
self.diggers = collections.OrderedDict()
self.file_digger_class = file_digger_class
self.filename = filename
self.execute_params = execute_params
if ssh_clients:
for ssh_client in ssh_clients:
self.add_host(ssh_client=ssh_client)
def add_host(self, hostname=None, ssh_client=None):
hostname = hostname or sh.get_hostname(ssh_client=ssh_client)
if hostname not in self.diggers:
self.diggers[hostname] = self.file_digger_class(
filename=self.filename,
ssh_client=ssh_client,
**self.execute_params)
def find_lines(self, pattern, new_lines=False):
lines = []
for hostname, digger in self.diggers.items():
for line in digger.find_lines(pattern, new_lines=new_lines):
lines.append((hostname, line))
return lines
def find_new_lines(self, pattern):
return self.find_lines(pattern=pattern, new_lines=True)