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