<!--
  ~ Copyright 2009 the original author or authors.
  ~
  ~ 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.
  -->
<chapter id='logging' xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>Logging</title>
    <para>The log is the main 'UI' of a build tool. If it is too verbose, real warnings and problems are easily hidden
        by this. On the other hand you need the relevant information for figuring out if things have gone wrong. Gradle
        defines 6 log levels, as shown in <xref linkend="logLevels"/>. There are two Gradle-specific log levels, in
        addition to the ones you might normally see. Those levels are <emphasis>QUIET</emphasis> and
        <emphasis>LIFECYCLE</emphasis>. The latter is the default, and is used to report build progress.
    </para>
    <table id="logLevels">
        <title>Log levels</title>
        <thead>
            <tr>
                <td>Level</td>
                <td>Used for</td>
            </tr>
        </thead>
        <tr>
            <td>ERROR</td>
            <td>Error messages</td>
        </tr>
        <tr>
            <td>QUIET</td>
            <td>Important information messages</td>
        </tr>
        <tr>
            <td>WARNING</td>
            <td>Warning messages</td>
        </tr>
        <tr>
            <td>LIFECYCLE</td>
            <td>Progress information messages</td>
        </tr>
        <tr>
            <td>INFO</td>
            <td>Information messages</td>
        </tr>
        <tr>
            <td>DEBUG</td>
            <td>Debug messages</td>
        </tr>
    </table>
    <section id='sec:choosing_a_log_level'>
        <title>Choosing a log level</title>
        <para>You can use the command line switches shown in <xref linkend='logLevelCommandLineOptions'/> to choose
            different log levels. In <xref linkend='stacktraces'/> you find the command line switches which affect
            stacktrace logging.
        </para>
        <table id='logLevelCommandLineOptions'>
            <title>Log level command-line options</title>
            <thead>
                <tr>
                    <td>Option</td>
                    <td>Outputs Log Levels</td>
                </tr>
            </thead>
            <tr>
                <td>no logging options</td>
                <td>LIFECYCLE and higher</td>
            </tr>
            <tr>
                <td>
                    <literal>-q</literal>
                </td>
                <td>QUIET and higher</td>
            </tr>
            <tr>
                <td>
                    <literal>-i</literal>
                </td>
                <td>INFO and higher</td>
            </tr>
            <tr>
                <td>
                    <literal>-d</literal>
                </td>
                <td>DEBUG and higher (that is, all log messages)</td>
            </tr>

        </table>
        <table id='stacktraces'>
            <title>Stacktrace command-line options</title>
            <thead>
                <tr>
                    <td>Option</td>
                    <td>Meaning</td>
                </tr>
            </thead>
            <tr>
                <td>No stacktrace options</td>
                <td>No stacktraces are printed to the console in case of a build error (e.g. a compile error). Only in
                    case of internal exceptions will stacktraces be printed. If the loglevel option <literal>-d</literal>
                    is chosen, truncated stacktraces are always printed.
                </td>
            </tr>
            <tr>
                <td>
                    <literal>-s</literal>
                </td>
                <td>Truncated stacktraces are printed. We recommend this over full stacktraces. Groovy full stacktraces
                    are extremely verbose (Due to the underlying dynamic invocation mechanisms. Yet they usually do not
                    contain relevant information for what has gone wrong in <emphasis>your</emphasis> code.)
                </td>
            </tr>
            <tr>
                <td>
                    <literal>-f</literal>
                </td>
                <td>The full stacktraces are printed out.</td>
            </tr>

        </table>
    </section>
    <section id='sec:sending_your_own_log_messages'>
        <title>Writing your own log messages</title>
        <para>A simple option for logging in your build file is to write messages to standard output. Gradle redirects
            anything written to standard output to it's logging system at the <literal>QUIET</literal> log level.</para>
        <sample id="logging_to_stdout" dir="userguide/tutorial/logging" title="Using stdout to write log messages">
            <sourcefile file="build.gradle" snippet="use-println"/>
        </sample>
        <para>Gradle also provides a <literal>logger</literal> property to a build script, which is an instance of
            <apilink class="org.gradle.api.logging.Logger"/>. This interface extends the SLF4J
            <classname>Logger</classname> interface and adds a few Gradle specific methods to it. Below is an example
            of how this is used in the build script:
        </para>
        <sample id="logging_ex" dir="userguide/tutorial/logging" title="Writing your own log messages">
            <sourcefile file="build.gradle" snippet="use-logger"/>
        </sample>
        <para>You can also hook into Gradle's logging system from within other classes used in the build (classes from
            the <filename>buildSrc</filename> directory for example). Simply use an SLF4J logger. You can use this
            logger the same way as you use the provided logger in the build script.
        </para>
        <sample id="logging_with_slf4j" dir="userguide/tutorial/logging" title="Using SLF4J to write log messages">
            <sourcefile file="build.gradle" snippet="use-slf4j"/>
        </sample>
    </section>

    <section id='sec:external_tools'>
        <title>Logging from external tools and libraries</title>
        <para>Internally, Gradle uses Ant and Ivy. Both have their own logging system. Gradle redirects their logging
            output into the Gradle logging system. There is a 1:1 mapping from the Ant/Ivy log levels to the Gradle log
            levels, except the Ant/Ivy <literal>TRACE</literal> log level, which is mapped to Gradle
            <literal>DEBUG</literal> log level. This means the default Gradle log level will not show any Ant/Ivy output
            unless it is an error or a warning.
        </para>
        <para>There are many tools out there which still use standard output for logging. By default, Gradle redirects
            standard output to the <literal>QUIET</literal> log level and standard error to the <literal>ERROR</literal>
            level. This behavior is configurable. The project object provides a
            <apilink class="org.gradle.api.logging.LoggingManager"/>, which allows you to change the log levels that
            standard out or error are redirected to when your build script is evaluated.</para>
        <sample id="project_stdout_capture" dir="userguide/tutorial/logging" title="Configuring standard output capture">
            <sourcefile file="build.gradle" snippet="capture-stdout"/>
        </sample>
        <para>
            To change the log level for standard out or error during task execution, tasks also provide a <apilink class="org.gradle.api.logging.LoggingManager"/>.
        </para>
        <sample id="task_stdout_capture" dir="userguide/tutorial/logging" title="Configuring standard output capture for a task">
            <sourcefile file="build.gradle" snippet="task-capture-stdout"/>
            <test args="logInfo"/>
        </sample>
        <para>Gradle also provides integration with the Java Util Logging, Jakarta Commons Logging and Log4j logging
            toolkits. Any log messages which your build classes write using these logging toolkits will be redirected to
            Gradle's logging system.
        </para>
    </section>

    <section id="sec:changing_what_gradle_logs">
        <title>Changing what Gradle logs</title>
        <para>You can replace much of Gradle's logging UI with your own. You might do this, for example, if you want to
            customize the UI in some way - to log more or less information, or to change the formatting. You replace
            the logging using the <apilink class="org.gradle.api.invocation.Gradle" method="useLogger"/> method. This
            is accessable from a build script, or an init script, or via the embedding API. Below is an example
            init script which changes how task execution and build completion is logged.
        </para>
        <sample id="custom_logging_ui" dir="userguide/initScripts/customLogger" title="Customizing what Gradle logs">
            <sourcefile file="init.gradle"/>
            <output args="-I init.gradle build"/>
        </sample>
        <para>Your logger can implement any of the listener interfaces listed below.
            When you register a logger, only the logging for the interfaces that it implements is replaced. Logging
            for the other interfaces is left untouched.
            You can find out more about the listener interfaces in <xref linkend="build_lifecycle_events"/>.
            <itemizedlist>
                <listitem><para><apilink class="org.gradle.BuildListener"/></para></listitem>
                <listitem><para><apilink class="org.gradle.api.ProjectEvaluationListener"/></para></listitem>
                <listitem><para><apilink class="org.gradle.api.execution.TaskExecutionGraphListener"/></para></listitem>
                <listitem><para><apilink class="org.gradle.api.execution.TaskExecutionListener"/></para></listitem>
                <listitem><para><apilink class="org.gradle.api.execution.TaskActionListener"/></para></listitem>
            </itemizedlist>
        </para>
    </section>
</chapter>
