newrelic-telemetry-sdk-java icon indicating copy to clipboard operation
newrelic-telemetry-sdk-java copied to clipboard

Add Batching Feature / Configuration to the New Relic Telemetry SDK

Open yamnihcg opened this issue 2 years ago • 0 comments

This PR adds a configuration to enable batching in the Telemetry SDK.

What is batching?

The Java Telemetry SDK sends Metric and Event data to New Relic by using the New Relic Ingest API. The Ingest API has limits on the amount of data that can be sent to New Relic in a single request. Specifically, the request payload has to be <= 1 MB. We implemented batching as a way to send reasonably large amounts of data (> 1 MB) without any user intervention. Batching takes request data and splits it into smaller payloads. Each of these payloads is <= 1 MB. So, each payload can then be sent to New Relic.

Enable batching in the Telemetry SDK

Batching can be turned on through constructors in the EventBuffer and the MetricBuffer. By default, batching is not enabled in the Telemetry SDK. Below are two snippets of code where batching is turned off / on. These snippets were taken from EventExample.java.

Batching: Off (by default)

EventBatchSenderFactory factory = EventBatchSenderFactory.fromHttpImplementation(OkHttpPoster::new);
EventBatchSender sender = EventBatchSender.create(factory.configureWith(licenseKey).useLicenseKey(true).build());
EventBuffer eventBuffer = new EventBuffer(getCommonAttributes());
.
.
sender.sendBatch(eventBuffer.createBatch());

Batching: On

EventBatchSenderFactory factory = EventBatchSenderFactory.fromHttpImplementation(OkHttpPoster::new);
EventBatchSender sender = EventBatchSender.create(factory.configureWith(licenseKey).useLicenseKey(true).build());
EventBuffer eventBuffer = new EventBuffer(getCommonAttributes(), true);
.
.
sender.sendBatch(eventBuffer.createBatch());

Where does the batching happen in the EventBuffer / MetricBuffer?

First, the createBatch() function is called on the buffer (refer to EventExample and CountExample). This function looks at the splitBatch variable to check if the user has turned batching on / off. If the user has turned batching off, a single batch is created by calling createSingleBatch(). An ArrayList (of size 1) contains this single batch. If the user has turned batching on, multiple batches are created by calling createBatches(). An interactive explanation of the batching algorithm is here.

The pseudocode for createBatches() is below.


Initialize currentUncompressedSizeCount = 0 // in bytes
Initialize maxUncompressedBatchSize = 18000000 // in bytes 

Initialize listOfBatches  
Initialize currentBatchEvents 

while (queueOfEvents is not empty):

    Pop event from queue 

    If currentUncompressedSizeCount > maxUncompressedBatchSize:

        listOfBatches.add(currentBatchEvents) 
        currentBatchEvents = [] // Reset Batch to Being Empty 
        currentUncompressedSizeCount = 0 // Reset UncompressedSize of Current Batch

    Else:

        Get Uncompressed Size of Event 
        Add it to currentUncompressedSizeCount 

Create Whatever is Remaining in currentBatchEvents, add it to listOfBatches 
Send listOfBatches

How is data sent to New Relic?

Data is sent to New Relic through the .sendBatch() method in the EventBatchSender / MetricBatchSender.

yamnihcg avatar Aug 06 '21 18:08 yamnihcg