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.cassandra;
018
019import com.datastax.driver.core.BatchStatement;
020import org.apache.logging.log4j.core.Core;
021import org.apache.logging.log4j.core.Filter;
022import org.apache.logging.log4j.core.appender.AbstractAppender;
023import org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender;
024import org.apache.logging.log4j.core.appender.db.ColumnMapping;
025import org.apache.logging.log4j.core.config.plugins.Plugin;
026import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
027import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
028import org.apache.logging.log4j.core.config.plugins.PluginElement;
029import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
030import org.apache.logging.log4j.core.net.SocketAddress;
031import org.apache.logging.log4j.core.util.Clock;
032
033/**
034 * Appender plugin that uses a Cassandra database.
035 *
036 * @see SocketAddress
037 * @see ColumnMapping
038 */
039@Plugin(name = "Cassandra", category = Core.CATEGORY_NAME, elementType = CassandraAppender.ELEMENT_TYPE, printObject = true)
040public class CassandraAppender extends AbstractDatabaseAppender<CassandraManager> {
041
042    private CassandraAppender(final String name, final Filter filter, final boolean ignoreExceptions,
043                              final CassandraManager manager) {
044        super(name, filter, ignoreExceptions, manager);
045    }
046
047    @PluginBuilderFactory
048    public static <B extends Builder<B>> B newBuilder() {
049        return new Builder<B>().asBuilder();
050    }
051
052    public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
053        implements org.apache.logging.log4j.core.util.Builder<CassandraAppender> {
054
055        /**
056         * List of Cassandra node contact points. Addresses without a port (or port set to 0) will use the default
057         * Cassandra port (9042).
058         */
059        @PluginElement("ContactPoints")
060        @Required(message = "No Cassandra servers provided")
061        private SocketAddress[] contactPoints = new SocketAddress[]{SocketAddress.getLoopback()};
062
063        /**
064         * List of column mappings to convert a LogEvent into a database row.
065         */
066        @PluginElement("Columns")
067        @Required(message = "No Cassandra columns provided")
068        private ColumnMapping[] columns;
069
070        @PluginBuilderAttribute
071        private boolean useTls;
072
073        @PluginBuilderAttribute
074        @Required(message = "No cluster name provided")
075        private String clusterName;
076
077        @PluginBuilderAttribute
078        @Required(message = "No keyspace provided")
079        private String keyspace;
080
081        @PluginBuilderAttribute
082        @Required(message = "No table name provided")
083        private String table;
084
085        @PluginBuilderAttribute
086        private String username;
087
088        @PluginBuilderAttribute(sensitive = true)
089        private String password;
090
091        /**
092         * Override the default TimestampGenerator with one based on the configured {@link Clock}.
093         */
094        @PluginBuilderAttribute
095        private boolean useClockForTimestampGenerator;
096
097        /**
098         * Number of LogEvents to buffer before writing. Can be used with or without batch statements.
099         */
100        @PluginBuilderAttribute
101        private int bufferSize;
102
103        /**
104         * Whether or not to use batch statements when inserting records.
105         */
106        @PluginBuilderAttribute
107        private boolean batched;
108
109        /**
110         * If batch statements are enabled, use this type of batch statement.
111         */
112        @PluginBuilderAttribute
113        private BatchStatement.Type batchType = BatchStatement.Type.LOGGED;
114
115        public B setContactPoints(final SocketAddress... contactPoints) {
116            this.contactPoints = contactPoints;
117            return asBuilder();
118        }
119
120        public B setColumns(final ColumnMapping... columns) {
121            this.columns = columns;
122            return asBuilder();
123        }
124
125        public B setUseTls(final boolean useTls) {
126            this.useTls = useTls;
127            return asBuilder();
128        }
129
130        public B setClusterName(final String clusterName) {
131            this.clusterName = clusterName;
132            return asBuilder();
133        }
134
135        public B setKeyspace(final String keyspace) {
136            this.keyspace = keyspace;
137            return asBuilder();
138        }
139
140        public B setTable(final String table) {
141            this.table = table;
142            return asBuilder();
143        }
144
145        public B setUsername(final String username) {
146            this.username = username;
147            return asBuilder();
148        }
149
150        public B setPassword(final String password) {
151            this.password = password;
152            return asBuilder();
153        }
154
155        public B setUseClockForTimestampGenerator(final boolean useClockForTimestampGenerator) {
156            this.useClockForTimestampGenerator = useClockForTimestampGenerator;
157            return asBuilder();
158        }
159
160        public B setBufferSize(final int bufferSize) {
161            this.bufferSize = bufferSize;
162            return asBuilder();
163        }
164
165        public B setBatched(final boolean batched) {
166            this.batched = batched;
167            return asBuilder();
168        }
169
170        public B setBatchType(final BatchStatement.Type batchType) {
171            this.batchType = batchType;
172            return asBuilder();
173        }
174
175        @Override
176        public CassandraAppender build() {
177            final CassandraManager manager = CassandraManager.getManager(getName(), contactPoints, columns, useTls,
178                clusterName, keyspace, table, username, password, useClockForTimestampGenerator, bufferSize, batched,
179                batchType);
180            return new CassandraAppender(getName(), getFilter(), isIgnoreExceptions(), manager);
181        }
182
183    }
184
185}