001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.layout;
018
019import java.io.IOException;
020import java.nio.charset.Charset;
021
022import org.apache.commons.csv.CSVFormat;
023import org.apache.commons.csv.QuoteMode;
024import org.apache.logging.log4j.core.Layout;
025import org.apache.logging.log4j.core.LogEvent;
026import org.apache.logging.log4j.core.config.Configuration;
027import org.apache.logging.log4j.core.config.Node;
028import org.apache.logging.log4j.core.config.plugins.Plugin;
029import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
030import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
031import org.apache.logging.log4j.core.config.plugins.PluginFactory;
032import org.apache.logging.log4j.status.StatusLogger;
033
034/**
035 * A Comma-Separated Value (CSV) layout to log events.
036 *
037 * Depends on Apache Commons CSV 1.2.
038 *
039 * @since 2.4
040 */
041@Plugin(name = "CsvLogEventLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
042public class CsvLogEventLayout extends AbstractCsvLayout {
043
044    public static CsvLogEventLayout createDefaultLayout() {
045        return new CsvLogEventLayout(null, Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null);
046    }
047
048    public static CsvLogEventLayout createLayout(final CSVFormat format) {
049        return new CsvLogEventLayout(null, Charset.forName(DEFAULT_CHARSET), format, null, null);
050    }
051
052    @PluginFactory
053    public static CsvLogEventLayout createLayout(
054            // @formatter:off
055            @PluginConfiguration final Configuration config,
056            @PluginAttribute(value = "format", defaultString = DEFAULT_FORMAT) final String format,
057            @PluginAttribute("delimiter") final Character delimiter,
058            @PluginAttribute("escape") final Character escape,
059            @PluginAttribute("quote") final Character quote,
060            @PluginAttribute("quoteMode") final QuoteMode quoteMode,
061            @PluginAttribute("nullString") final String nullString,
062            @PluginAttribute("recordSeparator") final String recordSeparator,
063            @PluginAttribute(value = "charset", defaultString = DEFAULT_CHARSET) final Charset charset,
064            @PluginAttribute("header") final String header,
065            @PluginAttribute("footer") final String footer)
066            // @formatter:on
067    {
068
069        final CSVFormat csvFormat = createFormat(format, delimiter, escape, quote, quoteMode, nullString, recordSeparator);
070        return new CsvLogEventLayout(config, charset, csvFormat, header, footer);
071    }
072
073    protected CsvLogEventLayout(final Configuration config, final Charset charset, final CSVFormat csvFormat, final String header, final String footer) {
074        super(config, charset, csvFormat, header, footer);
075    }
076
077    @Override
078    public String toSerializable(final LogEvent event) {
079        final StringBuilder buffer = getStringBuilder();
080        final CSVFormat format = getFormat();
081        try {
082            format.print(event.getNanoTime(), buffer, true);
083            format.print(event.getTimeMillis(), buffer, false);
084            format.print(event.getLevel(), buffer, false);
085            format.print(event.getThreadId(), buffer, false);
086            format.print(event.getThreadName(), buffer, false);
087            format.print(event.getThreadPriority(), buffer, false);
088            format.print(event.getMessage().getFormattedMessage(), buffer, false);
089            format.print(event.getLoggerFqcn(), buffer, false);
090            format.print(event.getLoggerName(), buffer, false);
091            format.print(event.getMarker(), buffer, false);
092            format.print(event.getThrownProxy(), buffer, false);
093            format.print(event.getSource(), buffer, false);
094            format.print(event.getContextData(), buffer, false);
095            format.print(event.getContextStack(), buffer, false);
096            format.println(buffer);
097            return buffer.toString();
098        } catch (final IOException e) {
099            StatusLogger.getLogger().error(event.toString(), e);
100            return format.getCommentMarker() + " " + e;
101        }
102    }
103
104}