package com.splunk.logging; /** * @copyright * * Copyright 2013-2015 Splunk, Inc. * * 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. */ import java.util.List; /** * @brief Splunk http event collector resend middleware. * * @details * HTTP event collector middleware plug in that implements a simple resend policy. * When HTTP post reply isn't an application error it tries to resend the data. * An exponentially growing delay is used to prevent server overflow. */ public class HttpEventCollectorResendMiddleware extends HttpEventCollectorMiddleware.HttpSenderMiddleware { private long retriesOnError = 0; /** * Create a resend middleware component. * @param retriesOnError is the max retry count. */ public HttpEventCollectorResendMiddleware(long retriesOnError) { this.retriesOnError = retriesOnError; } public void postEvents( final List<HttpEventCollectorEventInfo> events, HttpEventCollectorMiddleware.IHttpSender sender, HttpEventCollectorMiddleware.IHttpSenderCallback callback) { callNext(events, sender, new Callback(events, sender, callback)); } private class Callback implements HttpEventCollectorMiddleware.IHttpSenderCallback { private long retries = 0; private final List<HttpEventCollectorEventInfo> events; private HttpEventCollectorMiddleware.IHttpSenderCallback prevCallback; private HttpEventCollectorMiddleware.IHttpSender sender; private final long RetryDelayCeiling = 60 * 1000; // 1 minute private long retryDelay = 1000; // start with 1 second public Callback( final List<HttpEventCollectorEventInfo> events, HttpEventCollectorMiddleware.IHttpSender sender, HttpEventCollectorMiddleware.IHttpSenderCallback prevCallback) { this.events = events; this.prevCallback = prevCallback; this.sender = sender; } @Override public void completed(int statusCode, final String reply) { if (statusCode != 200) { // resend wouldn't help - report error prevCallback.failed(new HttpEventCollectorErrorHandler.ServerErrorException(reply)); } } @Override public void failed(final Exception ex) { if (retries < retriesOnError) { retries++; try { Thread.sleep(retryDelay); callNext(events, sender, this); } catch (InterruptedException ie) { prevCallback.failed(ie); } // increase delay exponentially retryDelay = Math.min(RetryDelayCeiling, retryDelay * 2); } else { prevCallback.failed(ex); } } } }