diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt index d4d6a5799f..a876aa9dde 100644 --- a/Documentation/cmd-index.txt +++ b/Documentation/cmd-index.txt @@ -138,6 +138,12 @@ link:cmd-show-connections.html[gerrit show-connections]:: link:cmd-show-queue.html[gerrit show-queue]:: Display the background work queues, including replication. +link:cmd-logging-ls-level.html[gerrit logging ls-level]:: + List loggers and their logging level. + +link:cmd-logging-set-level.html[gerrit logging set-level]:: + Set the logging level of loggers. + link:cmd-plugin-install.html[gerrit plugin add]:: Alias for 'gerrit plugin install'. diff --git a/Documentation/cmd-logging-ls-level.txt b/Documentation/cmd-logging-ls-level.txt new file mode 100644 index 0000000000..c59dc3f435 --- /dev/null +++ b/Documentation/cmd-logging-ls-level.txt @@ -0,0 +1,43 @@ += gerrit logging ls-level + +== NAME +gerrit logging ls-level - view the logging level + +gerrit logging ls - view the logging level + +== SYNOPSIS +-- +'ssh' -p 'gerrit logging ls-level | ls' + +-- + +== DESCRIPTION +View the logging level of specified loggers. + +== Options +:: + Display the loggers which contain the input argument in their name. If this + argument is not provided, all loggers will be printed. + +== ACCESS +Caller must have the ADMINISTRATE_SERVER capability. + +== Examples + +View the logging level of the loggers in the package com.google: +===== + $ssh -p 29418 review.example.com gerrit logging ls-level \ + com.google. +===== + +View the logging level of every logger +===== + $ssh -p 29418 review.example.com gerrit logging ls-level +===== + +GERRIT +------ +Part of link:index.html[Gerrit Code Review] + +SEARCHBOX +--------- diff --git a/Documentation/cmd-logging-set-level.txt b/Documentation/cmd-logging-set-level.txt new file mode 100644 index 0000000000..38062cb340 --- /dev/null +++ b/Documentation/cmd-logging-set-level.txt @@ -0,0 +1,51 @@ += gerrit logging set-level + +== NAME +gerrit logging set-level - set the logging level + +gerrit logging set - set the logging level + +== SYNOPSIS +-- +'ssh' -p 'gerrit logging set-level | set' + + +-- + +== DESCRIPTION +Set the logging level of specified loggers. + +== Options +:: + Required; logging level for which the loggers should be set. + 'reset' can be used to revert all loggers back to their level + at deployment time. + +:: + Set the level of the loggers which contain the input argument in their name. + If this argument is not provided, all loggers will have their level changed. + Note that this argument has no effect if 'reset' is passed in LEVEL. + +== ACCESS +Caller must have the ADMINISTRATE_SERVER capability. + +== Examples + +Change the logging level of the loggers in the package com.google to DEBUG. +===== + $ssh -p 29418 review.example.com gerrit logging set-level \ + debug com.google. +===== + +Reset the logging level of every logger to what they were at deployment time. +===== + $ssh -p 29418 review.example.com gerrit logging set-level \ + reset +===== + +GERRIT +------ +Part of link:index.html[Gerrit Code Review] + +SEARCHBOX +--------- diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java index f905c5b5cd..cd20f2a830 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java @@ -31,6 +31,7 @@ public class DefaultCommandModule extends CommandModule { protected void configure() { final CommandName git = Commands.named("git"); final CommandName gerrit = Commands.named("gerrit"); + final CommandName logging = Commands.named(gerrit, "logging"); final CommandName plugin = Commands.named(gerrit, "plugin"); final CommandName testSubmit = Commands.named(gerrit, "test-submit"); @@ -98,5 +99,11 @@ public class DefaultCommandModule extends CommandModule { command(gerrit, CreateAccountCommand.class); command(testSubmit, TestSubmitRuleCommand.class); command(testSubmit, TestSubmitTypeCommand.class); + + command(logging).toProvider(new DispatchCommandProvider(logging)); + command(logging, SetLoggingLevelCommand.class); + command(logging, ListLoggingLevelCommand.class); + alias(logging, "ls", ListLoggingLevelCommand.class); + alias(logging, "set", SetLoggingLevelCommand.class); } } diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListLoggingLevelCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListLoggingLevelCommand.java new file mode 100644 index 0000000000..bc6bc17ba0 --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListLoggingLevelCommand.java @@ -0,0 +1,55 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd.commands; + +import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER_OR_SLAVE; + +import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; +import com.google.gerrit.sshd.CommandMetaData; +import com.google.gerrit.sshd.SshCommand; + +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.kohsuke.args4j.Argument; + +import java.util.Enumeration; +import java.util.Map; +import java.util.TreeMap; + +@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER) +@CommandMetaData(name = "ls-level", description = "list the level of loggers", + runsAt = MASTER_OR_SLAVE) +public class ListLoggingLevelCommand extends SshCommand { + + @Argument(index = 0, required = false, metaVar = "NAME", usage = "used to match loggers") + private String name; + + @SuppressWarnings("unchecked") + @Override + protected void run() { + Map logs = new TreeMap<>(); + for (Enumeration logger = LogManager.getCurrentLoggers(); logger + .hasMoreElements();) { + Logger log = logger.nextElement(); + if (name == null || log.getName().contains(name)) { + logs.put(log.getName(), log.getEffectiveLevel().toString()); + } + } + for (Map.Entry e : logs.entrySet()) { + stdout.println(e.getKey() + ": " + e.getValue()); + } + } +} diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetLoggingLevelCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetLoggingLevelCommand.java new file mode 100644 index 0000000000..49edf145d7 --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetLoggingLevelCommand.java @@ -0,0 +1,91 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd.commands; + +import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER_OR_SLAVE; + +import com.google.common.base.Strings; +import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; +import com.google.gerrit.sshd.CommandMetaData; +import com.google.gerrit.sshd.SshCommand; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.helpers.Loader; +import org.kohsuke.args4j.Argument; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; + +@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER) +@CommandMetaData(name = "set-level", description = "Change the level of loggers", + runsAt = MASTER_OR_SLAVE) +public class SetLoggingLevelCommand extends SshCommand { + private static final String LOG_CONFIGURATION = "log4j.properties"; + private static final String JAVA_OPTIONS_LOG_CONFIG = "log4j.configuration"; + + private static enum LevelOption { + ALL, + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + FATAL, + OFF, + RESET, + } + + @Argument(index = 0, required = true, metaVar = "LEVEL", usage = "logging level to set to") + private LevelOption level; + + @Argument(index = 1, required = false, metaVar = "NAME", usage = "used to match loggers") + private String name; + + @SuppressWarnings("unchecked") + @Override + protected void run() throws MalformedURLException { + if (level == LevelOption.RESET) { + reset(); + } else { + for (Enumeration logger = LogManager.getCurrentLoggers(); logger + .hasMoreElements();) { + Logger log = logger.nextElement(); + if (name == null || log.getName().contains(name)) { + log.setLevel(Level.toLevel(level.name())); + } + } + } + } + + @SuppressWarnings("unchecked") + private static void reset() throws MalformedURLException { + for (Enumeration logger = LogManager.getCurrentLoggers(); + logger.hasMoreElements();) { + logger.nextElement().setLevel(null); + } + + String path = System.getProperty(JAVA_OPTIONS_LOG_CONFIG); + if (Strings.isNullOrEmpty(path)) { + PropertyConfigurator.configure(Loader.getResource(LOG_CONFIGURATION)); + } else { + PropertyConfigurator.configure(new URL(path)); + } + } +}