Skip to content

Commit

Permalink
Add a command to update log level and refresh configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Junchao-Mellanox committed Jul 18, 2024
1 parent 515265a commit 8698c9b
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
49 changes: 49 additions & 0 deletions config/syslog.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,52 @@ def disable_rate_limit_feature(db, service_name, namespace):

if not failed:
click.echo(f'Disabled syslog rate limit feature for {feature_name}')


@syslog.command('level')
@click.option("-c", "--component",
required=True,
help="Component name in DB for which loglevel is applied (provided with -l)")
@click.option("-l", "--level",
required=True,
help="Loglevel value",
type=click.Choice(['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERROR']))
@click.option("--service",
help="Container name to which the SIGHUP is sent (provided with --pid or --program)")
@click.option("--program",
help="Program name to which the SIGHUP is sent (provided with --service)")
@click.option("--pid",
help="Process ID to which the SIGHUP is sent (provided with --service if PID is from container)")
@clicommon.pass_db
def level(db, component, level, service, program, pid):
""" Configure log level """
if program and not service:
raise click.UsageError('--program must be specified with --service')

if service and not program and not pid:
raise click.UsageError('--service must be specified with --pid or --program')

if component and level:
output, ret = clicommon.run_command(['swssloglevel', '-c', component, '-l', level], return_cmd=True)
if ret != 0:
raise click.ClickException(f'Failed: {output}')

if not service and not program and not pid:
return

log_config = db.cfgdb.get_entry('LOGGER', component)
require_manual_refresh = log_config.get('require_manual_refresh')
if not require_manual_refresh:
click.echo(f'Log {component} does not need manual refresh')
return

if service:
if program:
command = ['docker', 'exec', '-i', service, 'supervisorctl', 'signal', 'HUP', program]
else:
command = ['docker', 'exec', '-i', service, 'kill', '-s', 'SIGHUP', pid]
else:
command = ['kill', '-s', 'SIGHUP', pid]
output, ret = clicommon.run_command(command, return_cmd=True)
if ret != 0:
raise click.ClickException(f'Failed: {output}')
29 changes: 29 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -10713,6 +10713,35 @@ This command is used to disable syslog rate limit feature.
config syslog rate-limit-feature disable database -n asci0
```
**config syslog level**
This command is used to configure log level for a given log identifier.
- Usage:
```
config syslog level -c <log_identifier> -l <log_level> --service [<service_name>] --program [<program_name>]
config syslog level -c <log_identifier> -l <log_level> --service [<service_name>] --pid [<process_id>]
config syslog level -c <log_identifier> -l <log_level> ---pid [<process_id>]
```
- Example:
```
# Update the log level without refresh the configuration
config syslog level -c xcvrd -l DEBUG
# Update the log level and send SIGHUP to xcvrd running in PMON
config syslog level -c xcvrd -l DEBUG --service pmon --program xcvrd
# Update the log level and send SIGHUP to PID 20 running in PMON
config syslog level -c xcvrd -l DEBUG --service pmon --pid 20
# Update the log level and send SIGHUP to PID 20 running in host
config syslog level -c xcvrd -l DEBUG --pid 20
```
Go Back To [Beginning of the document](#) or [Beginning of this section](#syslog)
## System State
Expand Down
62 changes: 62 additions & 0 deletions tests/syslog_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,65 @@ def side_effect(*args, **kwargs):
config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db
)
assert result.exit_code == SUCCESS


@mock.patch('config.syslog.clicommon.run_command')
def test_config_log_level(self, mock_run):
db = Db()
db.cfgdb.set_entry('LOGGER', 'log1', {'require_manual_refresh': 'true'})

runner = CliRunner()

mock_run.return_value = ('something', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'component', '-l', 'DEBUG'], obj=db
)
assert result.exit_code == SUCCESS

result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'component', '-l', 'DEBUG', '--pid', '123'], obj=db
)
assert result.exit_code == SUCCESS

result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'component', '-l', 'DEBUG', '--service', 'pmon', '--pid', '123'], obj=db
)
assert result.exit_code == SUCCESS

result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'component', '-l', 'DEBUG', '--service', 'pmon', '--program', 'xcvrd'], obj=db
)
assert result.exit_code == SUCCESS


@mock.patch('config.syslog.clicommon.run_command')
def test_config_log_level_negative(self, mock_run):
db = Db()

runner = CliRunner()

mock_run.return_value = ('something', 0)
result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'log1', '-l', 'DEBUG', '--service', 'pmon'], obj=db
)
assert result.exit_code != SUCCESS

result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'log1', '-l', 'DEBUG', '--program', 'xcvrd'], obj=db
)
assert result.exit_code != SUCCESS

mock_run.reset_mock()
result = runner.invoke(
config.config.commands["syslog"].commands["level"],
['-c', 'log1', '-l', 'DEBUG', '--service', 'swss', '--program', 'orchagent'], obj=db
)
assert result.exit_code == SUCCESS
# Verify it does not send signal to orchagent if require_manual_refresh is not true
assert mock_run.call_count == 1

0 comments on commit 8698c9b

Please sign in to comment.