Code review comment: yes, you'D of course have to rap the subList in a DSeries again, requiring a new constructor.

Code before review:
public void open(MetricConfig config) {
String apiKey = config.getString(API_KEY, null);
String proxyHost = config.getString(PROXY_HOST, null);
Integer proxyPort = config.getInteger(PROXY_PORT, 8080);
String rawDataCenter = config.getString(DATA_CENTER, "US");
maxMetricsPerRequestValue = config.getInteger(MAX_METRICS_PER_REQUEST, 2000);
DataCenter dataCenter = DataCenter.valueOf(rawDataCenter);
String tags = config.getString(TAGS, "");
client = new DatadogHttpClient(apiKey, proxyHost, proxyPort, dataCenter, true);
configTags = getTagsFromConfig(tags);
LOGGER.info("Configured DatadogHttpReporter with {tags={}, proxyHost={}, proxyPort={}, dataCenter={}, maxMetricsPerRequest={}", tags, proxyHost, proxyPort, dataCenter, maxMetricsPerRequestValue);
}
@Override
public void close() {
client.close();
LOGGER.info("Shut down DatadogHttpReporter");
}
@Override
public void report() {
try {
int totalGaugesSent = addGaugesAndUnregisterOnException();
DSeries request = new DSeries();
int currentCount = 0;
for (DCounter c : counters.values()) {
request.addCounter(c);
++currentCount;
if (currentCount % maxMetricsPerRequestValue == 0) {
client.send(request);
request = new DSeries();
}
}
for (DMeter m : meters.values()) {
request.addMeter(m);
++currentCount;
if (currentCount % maxMetricsPerRequestValue == 0) {
client.send(request);
request = new DSeries();
}
}
if (request.getSeries().size() > 0) {
client.send(request);
}
counters.values().forEach(DCounter::ackReport);
LOGGER.debug("Reported series with size {}.", totalGaugesSent + currentCount);
} catch (SocketTimeoutException e) {
LOGGER.warn("Failed reporting metrics to Datadog because of socket timeout: {}", e.getMessage());
} catch (Exception e) {
LOGGER.warn("Failed reporting metrics to Datadog.", e);
}
}
private int addGaugesAndUnregisterOnException() {
DSeries request = new DSeries();
int currentCount = 0;
int totalGauges = gauges.size();
List<Gauge> gaugesToRemove = new ArrayList<>();
for (Map.Entry<Gauge, DGauge> entry : gauges.entrySet()) {
DGauge g = entry.getValue();
try {
g.getMetricValue();
request.addGauge(g);
++currentCount;
if (currentCount % maxMetricsPerRequestValue == 0 || currentCount >= totalGauges) {
client.send(request);
request = new DSeries();
}
} catch (ClassCastException e) {
LOGGER.info("The metric {} will not be reported because only number types are supported by this reporter.", g.getMetric());
gaugesToRemove.add(entry.getKey());
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The metric {} will not be reported because it threw an exception.", g.getMetric(), e);
} else {
LOGGER.info("The metric {} will not be reported because it threw an exception.", g.getMetric());
}
gaugesToRemove.add(entry.getKey());
}
}
gaugesToRemove.forEach(gauges::remove);
return currentCount;
}
/**
* Get config tags from config 'metrics.reporter.dghttp.tags'.
*/
private List<String> getTagsFromConfig(String str) {
return Arrays.asList(str.split(","));
}
/**
* Get tags from MetricGroup
*/
private List<String> getTagsFromMetricGroup(MetricGroup metricGroup) {
List<String> tags = new ArrayList<>();
for (Map.Entry<String, String> entry: metricGroup.getAllVariables().entrySet()) {
if (!entry.getKey().equals(HOST_VARIABLE)) {
tags.add(getVariableName(entry.getKey()) + ":" + entry.getValue());
}
}
return tags;
}
private String getHostFromMetricGroup(MetricGroup metricGroup) {
return metricGroup.getAllVariables().get(HOST_VARIABLE);
}
/**
* Removes leading and trailing angle brackets.
*/
private String getVariableName(String str) {
return str.substring(1, str.length() - 1);
}
}

Line under review: client.send(request);

Code after addressing the review:
public void open(MetricConfig config) {
String apiKey = config.getString(API_KEY, null);
String proxyHost = config.getString(PROXY_HOST, null);
Integer proxyPort = config.getInteger(PROXY_PORT, 8080);
String rawDataCenter = config.getString(DATA_CENTER, "US");
maxMetricsPerRequestValue = config.getInteger(MAX_METRICS_PER_REQUEST, 2000);
DataCenter dataCenter = DataCenter.valueOf(rawDataCenter);
String tags = config.getString(TAGS, "");
client = new DatadogHttpClient(apiKey, proxyHost, proxyPort, dataCenter, true);
configTags = getTagsFromConfig(tags);
LOGGER.info("Configured DatadogHttpReporter with {tags={}, proxyHost={}, proxyPort={}, dataCenter={}, maxMetricsPerRequest={}", tags, proxyHost, proxyPort, dataCenter, maxMetricsPerRequestValue);
}
@Override
public void close() {
client.close();
LOGGER.info("Shut down DatadogHttpReporter");
}
@Override
public void report() {
DSeries request = new DSeries();
addGaugesAndUnregisterOnException(request);
counters.values().forEach(request::addCounter);
meters.values().forEach(request::addMeter);
int totalMetrics = request.getSeries().size();
int fromIndex = 0;
while (fromIndex < totalMetrics) {
int toIndex = Math.min(fromIndex + maxMetricsPerRequestValue, totalMetrics);
try {
DSeries chunk = new DSeries(request.getSeries().subList(fromIndex, toIndex));
client.send(chunk);
chunk.getSeries().forEach(DMetric::ackReport);
LOGGER.debug("Reported series with size {}.", chunk.getSeries().size());
} catch (SocketTimeoutException e) {
LOGGER.warn("Failed reporting metrics to Datadog because of socket timeout: {}", e.getMessage());
} catch (Exception e) {
LOGGER.warn("Failed reporting metrics to Datadog.", e);
}
fromIndex = toIndex;
}
}
private void addGaugesAndUnregisterOnException(DSeries request) {
List<Gauge> gaugesToRemove = new ArrayList<>();
for (Map.Entry<Gauge, DGauge> entry : gauges.entrySet()) {
DGauge g = entry.getValue();
try {
g.getMetricValue();
request.addGauge(g);
} catch (ClassCastException e) {
LOGGER.info("The metric {} will not be reported because only number types are supported by this reporter.", g.getMetric());
gaugesToRemove.add(entry.getKey());
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The metric {} will not be reported because it threw an exception.", g.getMetric(), e);
} else {
LOGGER.info("The metric {} will not be reported because it threw an exception.", g.getMetric());
}
gaugesToRemove.add(entry.getKey());
}
}
gaugesToRemove.forEach(gauges::remove);
}
/**
* Get config tags from config 'metrics.reporter.dghttp.tags'.
*/
private List<String> getTagsFromConfig(String str) {
return Arrays.asList(str.split(","));
}
/**
* Get tags from MetricGroup
*/
private List<String> getTagsFromMetricGroup(MetricGroup metricGroup) {
List<String> tags = new ArrayList<>();
for (Map.Entry<String, String> entry: metricGroup.getAllVariables().entrySet()) {
if (!entry.getKey().equals(HOST_VARIABLE)) {
tags.add(getVariableName(entry.getKey()) + ":" + entry.getValue());
}
}
return tags;
}
private String getHostFromMetricGroup(MetricGroup metricGroup) {
return metricGroup.getAllVariables().get(HOST_VARIABLE);
}
/**
* Removes leading and trailing angle brackets.
*/
private String getVariableName(String str) {
return str.substring(1, str.length() - 1);
}
}