Skip to content

Commit 88ef85c

Browse files
Add a command to update log level and refresh configuration (#3428)
* Add a command to update log level and refresh configuration * Multi ASIC support * Fix pre-commit issue * Fix comment Fix review comment
1 parent 910252c commit 88ef85c

File tree

4 files changed

+169
-0
lines changed

4 files changed

+169
-0
lines changed

config/syslog.py

+54
Original file line numberDiff line numberDiff line change
@@ -642,3 +642,57 @@ def disable_rate_limit_feature(db, service_name, namespace):
642642

643643
if not failed:
644644
click.echo(f'Disabled syslog rate limit feature for {feature_name}')
645+
646+
647+
@syslog.command('level')
648+
@click.option("-i", "--identifier",
649+
required=True,
650+
help="Log identifier in DB for which loglevel is applied (provided with -l)")
651+
@click.option("-l", "--level",
652+
required=True,
653+
help="Loglevel value",
654+
type=click.Choice(['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERROR']))
655+
@click.option("--container",
656+
help="Container name to which the SIGHUP is sent (provided with --pid or --program)")
657+
@click.option("--program",
658+
help="Program name to which the SIGHUP is sent (provided with --container)")
659+
@click.option("--pid",
660+
help="Process ID to which the SIGHUP is sent (provided with --container if PID is from container)")
661+
@click.option('--namespace', '-n', 'namespace', default=None,
662+
type=click.Choice(multi_asic_util.multi_asic_ns_choices()),
663+
show_default=True, help='Namespace name')
664+
@clicommon.pass_db
665+
def level(db, identifier, level, container, program, pid, namespace):
666+
""" Configure log level """
667+
if program and not container:
668+
raise click.UsageError('--program must be specified with --container')
669+
670+
if container and not program and not pid:
671+
raise click.UsageError('--container must be specified with --pid or --program')
672+
673+
if not namespace:
674+
cfg_db = db.cfgdb
675+
else:
676+
asic_id = multi_asic.get_asic_id_from_name(namespace)
677+
container = f'{container}{asic_id}'
678+
cfg_db = db.cfgdb_clients[namespace]
679+
680+
cfg_db.mod_entry('LOGGER', identifier, {'LOGLEVEL': level})
681+
if not container and not program and not pid:
682+
return
683+
684+
log_config = cfg_db.get_entry('LOGGER', identifier)
685+
require_manual_refresh = log_config.get('require_manual_refresh')
686+
if not require_manual_refresh:
687+
return
688+
689+
if container:
690+
if program:
691+
command = ['docker', 'exec', '-i', container, 'supervisorctl', 'signal', 'HUP', program]
692+
else:
693+
command = ['docker', 'exec', '-i', container, 'kill', '-s', 'SIGHUP', pid]
694+
else:
695+
command = ['kill', '-s', 'SIGHUP', pid]
696+
output, ret = clicommon.run_command(command, return_cmd=True)
697+
if ret != 0:
698+
raise click.ClickException(f'Failed: {output}')

doc/Command-Reference.md

+29
Original file line numberDiff line numberDiff line change
@@ -10858,6 +10858,35 @@ This command is used to disable syslog rate limit feature.
1085810858
config syslog rate-limit-feature disable database -n asci0
1085910859
```
1086010860
10861+
**config syslog level**
10862+
10863+
This command is used to configure log level for a given log identifier.
10864+
10865+
- Usage:
10866+
```
10867+
config syslog level -i <log_identifier> -l <log_level> --container [<container_name>] --program [<program_name>]
10868+
10869+
config syslog level -i <log_identifier> -l <log_level> --container [<container_name>] --pid [<process_id>]
10870+
10871+
config syslog level -i <log_identifier> -l <log_level> ---pid [<process_id>]
10872+
```
10873+
10874+
- Example:
10875+
10876+
```
10877+
# Update the log level without refresh the configuration
10878+
config syslog level -i xcvrd -l DEBUG
10879+
10880+
# Update the log level and send SIGHUP to xcvrd running in PMON
10881+
config syslog level -i xcvrd -l DEBUG --container pmon --program xcvrd
10882+
10883+
# Update the log level and send SIGHUP to PID 20 running in PMON
10884+
config syslog level -i xcvrd -l DEBUG --container pmon --pid 20
10885+
10886+
# Update the log level and send SIGHUP to PID 20 running in host
10887+
config syslog level -i xcvrd -l DEBUG --pid 20
10888+
```
10889+
1086110890
Go Back To [Beginning of the document](#) or [Beginning of this section](#syslog)
1086210891
1086310892
## System State

tests/syslog_multi_asic_test.py

+16
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,19 @@ def test_disable_syslog_rate_limit_feature(self, setup_cmd_module):
279279
['database', '-n', 'asic0']
280280
)
281281
assert result.exit_code == 0
282+
283+
@mock.patch('config.syslog.clicommon.run_command')
284+
def test_config_log_level(self, mock_run, setup_cmd_module):
285+
_, config = setup_cmd_module
286+
db = Db()
287+
runner = CliRunner()
288+
289+
mock_run.return_value = ('something', 0)
290+
result = runner.invoke(
291+
config.config.commands["syslog"].commands["level"],
292+
['-i', 'component', '-l', 'DEBUG', '-n', 'asic0'], obj=db
293+
)
294+
assert result.exit_code == 0
295+
cfg_db = db.cfgdb_clients['asic0']
296+
data = cfg_db.get_entry('LOGGER', 'component')
297+
assert data.get('LOGLEVEL') == 'DEBUG'

tests/syslog_test.py

+70
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,73 @@ def side_effect(*args, **kwargs):
484484
config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db
485485
)
486486
assert result.exit_code == SUCCESS
487+
488+
@mock.patch('config.syslog.clicommon.run_command')
489+
def test_config_log_level(self, mock_run):
490+
db = Db()
491+
db.cfgdb.set_entry('LOGGER', 'log1', {'require_manual_refresh': 'true'})
492+
493+
runner = CliRunner()
494+
495+
mock_run.return_value = ('something', 0)
496+
result = runner.invoke(
497+
config.config.commands["syslog"].commands["level"],
498+
['-i', 'component', '-l', 'DEBUG'], obj=db
499+
)
500+
assert result.exit_code == SUCCESS
501+
data = db.cfgdb.get_entry('LOGGER', 'component')
502+
assert data.get('LOGLEVEL') == 'DEBUG'
503+
504+
result = runner.invoke(
505+
config.config.commands["syslog"].commands["level"],
506+
['-i', 'component', '-l', 'DEBUG', '--pid', '123'], obj=db
507+
)
508+
assert result.exit_code == SUCCESS
509+
510+
result = runner.invoke(
511+
config.config.commands["syslog"].commands["level"],
512+
['-i', 'component', '-l', 'DEBUG', '--container', 'pmon', '--pid', '123'], obj=db
513+
)
514+
assert result.exit_code == SUCCESS
515+
516+
result = runner.invoke(
517+
config.config.commands["syslog"].commands["level"],
518+
['-i', 'component', '-l', 'DEBUG', '--container', 'pmon', '--program', 'xcvrd'], obj=db
519+
)
520+
assert result.exit_code == SUCCESS
521+
522+
@mock.patch('config.syslog.clicommon.run_command')
523+
def test_config_log_level_negative(self, mock_run):
524+
db = Db()
525+
526+
runner = CliRunner()
527+
528+
mock_run.return_value = ('something', 0)
529+
result = runner.invoke(
530+
config.config.commands["syslog"].commands["level"],
531+
['-i', 'log1', '-l', 'DEBUG', '--container', 'pmon'], obj=db
532+
)
533+
assert result.exit_code != SUCCESS
534+
535+
result = runner.invoke(
536+
config.config.commands["syslog"].commands["level"],
537+
['-i', 'log1', '-l', 'DEBUG', '--program', 'xcvrd'], obj=db
538+
)
539+
assert result.exit_code != SUCCESS
540+
541+
mock_run.reset_mock()
542+
result = runner.invoke(
543+
config.config.commands["syslog"].commands["level"],
544+
['-i', 'log1', '-l', 'DEBUG', '--container', 'swss', '--program', 'orchagent'], obj=db
545+
)
546+
assert result.exit_code == SUCCESS
547+
# Verify it does not send signal to orchagent if require_manual_refresh is not true
548+
assert mock_run.call_count == 0
549+
550+
mock_run.return_value = ('something', -1)
551+
db.cfgdb.set_entry('LOGGER', 'log1', {'require_manual_refresh': 'true'})
552+
result = runner.invoke(
553+
config.config.commands["syslog"].commands["level"],
554+
['-i', 'log1', '-l', 'DEBUG', '--container', 'pmon', '--program', 'xcvrd'], obj=db
555+
)
556+
assert result.exit_code != SUCCESS

0 commit comments

Comments
 (0)