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

com.pronoia.splunk.eventcollector.client.SimpleEventCollectorClient Maven / Gradle / Ivy

Go to download

A library to assist in building property-formatted JSON payloads for Splunk Events, and delivering those events to a Splunk HTTP Event Collector

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.pronoia.splunk.eventcollector.client;

import com.pronoia.splunk.eventcollector.EventDeliveryException;
import com.pronoia.splunk.eventcollector.EventDeliveryHttpException;

import java.io.IOException;

import java.lang.management.ManagementFactory;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;


/**
 * Simple Client for sending JSON-formatted events to a single Splunk HTTP
 * Collector.
 */
public class SimpleEventCollectorClient extends AbstractEventCollectorClient implements SimpleEventCollectorClientMBean {
    static final int RETRY_COUNT = 3;
    static final long CONNECTION_TIME_TO_LIVE_MILLIS = 500;

    CloseableHttpClient httpClient;

    ObjectName clientObjectName;

    Date startTime;
    Date lastEventTime;
    Date stopTime;

    long eventCount;

    /**
     * Create a new EventCollectorClient.
     */
    public SimpleEventCollectorClient() {
    }

   /**
     * Determine if the instance has been intialized.
     *
     * @return true if the instance has been intialized; false otherwise
     */
    public boolean isInitialized() {
        return (httpClient == null) ? false : true;
    }

    @Override
    public Date getStartTime() {
        return startTime;
    }

    @Override
    public Date getLastEventTime() {
        return lastEventTime;
    }

    @Override
    public long getEventCount() {
        return eventCount;
    }

    @Override
    public Date getStopTime() {
        return stopTime;
    }

    public synchronized void initialize() {
        registerMBean();
        start();
    }

    public synchronized void destroy() {
        stop();
        unregisterMBean();
    }

    /**
     * Start the HTTP Event Collector client instance.
     */
    @Override
    public synchronized void start() {
        if (httpClient == null) {
            HttpClientBuilder clientBuilder = HttpClients.custom();
            clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(RETRY_COUNT,true))
                    .setConnectionTimeToLive(CONNECTION_TIME_TO_LIVE_MILLIS, TimeUnit.MILLISECONDS);
            if (!eventCollectorInfo.isCertificateValidationEnabled()) {
                clientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
                try {
                    SSLContext sslContext = new SSLContextBuilder()
                            .loadTrustMaterial(null, new AcceptAllTrustStrategy())
                            .build();
                    clientBuilder.setSSLContext(sslContext);
                } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException ex) {
                    throw new IllegalStateException("Failed to create SSL Context", ex);
                }

            }

            httpClient = clientBuilder.build();
            startTime = new Date();
        } else {
            log.warn("{} already initialized - ignoring 'initialize()' call", this.getClass().getSimpleName());
        }

    }

    /**
     * Stop the HTTP Event Collector client instance.
     */
    @Override
    public synchronized void stop() {
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (Exception closeEx) {
                log.info("Ignoring exception encountered closing the HTTP Client", closeEx);
            } finally {
                httpClient = null;
                stopTime = new Date();
            }
        } else {
            log.warn("{} is not initialized - ignoring 'destroy()' call", this.getClass().getSimpleName());
        }
    }

    /**
     * Restart the HTTP Event Collector client instance.
     */
    @Override
    public synchronized void restart() {
        stop();
        try {
            Thread.sleep(5000);
            start();
        } catch (InterruptedException interruptedEx) {
            log.warn("Restart was interrupted - consumer will not be restarted", interruptedEx);
        }
    }

    /**
     * Send and event to the the HTTP Event Collector client.
     */
    @Override
    public void sendEvent(final String event) throws EventDeliveryException {
        log.debug("Posting payload to {}: {}", getPostUrl(), event);

        if (httpClient == null) {
            start();
        }

        CloseableHttpResponse response = null;
        final HttpPost httpPost = new HttpPost(getPostUrl());

        httpPost.setHeader("Authorization", getAuthorizationHeaderValue());
        httpPost.setEntity(new StringEntity(event, ContentType.APPLICATION_JSON));
        try {
            response = httpClient.execute(httpPost);
            StatusLine statusLine = response.getStatusLine();

            if (statusLine.getStatusCode() != 200) {
                HttpEntity responseEntity = response.getEntity();

                String responseBody = (responseEntity == null ? "" : EntityUtils.toString(responseEntity));
                log.error("Post failed with response {} - {} for payload {}", responseBody, response, event);
                throw new EventDeliveryHttpException(event, response, responseBody);
            }
            lastEventTime = new Date();
            ++eventCount;
        } catch (IOException ioEx) {
            throw new EventDeliveryException(event, ioEx);
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException consumeEx) {
                    log.warn("Ignoring exception encountered consuming HTTP response entity", consumeEx);
                }
                try {
                    response.close();
                } catch (IOException closeEx) {
                    log.warn("Ignoring exception encountered closing HTTP response", closeEx);
                }
            }
        }
    }


    void registerMBean() {
        String newClientObjectNameString = String.format("com.pronoia.splunk.httpec:type=%s,id=%s",
            this.getClass().getSimpleName(), getClientId());

        try {
            clientObjectName = new ObjectName(newClientObjectNameString);
        } catch (MalformedObjectNameException malformedNameEx) {
            log.warn("Failed to create ObjectName for string {} - MBean will not be registered", newClientObjectNameString, malformedNameEx);
            return;
        }

        try {
            ManagementFactory.getPlatformMBeanServer().registerMBean(this, clientObjectName);
        } catch (InstanceAlreadyExistsException allreadyExistsEx) {
            log.warn("MBean already registered for name {}", clientObjectName, allreadyExistsEx);
        } catch (MBeanRegistrationException registrationEx) {
            log.warn("MBean registration failure for name {}", clientObjectName, registrationEx);
        } catch (NotCompliantMBeanException nonCompliantMBeanEx) {
            log.warn("Invalid MBean for name {}", clientObjectName, nonCompliantMBeanEx);
        }

    }

    void unregisterMBean() {
        if (clientObjectName != null) {
            try {
                ManagementFactory.getPlatformMBeanServer().unregisterMBean(clientObjectName);
            } catch (InstanceNotFoundException | MBeanRegistrationException unregisterEx) {
                log.warn("Failed to unregister consumer MBean {}", clientObjectName.getCanonicalName(), unregisterEx);
            } finally {
                clientObjectName = null;
            }
        }
    }

    /**
     * Simple implementation of a TrustStrategy that does not validate
     * certificates (it accepts all certificates as valid).
     *
     * 

This class is primarily for use in development environments, and will be * use when the disableCertificateValidation attribute is true. */ class AcceptAllTrustStrategy implements TrustStrategy { @Override public boolean isTrusted(final X509Certificate[] x509Certificates, final String s) throws CertificateException { return true; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy