
io.honeycomb.libhoney.builders.HoneyClientBuilder Maven / Gradle / Ivy
Show all versions of libhoney-java Show documentation
package io.honeycomb.libhoney.builders;
import io.honeycomb.libhoney.DefaultDebugResponseObserver;
import io.honeycomb.libhoney.Event;
import io.honeycomb.libhoney.EventFactory;
import io.honeycomb.libhoney.EventPostProcessor;
import io.honeycomb.libhoney.HoneyClient;
import io.honeycomb.libhoney.LibHoney;
import io.honeycomb.libhoney.Options;
import io.honeycomb.libhoney.ResponseObserver;
import io.honeycomb.libhoney.TransportOptions;
import io.honeycomb.libhoney.ValueSupplier;
import io.honeycomb.libhoney.transport.Transport;
import io.honeycomb.libhoney.transport.batch.impl.HoneycombBatchConsumer;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import javax.net.ssl.SSLContext;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HoneyClientBuilder {
private final Map globalFields = new HashMap<>();
private final Map> globalDynamicFields = new HashMap<>();
private final Map credentialMap = new HashMap<>();
private final List responseObservers = new ArrayList<>();
protected TransportOptions.Builder transportOptionsBuilder = new TransportOptions.Builder();
protected Options.Builder optionsBuilder = new Options.Builder();
private Transport transport = null;
private boolean debugEnabled = false;
/**
* Build new HoneyClient instance as configured by calling the various builder methods previous to this call.
* Example
* {@code
* HoneyClient client = new HoneyClientBuilder()
* .dataSet("dataset")
* .writeKey("write key")
* .addProxy("proxy.domain.com")
* .build()}
*
* @return new HoneyClient instance
*/
public HoneyClient build() {
configureOptionBuilder();
configureTransportOptionBuilder();
final HoneyClient client = createClient();
configureClient(client);
return client;
}
private HoneyClient createClient() {
if(transport==null){
return new HoneyClient(optionsBuilder.build(), transportOptionsBuilder.build());
}
return new HoneyClient(optionsBuilder.build(), transport);
}
private void configureClient(final HoneyClient client) {
if (!responseObservers.isEmpty()) {
for (final ResponseObserver responseObserver : responseObservers) {
client.addResponseObserver(responseObserver);
}
}
if (debugEnabled) {
client.addResponseObserver(new DefaultDebugResponseObserver());
}
}
private void configureTransportOptionBuilder() {
if (!credentialMap.isEmpty()) {
transportOptionsBuilder.setCredentialsProvider(createCredentialsProvider());
}
}
private CredentialsProvider createCredentialsProvider() {
final CredentialsProvider provider = new BasicCredentialsProvider();
for (final Map.Entry entry : credentialMap.entrySet()) {
final String proxy = entry.getKey();
final Credentials credential = entry.getValue();
final HttpHost proxyHost = HttpHost.create(proxy);
final AuthScope authScope = new AuthScope(proxyHost);
provider.setCredentials(authScope, credential);
}
return provider;
}
private void configureOptionBuilder() {
if (!globalFields.isEmpty()) {
optionsBuilder.setGlobalFields(globalFields);
}
if (!globalDynamicFields.isEmpty()) {
optionsBuilder.setGlobalDynamicFields(globalDynamicFields);
}
}
/**
* Use this to add fields to all events, where both keys and values are fixed.
* Entries may be overridden before the event is sent to the server. See "Usage" on {@link HoneyClient}'s
* class documentation.
*
* Default: None
*
* @param name the "key".
* @param field the "value"
* @return HoneyClientBuilder instance
* @see Options.Builder#setGlobalFields(java.util.Map)
*/
public HoneyClientBuilder addGlobalField(final String name, final Object field) {
this.globalFields.put(name, field);
return this;
}
/**
* Use this method to supply fields to events, where keys are fixed but values are dynamically created at runtime.
* Entries may be overridden before the event is sent to the server. See "Usage" on {@link HoneyClient}'s
* class documentation.
*
* Default: None
*
* @param name the "key"
* @param valueSupplier calculates value
* @return HoneyClientBuilder instance
* @see Options.Builder#setGlobalDynamicFields(java.util.Map)
*/
public HoneyClientBuilder addGlobalDynamicFields(final String name, final ValueSupplier> valueSupplier) {
this.globalDynamicFields.put(name, valueSupplier);
return this;
}
/**
* Use this method to configure the HTTP client to use a proxy that needs authentication.
*
* For configuring a proxy server without authentication see: {@link #addProxy(String)}
*
* @param proxyHost hostname of the proxy, frequently FQDN of the server
* @param username username for authentication with proxy server
* @param password password for authentication with proxy server
* @return HoneyClientBuilder instance
*/
public HoneyClientBuilder addProxy(final String proxyHost, final String username, final String password) {
final UsernamePasswordCredentials credential = new UsernamePasswordCredentials(username, password);
credentialMap.put(proxyHost, credential);
return this;
}
/**
* SampleRate is the rate at which to sample this event. Default is 1, meaning no sampling.
* The probability of sending is {@code 1/sampleRate}. In other words, if one out of every 250 events is to be
* sent when Send() is called, you would specify set sample rate to 250.
*
* Must be greater than 1
* Default: 1
*
* @param sampleRate average number of events until sample is taken.
* @return HoneyClientBuilder instance
*/
public HoneyClientBuilder sampleRate(final int sampleRate) {
optionsBuilder.setSampleRate(sampleRate);
return this;
}
/**
* Set this to apply post processing to any event about to be submitted to Honeycomb.
* See {@link EventPostProcessor} for details.
*
* Default: None
*
* @param eventPostProcessor to set.
* @return this.
*/
public HoneyClientBuilder eventPostProcessor(final EventPostProcessor eventPostProcessor) {
optionsBuilder.setEventPostProcessor(eventPostProcessor);
return this;
}
/**
* This determines that maximum number of events that get sent to the Honeycomb server (via a batch request).
* In other words, this is a trigger that will cause a batch request to be created if a batch reaches this
* maximum size.
*
* Also see {@link io.honeycomb.libhoney.TransportOptions.Builder#setBatchTimeoutMillis}, as that might cause batch request to be created
* earlier (triggering on time rather than space).
*
* Note: Events are grouped into batches that have the same write key, dataset name and API host.
* See {@link Event#setWriteKey(String)}, {@link Event#setDataset(String)}, and {@link Event#setApiHost(URI)}.
*
* @param batchSize max number of events to send in single data transmission
* @return HoneyClientBuilder instance
*/
public HoneyClientBuilder batchSize(final int batchSize) {
transportOptionsBuilder.setBatchSize(batchSize);
return this;
}
/**
* If batches do no fill up to the batch size in time (as defined by {@link TransportOptions.Builder#setBatchSize(int)}), then
* this timeout will trigger a batch request to the Honeycomb server. Essentially, for batches that fill
* slowly, this ensures that there is a temporal upper bound to when events are sent via a batch request.
* The time is measured in milliseconds.
*
* Note: Events are grouped into batches that have the same write key, dataset name and API host.
* See {@link Event#setWriteKey(String)}, {@link Event#setDataset(String)}, and {@link Event#setApiHost(URI)}.
*
* Default: 100
*
* @param batchTimeoutMillis max milliseconds to send a non-empty but not-full batch.
* @return HoneyClientBuilder instance
*/
public HoneyClientBuilder batchTimeoutMillis(final long batchTimeoutMillis) {
transportOptionsBuilder.setBatchTimeoutMillis(batchTimeoutMillis);
return this;
}
/**
* This sets the capacity of the queue that events are submitted to before they get processed for batching
* and eventually sent to the honeycomb HTTP endpoint.
*
* Under normal circumstances this queue should remain near empty, but in case of heavy load it acts as a
* bounded buffer against a build up of backpressure from the batching and http client implementation.
*
* Default: 10000
*
* @param queueCapacity queue size.
* @return HoneyClientBuilder instance
* @see io.honeycomb.libhoney.responses.ClientRejected.RejectionReason#QUEUE_OVERFLOW
* @see io.honeycomb.libhoney.transport.batch.BatchConsumer#consume(java.util.List)
*/
public HoneyClientBuilder queueCapacity(final int queueCapacity) {
transportOptionsBuilder.setQueueCapacity(queueCapacity);
return this;
}
/**
* This determines the maximum number of batch requests that can be still pending completion at any one time.
* Set to -1 if there is no maximum, i.e. the number of batch requests pending completion is allowed to grow
* without bound.
*
* Once a batch request has been triggered (see {@link TransportOptions.Builder#setBatchSize(int)} and
* {@link TransportOptions.Builder#setBatchTimeoutMillis(long)}), then the batch request is submitted
* to {@link io.honeycomb.libhoney.transport.batch.BatchConsumer#consume(java.util.List)}.
*
* If the maximum pending requests is reached, then
* {@link io.honeycomb.libhoney.transport.batch.BatchConsumer#consume(java.util.List)} may block until the number of
* pending requests has dropped below the threshold.
*
* This allows backpressure to be created if the {@link io.honeycomb.libhoney.transport.batch.BatchConsumer}
* implementation cannot keep up with the number of batch requests being submitted. The intended consequence of
* this is that the event queue may reach its capacity and overflow.
*
* See {@link TransportOptions.Builder#setQueueCapacity(int)}.
*
* This configuration differs from {@link TransportOptions.Builder#getMaxConnections()} in that a batch request may be pending
* completion, but it may be still be waiting for an HTTP connection. This is the case in the default
* {@link HoneycombBatchConsumer} where the
* {@link org.apache.http.nio.client.HttpAsyncClient} maintains an internal unbounded pending queue for
* requests that are waiting for a connection. This configuration effectively puts a bound on the total
* number of batch requests being serviced by the HTTP client, regardless of whether they have
* a connection or not.
*
* Default: 250
*
* @param maxPendingBatchRequests max simultaneous requests.
* @return HoneyClientBuilder instance
* @see TransportOptions.Builder#setMaxConnections(int)
*/
public HoneyClientBuilder maxPendingBatchRequests(final int maxPendingBatchRequests) {
transportOptionsBuilder.setMaximumPendingBatchRequests(maxPendingBatchRequests);
return this;
}
/**
* Set this to define the maximum amount of connections the http client may hold in its connection pool.
* In effect this is the maximum level of concurrent HTTP requests that may be in progress at any given time.
*
* Default: 200
*
* @param maxConnections maximum number of connections.
* @return HoneyClientBuilder instance
* @see HttpAsyncClientBuilder#setMaxConnTotal(int)
*/
public HoneyClientBuilder maxConnections(final int maxConnections) {
transportOptionsBuilder.setMaxConnections(maxConnections);
return this;
}
/**
* Set this to define the maximum amount of connections the http client may hold in its connection pool for a
* given hostname.
* In effect this limits how many concurrent requests may be sent to a single host.
*
* Default: 100
*
* @param maxConnectionsPerApiHost pool size for per hostname
* @return HoneyClientBuilder instance
* @see HttpAsyncClientBuilder#setMaxConnPerRoute(int)
*/
public HoneyClientBuilder maxConnectionsPerApiHost(final int maxConnectionsPerApiHost) {
transportOptionsBuilder.setMaxConnectionsPerApiHost(maxConnectionsPerApiHost);
return this;
}
/**
* Set this to define the http client's connect timeout in milliseconds. Set to 0 for no timeout.
*
* Default: 0
*
* @param connectTimeout to set.
* @return HoneyClientBuilder instance
* @see RequestConfig#getConnectTimeout()
*/
public HoneyClientBuilder connectionTimeout(final int connectTimeout) {
transportOptionsBuilder.setConnectTimeout(connectTimeout);
return this;
}
/**
* Set this to define the http client's connection request timeout in milliseconds. This defines the maximum
* time that a batch request can wait for a connection from the connection manager after
* submission to the HTTP client. Set to 0 for no timeout.
*
* Beware that setting this to a non-zero value might conflict with the backpressure effect of the
* {@link io.honeycomb.libhoney.transport.batch.BatchConsumer} implementation, and so might see an increase
* in failed batches. See {@link #maxPendingBatchRequests(int)} for more detail.
*
* Default: 0
*
* @param connectionRequestTimeout to set.
* @return HoneyClientBuilder instance
* @see RequestConfig#getConnectionRequestTimeout()
*/
public HoneyClientBuilder connectionRequestTimeout(final int connectionRequestTimeout) {
transportOptionsBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
return this;
}
/**
* Set this to define the http client's socket timeout in milliseconds. Set to 0 for no timeout.
*
* Default: 3000
*
* @param socketTimeout to set.
* @return HoneyClientBuilder instance
* @see RequestConfig#getSocketTimeout()
*/
public HoneyClientBuilder socketTimeout(final int socketTimeout) {
transportOptionsBuilder.setSocketTimeout(socketTimeout);
return this;
}
/**
* Set this to define the http client's socket buffer size in bytes.
*
* Default: 8192
*
* @param bufferSize to set.
* @return HoneyClientBuilder instance
* @see org.apache.http.config.ConnectionConfig.Builder#setBufferSize(int)
*/
public HoneyClientBuilder bufferSize(final int bufferSize) {
transportOptionsBuilder.setBufferSize(bufferSize);
return this;
}
/**
* Set this to define the http client's io thread count. This is usually set to the number of CPU cores.
*
* Default: System CPU cores.
*
* @param ioThreadCount to set, must be between 1 and the system's number of CPU cores.
* @return HoneyClientBuilder instance
* @see Apache http client NIO
* @see IOReactorConfig#getIoThreadCount()
*/
public HoneyClientBuilder ioThreadCount(final int ioThreadCount) {
transportOptionsBuilder.setIoThreadCount(ioThreadCount);
return this;
}
/**
* Defines the maximum time (in milliseconds) that we should wait for any pending HTTP requests to complete
* during the client shutdown process.
*
* Any requests that are still pending at the end of this wait period will be terminated.
*
* Default: 2000
*
* @param maximumHttpRequestShutdownWait milliseconds.
* @return HoneyClientBuilder instance
* @see TransportOptions.Builder#setMaximumHttpRequestShutdownWait(long)
*/
public HoneyClientBuilder maximumHttpRequestShutdownWait(final long maximumHttpRequestShutdownWait) {
transportOptionsBuilder.setMaximumHttpRequestShutdownWait(maximumHttpRequestShutdownWait);
return this;
}
/**
* Set this to add an additional component to the user agent header sent to Honeycomb when Events are submitted.
* This is usually only of interest for instrumentation libraries that wrap LibHoney.
*
* Default: None
*
* @param additionalUserAgent added to the user agent on http request header.
* @return HoneyClientBuilder instance
* @see TransportOptions.Builder#setAdditionalUserAgent(java.lang.String)
*/
public HoneyClientBuilder additionalUserAgent(final String additionalUserAgent) {
transportOptionsBuilder.setAdditionalUserAgent(additionalUserAgent);
return this;
}
/**
* Use this method to configure the HTTP client to use a proxy without authentication.
*
* For configuring a proxy server with authentication see: {@link #addProxy(String, String, String)}
*
* @param host hostname of the proxy, frequently FQDN of the server
* @return HoneyClientBuilder instance
*/
public HoneyClientBuilder addProxy(final String host) {
transportOptionsBuilder.setProxy(new HttpHost(host));
return this;
}
public HoneyClientBuilder sslContext(final SSLContext sslContext) {
transportOptionsBuilder.setSSLContext(sslContext);
return this;
}
/**
* Dataset is the name of the Honeycomb dataset to which to send these events.
* If it is specified during {@link LibHoney} initialization, it will be used as the default dataset for all
* events. If absent, dataset must be explicitly set on an {@link EventFactory} or {@link Event}.
*
* @param dataSet to set.
* @return HoneyClientBuilder instance
* @see Options.Builder#setDataset(java.lang.String)
*
* Default: None
*/
public HoneyClientBuilder dataSet(final String dataSet) {
optionsBuilder.setDataset(dataSet);
return this;
}
/**
* APIHost is the hostname for the Honeycomb API server to which to send this event.
*
* Default: {@code https://api.honeycomb.io/}
*
* @param apiHost to set.
* @return HoneyClientBuilder instance
* @throws URISyntaxException if host is not valid URI syntax
* @see Options.Builder#setApiHost(java.net.URI)
*/
public HoneyClientBuilder apiHost(final String apiHost) throws URISyntaxException {
apiHost(new URI(apiHost));
return this;
}
/**
* APIHost is the hostname for the Honeycomb API server to which to send this event.
*
* Default: {@code https://api.honeycomb.io/}
*
* @param apiHost to set.
* @return HoneyClientBuilder instance
* @throws URISyntaxException if host is not valid URI syntax
* @see Options.Builder#setApiHost(java.net.URI)
*/
public HoneyClientBuilder apiHost(final URI apiHost) throws URISyntaxException {
optionsBuilder.setApiHost(apiHost);
return this;
}
/**
* WriteKey is the Honeycomb authentication token.
* If it is specified during {@link LibHoney} initialization, it will be used as the default write key for all
* events.
* If absent, write key must be explicitly set on a builder or event.
* Find your team write key at https://ui.honeycomb.io/account
*
* Default: None
*
* @param writeKey to set.
* @return HoneyClientBuilder instance
* @see Options.Builder#setWriteKey(java.lang.String)
*/
public HoneyClientBuilder writeKey(final String writeKey) {
optionsBuilder.setWriteKey(writeKey);
return this;
}
/**
* Setting Debug to true will ensure the DefaultDebugResponseObserver to the HoneyClient's list of response observers.
* Default: false
*
* @param enabled true to enable debug response observer
* @return HoneyClientBuilder instance
*/
public HoneyClientBuilder debug(final boolean enabled) {
this.debugEnabled = enabled;
return this;
}
public HoneyClientBuilder addResponseObserver(final ResponseObserver responseObserver) {
responseObservers.add(responseObserver);
return this;
}
/**
* Transport for sending events to HoneyComb. Used by the {@link io.honeycomb.libhoney.HoneyClient} internals.
* This can also be used to disable sending events to Honeycomb by passing in a mock Transport.
*/
public HoneyClientBuilder transport(final Transport transport){
this.transport = transport;
return this;
}
}