Skip to content

Commit d88f761

Browse files
author
David Noble
committed
DVPL-3937: Search Commands: logging.conf shouldn't be required
Verified with automated unit tests and ad-hoc integration tests. Confirmed 100% pass rate on searchcommands test suite on OSX-9. Signed-off-by: David Noble <[email protected]>
1 parent 83aa721 commit d88f761

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

splunklib/searchcommands/logging.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from __future__ import absolute_import
1616

1717
from logging.config import fileConfig
18-
from logging import getLogger
18+
from logging import getLogger, root, StreamHandler
1919
import os
2020

2121

@@ -107,5 +107,8 @@ def configure(name, path=None):
107107
finally:
108108
os.chdir(working_directory)
109109

110+
if len(root.handlers) == 0:
111+
root.addHandler(StreamHandler()) # shared by loggers without handlers
112+
110113
logger = getLogger(name)
111114
return logger, path

tests/searchcommands/data/app/default/logging.conf

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@
22
keys = root, SearchCommand
33

44
[logger_root]
5-
level = WARNING ; Default: WARNING
6-
handlers = stderr ; Default: stderr
5+
level = WARNING ; Default: WARNING
6+
handlers = log_file ; Default: stderr
77

88
[logger_SearchCommand]
99
qualname = SearchCommand
10-
level = NOTSET ; Default: WARNING
11-
handlers = stderr ; Default: stderr
10+
level = NOTSET ; Default: WARNING
11+
handlers = log_file ; Default: stderr
1212

1313
[handlers]
14-
keys=stderr
14+
keys=log_file, stderr
15+
16+
[handler_log_file]
17+
class = logging.FileHandler
18+
level = NOTSET
19+
args = ('app.log',)
20+
formatter = search_command
1521

1622
[handler_stderr]
1723
class = logging.StreamHandler
1824
level = NOTSET
1925
args = (sys.stderr,)
20-
formatter = search_command
2126

2227
[formatters]
2328
keys = search_command

tests/searchcommands/test_decorators.py

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import logging
2626
import os
27-
27+
import sys
2828

2929
@Configuration()
3030
class SearchCommand(StreamingCommand):
@@ -48,6 +48,9 @@ def test_builtin_options(self):
4848
notset = logging.getLevelName(logging.NOTSET)
4949
logging.root.setLevel(logging.WARNING)
5050

51+
while len(logging.root.handlers) > 0:
52+
logging.root.removeHandler(logging.root.handlers[0])
53+
5154
command = SearchCommand()
5255

5356
self.assertEquals(warning, command.logging_level)
@@ -64,21 +67,65 @@ def test_builtin_options(self):
6467
self.assertEquals(command.logging_level, warning if level_name == notset else level_name)
6568

6669
app_root = os.path.join(TestDecorators._package_directory, 'data', 'app')
67-
68-
command = SearchCommand()
70+
command = SearchCommand() # guarantee: no logging.conf
6971
directory = os.getcwd()
7072
os.chdir(os.path.join(app_root, 'bin'))
7173

7274
try:
75+
# In the absence of a logging.conf file, messages are written to
76+
# stderr
77+
78+
self.assertEqual(len(logging.root.handlers), 1)
79+
80+
root_handler = logging.root.handlers[0]
81+
self.assertIsInstance(root_handler, logging.StreamHandler)
82+
self.assertEqual(root_handler.stream, sys.stderr)
83+
84+
self.assertEqual(len(command.logger.handlers), 0)
85+
86+
# TODO: capture this output and verify it
87+
command.logger.warning('Test that output is directed to stderr without formatting')
88+
89+
default_logging_configuration = os.path.join(app_root, 'default', 'logging.conf')
90+
91+
# A search command loads {local,default}/logging.conf when it is
92+
# available
93+
94+
command = SearchCommand() # guarantee: default/logging.conf
95+
self.assertEqual(command.logging_configuration, default_logging_configuration)
96+
7397
# logging_configuration loads a new logging configuration file
7498
# relative to the app root
7599

76100
command.logging_configuration = 'logging.conf'
101+
self.assertEqual(command.logging_configuration, default_logging_configuration)
77102

78103
# logging_configuration loads a new logging configuration file on an
79104
# absolute path
80105

81-
command.logging_configuration = os.path.join(app_root, 'default', 'logging.conf')
106+
command.logging_configuration = default_logging_configuration
107+
self.assertEqual(command.logging_configuration, default_logging_configuration)
108+
109+
# logging_configuration raises a value error, if a non-existent
110+
# logging configuration file is provided
111+
112+
try:
113+
command.logging_configuration = 'foo'
114+
except ValueError:
115+
pass
116+
except BaseException as e:
117+
self.fail('Expected ValueError, but %s was raised' % type(e))
118+
else:
119+
self.fail('Expected ValueError, but logging_configuration=%s' % command.logging_configuration)
120+
121+
try:
122+
command.logging_configuration = os.path.join(TestDecorators._package_directory, 'non-existent.logging.conf')
123+
except ValueError:
124+
pass
125+
except BaseException as e:
126+
self.fail('Expected ValueError, but %s was raised' % type(e))
127+
else:
128+
self.fail('Expected ValueError, but logging_configuration=%s' % command.logging_configuration)
82129

83130
finally:
84131
os.chdir(directory)

0 commit comments

Comments
 (0)