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

software.amazon.cloudformation.loggers.CloudWatchLogPublisher Maven / Gradle / Ivy

/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
*  http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.cloudformation.loggers;

import com.amazonaws.services.lambda.runtime.LambdaLogger;

import java.time.Instant;
import java.util.Date;

import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient;
import software.amazon.awssdk.services.cloudwatchlogs.model.InputLogEvent;
import software.amazon.awssdk.services.cloudwatchlogs.model.PutLogEventsRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.PutLogEventsResponse;
import software.amazon.cloudformation.injection.CloudWatchLogsProvider;
import software.amazon.cloudformation.proxy.MetricsPublisherProxy;

public class CloudWatchLogPublisher extends LogPublisher {

    private final CloudWatchLogsProvider cloudWatchLogsProvider;

    private CloudWatchLogsClient cloudWatchLogsClient;
    private String logGroupName;
    private String logStreamName;
    private LambdaLogger platformLambdaLogger;
    private MetricsPublisherProxy metricsPublisherProxy;

    // Note: PutLogEvents returns a result that includes a sequence number.
    // That same sequence number must be used in the subsequent put for the same
    // (log group, log stream) pair.
    // Ref: https://forums.aws.amazon.com/message.jspa?messageID=676799
    private String nextSequenceToken = null;

    public CloudWatchLogPublisher(final CloudWatchLogsProvider cloudWatchLogsProvider,
                                  final String logGroupName,
                                  final String logStreamName,
                                  final LambdaLogger platformLambdaLogger,
                                  final MetricsPublisherProxy metricsPublisherProxy,
                                  final LogFilter... logFilters) {
        super(logFilters);
        this.cloudWatchLogsProvider = cloudWatchLogsProvider;
        this.logGroupName = logGroupName;
        this.logStreamName = logStreamName;
        this.platformLambdaLogger = platformLambdaLogger;
        this.metricsPublisherProxy = metricsPublisherProxy;
    }

    public void refreshClient() {
        this.cloudWatchLogsClient = cloudWatchLogsProvider.get();
    }

    @Override
    protected void publishMessage(final String message) {
        try {
            if (skipLogging()) {
                return;
            }
            assert cloudWatchLogsClient != null : "cloudWatchLogsClient was not initialised. "
                + "You must call refreshClient() first.";
            PutLogEventsResponse putLogEventsResponse = cloudWatchLogsClient.putLogEvents(PutLogEventsRequest.builder()
                .sequenceToken(nextSequenceToken).logGroupName(logGroupName).logStreamName(logStreamName)
                .logEvents(InputLogEvent.builder().message(message).timestamp(new Date().getTime()).build()).build());

            nextSequenceToken = putLogEventsResponse.nextSequenceToken();
        } catch (final Exception ex) {
            platformLambdaLogger.log(
                String.format("An error occurred while putting log events [%s] " + "to resource owner account, with error: %s",
                    message, ex.toString()));
            emitMetricsForLoggingFailure(ex);
        }
    }

    private boolean skipLogging() {
        return logStreamName == null;
    }

    private void emitMetricsForLoggingFailure(final Exception ex) {
        if (this.metricsPublisherProxy != null) {
            this.metricsPublisherProxy.publishProviderLogDeliveryExceptionMetric(Instant.now(), ex);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy