Viewing file: checkers.py (3.9 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2020 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT import logging import os from contextlib import contextmanager from typing import Optional
import requests from requests import Timeout, ReadTimeout from requests.exceptions import SSLError import urllib3 from urllib3.exceptions import ReadTimeoutError
from .errors import ( PhpLogErrorsFound, WebsiteCheckBadHttpCode, WebsiteTimeout, WebsiteHttpsBroken, WebsiteNotResponding )
# long timeout is set because our tested # sites may be really slow TIMEOUT: int = 10
ERROR_LOGFILE_NAME = "error_log" ERROR_PATTERNS = [ "PHP Fatal error", # not all php errors are marked # as fatal in logs, see tests for examples "Stack trace" ]
@contextmanager def check_error_log(abs_wp_path: str): """ Looks into {doc_root}/public_html and searches for any php errors found.
As log can be really big, this context manager captures log size at start point and then analyzes only part which was added during context execution :param abs_wp_path: path to the root directory of wordpress installation """ error_log_path = os.path.join(abs_wp_path, ERROR_LOGFILE_NAME) if os.path.exists(error_log_path): old_stat_result = os.stat(error_log_path) else: # the case when log was removed for some reason old_stat_result = None
yield
# log file still does not exist, nothing to check if not os.path.exists(error_log_path): logging.warning('%s does not exists, nothing to analyze in log file', error_log_path) return
cur_stat_result = os.stat(error_log_path) with open(error_log_path, "r") as f: # log file was not rotated, skip the beginning if old_stat_result \ and old_stat_result.st_ino == cur_stat_result.st_ino \ and old_stat_result.st_size <= cur_stat_result.st_size: f.seek(old_stat_result.st_size)
# "[" is not a misprint # logfile contains of records that start with date and time surronded by []: # [2021 01 01 19:86] text # text text multiline # [2021 01 01 19:86] another message # so what I'm trying to do here is split file not by lines, but by log records # it might not work in some cases, but must be fine in 99% for log_record in f.read().split('\n['): if not any((error_pattern in log_record for error_pattern in ERROR_PATTERNS)): continue raise PhpLogErrorsFound(error_log_path, log_record)
def check_site_status_code(domain: str, wp_path: str) -> Optional[str]: """ Checks that website response http code is in range 200-400 and site returns something at all :param domain: domain name in format "domain.zone" protocol will be added automatically :param wp_path: path to the wordpress installation instance :raises: WebsiteCheckError and subclasses """ url = 'http://' + domain + '/' + wp_path # if certificate is bad, but the site itself works, we consider it ok for WPOS urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) try: response = requests.get(url, timeout=TIMEOUT, verify=False) if 200 <= response.status_code < 400: return raise WebsiteCheckBadHttpCode(response.url, response.status_code) except Timeout: raise WebsiteTimeout(url, timeout=TIMEOUT) except SSLError as e: raise WebsiteHttpsBroken(url, details=str(e)) except requests.ConnectionError as e: # really strange behavior of requests that wrap # errors inside of ConnectionError if e.args and isinstance(e.args[0], ReadTimeoutError): raise WebsiteTimeout(url, timeout=TIMEOUT) raise WebsiteNotResponding(url, details=str(e))
|