All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kdgregory.log4j2.aws.SNSAppender Maven / Gradle / Ivy

There is a newer version: 3.2.1
Show newest version
// Copyright (c) Keith D Gregory
//
// 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.kdgregory.log4j2.aws;

import java.util.Date;

import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;

import com.kdgregory.log4j2.aws.internal.AbstractAppender;
import com.kdgregory.log4j2.aws.internal.AbstractAppenderBuilder;
import com.kdgregory.log4j2.aws.internal.SNSAppenderConfig;
import com.kdgregory.logging.aws.sns.SNSWriterConfig;
import com.kdgregory.logging.aws.sns.SNSWriterFactory;
import com.kdgregory.logging.aws.sns.SNSWriterStatistics;
import com.kdgregory.logging.aws.sns.SNSWriterStatisticsMXBean;
import com.kdgregory.logging.aws.common.Substitutions;
import com.kdgregory.logging.common.factories.DefaultThreadFactory;
import com.kdgregory.logging.common.util.InternalLogger;


/**
 *  An appender that writes to an SNS topic.
 *  

* This appender supports the following configuration parameters: *

*

* * * * * * * * * * * *
topicName * The name of the destination SNS topic; substitutions are allowed. *

* Must refer to a topic in the current region; if not, and you do not * enable auto-create, initialization fails. *

* If you specify both topicName and topicArn, * the latter takes precedence. * *

topicArn * The ARN of the destination SNS topic; substitutions are allowed. *

* Must refer to a topic in the current region; if not, initialization * fails. *

* If you specify both topicName and topicArn, * the latter takes precedence. * *

autoCreate * If true, and the topic is specified by name, the appender will create * the topic if it does not already exist. If false, a missing topic * will be reported as an error and the appender will be disabled. *

* Default is false. * *

subject * (optional) The subject for messages that are delivered via email. This * is constrained by the SNS API to be less than 100 characters, ASCII * only, and not start with whitespace. * *
discardThreshold * The number of unsent messages that will trigger message discard. A * high value is useful when network connectivity is intermittent and/or * overall AWS communication is causing throttling. However, a value that * is too high may cause out-of-memory errors. *

* The default, 10,000, is based on the assumptions that (1) each message * will be 1k or less, and (2) any app that uses remote logging can afford * 10MB. * *

discardAction * The action to take when the number of unsent messages exceeds the * discard threshold. Values are "none" (retain all messages), "oldest" * (discard oldest messages), and "newest" (discard most recent messages). *

* The default is "oldest". Attempting to set an incorrect value will throw * a configuration error. * *

assumedRole * Specifies role name or ARN that will be assumed by this appender. Useful * for cross-account logging. If the appender does not have permission to * assume this role, initialization will fail. * *
clientFactory * The fully-qualified name of a static method to create the correct AWS * client, which will be called instead of the writer's internal client * factory. This is useful if you need non-default configuration, such as * using a proxy server. *

* The passed string is of the form com.example.Classname.methodName. * If this does not reference a class/method on the classpath then writer * initialization will fail. * *

clientRegion * Specifies a non-default service region. This setting is ignored if you * use a client factory. *

* Note that the region must be supported by the current SDK version. * *

clientEndpoint * Specifies a non-default service endpoint. This is intended for use with * older AWS SDK versions that do not provide client factories and default * to us-east-1 for constructed clients, although it can be used for newer * releases when you want to override the default region provider. This * setting is ignored if you use a client factory. * *
useShutdownHook * Controls whether the appender uses a shutdown hook to attempt to process * outstanding messages when the JVM exits. This is true by default; set to * false to disable. *
* * @see Appender documentation */ @Plugin(name = "SNSAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) public class SNSAppender extends AbstractAppender { //---------------------------------------------------------------------------- // Builder //---------------------------------------------------------------------------- @PluginBuilderFactory public static SNSAppenderBuilder newBuilder() { return new SNSAppenderBuilder(); } public static class SNSAppenderBuilder extends AbstractAppenderBuilder implements SNSAppenderConfig, org.apache.logging.log4j.core.util.Builder { // this appender has different defaults than others, and while I could // have created an arg-taking constructor for AbstractAppenderBuilder, // I'm a little worred that Log4J might try to do something bizarre public SNSAppenderBuilder() { setDiscardThreshold(1000); } @PluginBuilderAttribute("name") @Required(message = "SNSAppender: no name provided") private String name; public SNSAppenderBuilder setName(String value) { this.name = value; return this; } @Override public String getName() { return name; } @PluginBuilderAttribute("topicName") private String topicName; /** * Sets the topicName configuration property. */ public SNSAppenderBuilder setTopicName(String value) { this.topicName = value; return this; } /** * Returns the topicName configuration property, null * if the appender was configured via ARN. */ @Override public String getTopicName() { return topicName; } @PluginBuilderAttribute("topicArn") private String topicArn; /** * Sets the topicArn configuration property. */ public SNSAppenderBuilder setTopicArn(String value) { this.topicArn = value; return this; } /** * Returns the topicArn configuration property, null * if the appender was configured via name. */ @Override public String getTopicArn() { return topicArn; } @PluginBuilderAttribute("autoCreate") private boolean autoCreate; /** * Sets the autoCreate configuration property. */ public SNSAppenderBuilder setAutoCreate(boolean value) { this.autoCreate = value; return this; } /** * Returns the autoCreate configuration property. */ @Override public boolean isAutoCreate() { return autoCreate; } @PluginBuilderAttribute("subject") private String subject; /** * Sets the subject configuration property. */ public SNSAppenderBuilder setSubject(String value) { this.subject = value; return this; } /** * Returns the subject configuration property. */ @Override public String getSubject() { return subject; } @Override public long getBatchDelay() { // we want a different default than other appenders, and we can't prevent // Log4J from changing it (because it bypasses the setter), so we'll return // a constant ... unless the super returns 0, which means synchronous mode long value = super.getBatchDelay(); return (value == 0) ? 0 : 1; } @Override public SNSAppender build() { return new SNSAppender(name, this, null); } } //---------------------------------------------------------------------------- // Appender //---------------------------------------------------------------------------- // this is extracted from config so that we can validate protected Integer retentionPeriod; protected SNSAppender(String name, SNSAppenderConfig config, InternalLogger internalLogger) { super( name, new DefaultThreadFactory("log4j2-kinesis"), new SNSWriterFactory(), new SNSWriterStatistics(), SNSWriterStatisticsMXBean.class, config, internalLogger); } //---------------------------------------------------------------------------- // Additional public API //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Internals //---------------------------------------------------------------------------- @Override protected SNSWriterConfig generateWriterConfig() { StrSubstitutor l4jsubs = config.getConfiguration().getStrSubstitutor(); Substitutions subs = new Substitutions(new Date(), sequence.get()); String actualTopicName = subs.perform(l4jsubs.replace(config.getTopicName())); String actualTopicArn = subs.perform(l4jsubs.replace(config.getTopicArn())); String actualSubject = subs.perform(l4jsubs.replace(config.getSubject())); return new SNSWriterConfig( actualTopicName, actualTopicArn, actualSubject, config.isAutoCreate(), config.getDiscardThreshold(), discardAction, config.getClientFactory(), config.getAssumedRole(), config.getClientRegion(), config.getClientEndpoint()); } @Override protected boolean shouldRotate(long now) { return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy