|
|
d69b2b |
From a6a52365df26edd4f6b0028056395d943344d787 Mon Sep 17 00:00:00 2001
|
|
|
d69b2b |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
d69b2b |
Date: Thu, 11 Jun 2020 15:30:28 -0400
|
|
|
d69b2b |
Subject: [PATCH] Issue 50791 - Healthcheck should look for notes=A/F in access
|
|
|
d69b2b |
log
|
|
|
d69b2b |
|
|
|
d69b2b |
Description: Add checks for notes=A (fully unindexed search) and
|
|
|
d69b2b |
notes=F (Unknown attribute in search filter) in the
|
|
|
d69b2b |
current access log.
|
|
|
d69b2b |
|
|
|
d69b2b |
relates: https://pagure.io/389-ds-base/issue/50791
|
|
|
d69b2b |
|
|
|
d69b2b |
Reviewed by: firstyear(Thanks!)
|
|
|
d69b2b |
---
|
|
|
d69b2b |
src/lib389/lib389/cli_ctl/health.py | 4 +-
|
|
|
d69b2b |
src/lib389/lib389/dirsrv_log.py | 72 +++++++++++++++++++++++++++--
|
|
|
d69b2b |
src/lib389/lib389/lint.py | 26 ++++++++++-
|
|
|
d69b2b |
3 files changed, 96 insertions(+), 6 deletions(-)
|
|
|
d69b2b |
|
|
|
d69b2b |
diff --git a/src/lib389/lib389/cli_ctl/health.py b/src/lib389/lib389/cli_ctl/health.py
|
|
|
d69b2b |
index 6333a753a..89484a11b 100644
|
|
|
d69b2b |
--- a/src/lib389/lib389/cli_ctl/health.py
|
|
|
d69b2b |
+++ b/src/lib389/lib389/cli_ctl/health.py
|
|
|
d69b2b |
@@ -1,5 +1,5 @@
|
|
|
d69b2b |
# --- BEGIN COPYRIGHT BLOCK ---
|
|
|
d69b2b |
-# Copyright (C) 2019 Red Hat, Inc.
|
|
|
d69b2b |
+# Copyright (C) 2020 Red Hat, Inc.
|
|
|
d69b2b |
# All rights reserved.
|
|
|
d69b2b |
#
|
|
|
d69b2b |
# License: GPL (version 3 or any later version).
|
|
|
d69b2b |
@@ -18,6 +18,7 @@ from lib389.monitor import MonitorDiskSpace
|
|
|
d69b2b |
from lib389.replica import Replica, Changelog5
|
|
|
d69b2b |
from lib389.nss_ssl import NssSsl
|
|
|
d69b2b |
from lib389.dseldif import FSChecks, DSEldif
|
|
|
d69b2b |
+from lib389.dirsrv_log import DirsrvAccessLog
|
|
|
d69b2b |
from lib389 import lint
|
|
|
d69b2b |
from lib389 import plugins
|
|
|
d69b2b |
from lib389._constants import DSRC_HOME
|
|
|
d69b2b |
@@ -37,6 +38,7 @@ CHECK_OBJECTS = [
|
|
|
d69b2b |
Changelog5,
|
|
|
d69b2b |
DSEldif,
|
|
|
d69b2b |
NssSsl,
|
|
|
d69b2b |
+ DirsrvAccessLog,
|
|
|
d69b2b |
]
|
|
|
d69b2b |
|
|
|
d69b2b |
|
|
|
d69b2b |
diff --git a/src/lib389/lib389/dirsrv_log.py b/src/lib389/lib389/dirsrv_log.py
|
|
|
d69b2b |
index baac2a3c9..7bed4bb17 100644
|
|
|
d69b2b |
--- a/src/lib389/lib389/dirsrv_log.py
|
|
|
d69b2b |
+++ b/src/lib389/lib389/dirsrv_log.py
|
|
|
d69b2b |
@@ -1,5 +1,5 @@
|
|
|
d69b2b |
# --- BEGIN COPYRIGHT BLOCK ---
|
|
|
d69b2b |
-# Copyright (C) 2016 Red Hat, Inc.
|
|
|
d69b2b |
+# Copyright (C) 2020 Red Hat, Inc.
|
|
|
d69b2b |
# All rights reserved.
|
|
|
d69b2b |
#
|
|
|
d69b2b |
# License: GPL (version 3 or any later version).
|
|
|
d69b2b |
@@ -9,12 +9,17 @@
|
|
|
d69b2b |
"""Helpers for managing the directory server internal logs.
|
|
|
d69b2b |
"""
|
|
|
d69b2b |
|
|
|
d69b2b |
+import copy
|
|
|
d69b2b |
import re
|
|
|
d69b2b |
import gzip
|
|
|
d69b2b |
from dateutil.parser import parse as dt_parse
|
|
|
d69b2b |
from glob import glob
|
|
|
d69b2b |
from lib389.utils import ensure_bytes
|
|
|
d69b2b |
-
|
|
|
d69b2b |
+from lib389._mapped_object_lint import DSLint
|
|
|
d69b2b |
+from lib389.lint import (
|
|
|
d69b2b |
+ DSLOGNOTES0001, # Unindexed search
|
|
|
d69b2b |
+ DSLOGNOTES0002, # Unknown attr in search filter
|
|
|
d69b2b |
+)
|
|
|
d69b2b |
|
|
|
d69b2b |
# Because many of these settings can change live, we need to check for certain
|
|
|
d69b2b |
# attributes all the time.
|
|
|
d69b2b |
@@ -35,7 +40,7 @@ MONTH_LOOKUP = {
|
|
|
d69b2b |
}
|
|
|
d69b2b |
|
|
|
d69b2b |
|
|
|
d69b2b |
-class DirsrvLog(object):
|
|
|
d69b2b |
+class DirsrvLog(DSLint):
|
|
|
d69b2b |
"""Class of functions to working with the various DIrectory Server logs
|
|
|
d69b2b |
"""
|
|
|
d69b2b |
def __init__(self, dirsrv):
|
|
|
d69b2b |
@@ -189,6 +194,67 @@ class DirsrvAccessLog(DirsrvLog):
|
|
|
d69b2b |
self.full_regexs = [self.prog_m1, self.prog_con, self.prog_discon]
|
|
|
d69b2b |
self.result_regexs = [self.prog_notes, self.prog_repl,
|
|
|
d69b2b |
self.prog_result]
|
|
|
d69b2b |
+ @classmethod
|
|
|
d69b2b |
+ def lint_uid(cls):
|
|
|
d69b2b |
+ return 'logs'
|
|
|
d69b2b |
+
|
|
|
d69b2b |
+ def _log_get_search_stats(self, conn, op):
|
|
|
d69b2b |
+ lines = self.match(f".* conn={conn} op={op} SRCH base=.*")
|
|
|
d69b2b |
+ if len(lines) != 1:
|
|
|
d69b2b |
+ return None
|
|
|
d69b2b |
+
|
|
|
d69b2b |
+ quoted_vals = re.findall('"([^"]*)"', lines[0])
|
|
|
d69b2b |
+ return {
|
|
|
d69b2b |
+ 'base': quoted_vals[0],
|
|
|
d69b2b |
+ 'filter': quoted_vals[1],
|
|
|
d69b2b |
+ 'timestamp': re.findall('\[(.*)\]', lines[0])[0],
|
|
|
d69b2b |
+ 'scope': lines[0].split(' scope=', 1)[1].split(' ',1)[0]
|
|
|
d69b2b |
+ }
|
|
|
d69b2b |
+
|
|
|
d69b2b |
+ def _lint_notes(self):
|
|
|
d69b2b |
+ """
|
|
|
d69b2b |
+ Check for notes=A (fully unindexed searches), and
|
|
|
d69b2b |
+ notes=F (unknown attribute in filter)
|
|
|
d69b2b |
+ """
|
|
|
d69b2b |
+ for pattern, lint_report in [(".* notes=A", DSLOGNOTES0001), (".* notes=F", DSLOGNOTES0002)]:
|
|
|
d69b2b |
+ lines = self.match(pattern)
|
|
|
d69b2b |
+ if len(lines) > 0:
|
|
|
d69b2b |
+ count = 0
|
|
|
d69b2b |
+ searches = []
|
|
|
d69b2b |
+ for line in lines:
|
|
|
d69b2b |
+ if ' RESULT err=' in line:
|
|
|
d69b2b |
+ # Looks like a valid notes=A/F
|
|
|
d69b2b |
+ conn = line.split(' conn=', 1)[1].split(' ',1)[0]
|
|
|
d69b2b |
+ op = line.split(' op=', 1)[1].split(' ',1)[0]
|
|
|
d69b2b |
+ etime = line.split(' etime=', 1)[1].split(' ',1)[0]
|
|
|
d69b2b |
+ stats = self._log_get_search_stats(conn, op)
|
|
|
d69b2b |
+ if stats is not None:
|
|
|
d69b2b |
+ timestamp = stats['timestamp']
|
|
|
d69b2b |
+ base = stats['base']
|
|
|
d69b2b |
+ scope = stats['scope']
|
|
|
d69b2b |
+ srch_filter = stats['filter']
|
|
|
d69b2b |
+ count += 1
|
|
|
d69b2b |
+ if lint_report == DSLOGNOTES0001:
|
|
|
d69b2b |
+ searches.append(f'\n [{count}] Unindexed Search\n'
|
|
|
d69b2b |
+ f' - date: {timestamp}\n'
|
|
|
d69b2b |
+ f' - conn/op: {conn}/{op}\n'
|
|
|
d69b2b |
+ f' - base: {base}\n'
|
|
|
d69b2b |
+ f' - scope: {scope}\n'
|
|
|
d69b2b |
+ f' - filter: {srch_filter}\n'
|
|
|
d69b2b |
+ f' - etime: {etime}\n')
|
|
|
d69b2b |
+ else:
|
|
|
d69b2b |
+ searches.append(f'\n [{count}] Invalid Attribute in Filter\n'
|
|
|
d69b2b |
+ f' - date: {timestamp}\n'
|
|
|
d69b2b |
+ f' - conn/op: {conn}/{op}\n'
|
|
|
d69b2b |
+ f' - filter: {srch_filter}\n')
|
|
|
d69b2b |
+ if len(searches) > 0:
|
|
|
d69b2b |
+ report = copy.deepcopy(lint_report)
|
|
|
d69b2b |
+ report['items'].append(self._get_log_path())
|
|
|
d69b2b |
+ report['detail'] = report['detail'].replace('NUMBER', str(count))
|
|
|
d69b2b |
+ for srch in searches:
|
|
|
d69b2b |
+ report['detail'] += srch
|
|
|
d69b2b |
+ yield report
|
|
|
d69b2b |
+
|
|
|
d69b2b |
|
|
|
d69b2b |
def _get_log_path(self):
|
|
|
d69b2b |
"""Return the current log file location"""
|
|
|
d69b2b |
diff --git a/src/lib389/lib389/lint.py b/src/lib389/lib389/lint.py
|
|
|
d69b2b |
index a103feec7..4b1700b92 100644
|
|
|
d69b2b |
--- a/src/lib389/lib389/lint.py
|
|
|
d69b2b |
+++ b/src/lib389/lib389/lint.py
|
|
|
d69b2b |
@@ -1,5 +1,5 @@
|
|
|
d69b2b |
# --- BEGIN COPYRIGHT BLOCK ---
|
|
|
d69b2b |
-# Copyright (C) 2019 Red Hat, Inc.
|
|
|
d69b2b |
+# Copyright (C) 2020 Red Hat, Inc.
|
|
|
d69b2b |
# All rights reserved.
|
|
|
d69b2b |
#
|
|
|
d69b2b |
# License: GPL (version 3 or any later version).
|
|
|
d69b2b |
@@ -253,7 +253,7 @@ can use the CLI tool "dsconf" to resolve the conflict. Here is an example:
|
|
|
d69b2b |
|
|
|
d69b2b |
Remove conflict entry and keep only the original/counterpart entry:
|
|
|
d69b2b |
|
|
|
d69b2b |
- # dsconf slapd-YOUR_INSTANCE repl-conflict remove <DN of conflict entry>
|
|
|
d69b2b |
+ # dsconf slapd-YOUR_INSTANCE repl-conflict delete <DN of conflict entry>
|
|
|
d69b2b |
|
|
|
d69b2b |
Replace the original/counterpart entry with the conflict entry:
|
|
|
d69b2b |
|
|
|
d69b2b |
@@ -418,3 +418,25 @@ until the time issues have been resolved:
|
|
|
d69b2b |
Also look at https://access.redhat.com/documentation/en-us/red_hat_directory_server/11/html/administration_guide/managing_replication-troubleshooting_replication_related_problems
|
|
|
d69b2b |
and find the paragraph "Too much time skew"."""
|
|
|
d69b2b |
}
|
|
|
d69b2b |
+
|
|
|
d69b2b |
+DSLOGNOTES0001 = {
|
|
|
d69b2b |
+ 'dsle': 'DSLOGNOTES0001',
|
|
|
d69b2b |
+ 'severity': 'Medium',
|
|
|
d69b2b |
+ 'description': 'Unindexed Search',
|
|
|
d69b2b |
+ 'items': ['Performance'],
|
|
|
d69b2b |
+ 'detail': """Found NUMBER fully unindexed searches in the current access log.
|
|
|
d69b2b |
+Unindexed searches can cause high CPU and slow down the entire server's performance.\n""",
|
|
|
d69b2b |
+ 'fix': """Examine the searches that are unindexed, and either properly index the attributes
|
|
|
d69b2b |
+in the filter, increase the nsslapd-idlistscanlimit, or stop using that filter."""
|
|
|
d69b2b |
+}
|
|
|
d69b2b |
+
|
|
|
d69b2b |
+DSLOGNOTES0002 = {
|
|
|
d69b2b |
+ 'dsle': 'DSLOGNOTES0002',
|
|
|
d69b2b |
+ 'severity': 'Medium',
|
|
|
d69b2b |
+ 'description': 'Unknown Attribute In Filter',
|
|
|
d69b2b |
+ 'items': ['Possible Performance Impact'],
|
|
|
d69b2b |
+ 'detail': """Found NUMBER searches in the current access log that are using an
|
|
|
d69b2b |
+unknown attribute in the search filter.\n""",
|
|
|
d69b2b |
+ 'fix': """Stop using this these unknown attributes in the filter, or add the schema
|
|
|
d69b2b |
+to the server and make sure it's properly indexed."""
|
|
|
d69b2b |
+}
|
|
|
d69b2b |
--
|
|
|
d69b2b |
2.26.2
|
|
|
d69b2b |
|