<commit_before>/*
 * Copyright 2013-2015, Teradata, Inc. All rights reserved.
 */
package com.teradata.benchmark.driver.graphite;

import com.facebook.presto.jdbc.internal.guava.base.Joiner;
import com.facebook.presto.jdbc.internal.guava.collect.ImmutableMap;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.teradata.benchmark.driver.BenchmarkExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.math.BigDecimal;
import java.net.URI;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Map;

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.teradata.benchmark.driver.graphite.GraphiteClient.GraphiteRenderResponseItem.DATA_POINT_VALUE_INDEX;
import static com.teradata.benchmark.driver.utils.TimeUtils.nowUtc;
import static java.lang.String.format;
import static java.util.stream.Collectors.toMap;
import static org.springframework.http.HttpStatus.OK;

@Component
@ConditionalOnProperty(prefix = "graphite", value = "url")
public class GraphiteClient
{

    private static final Logger LOGGER = LoggerFactory.getLogger(GraphiteClient.class);

    @Value("${graphite.url}")
    private String graphiteURL;

    @Autowired
    private RestTemplate restTemplate;

    public void storeEvent(GraphiteEventRequest request)
    {
        LOGGER.debug("Storing graphite event: {}", request);

        restTemplate.postForObject("{graphiteURL}/events/", request, Object.class, ImmutableMap.of("graphiteURL", graphiteURL));
    }

    public Map<String, double[]> loadMetrics(Map<String, String> metrics, ZonedDateTime from, ZonedDateTime to)
    {
        URI uri = buildLoadMetricsURI(metrics, from, to);

        LOGGER.debug("Loading metrics: {}", uri);

        ResponseEntity<GraphiteRenderResponseItem[]> response = restTemplate.getForEntity(uri, GraphiteRenderResponseItem[].class);

        if (response.getStatusCode() != OK) {
            throw new BenchmarkExecutionException("Could not load metrics: " + metrics + " - error: " + response);
        }

        return Arrays.stream(response.getBody()).collect(toMap(
                GraphiteRenderResponseItem::getTarget,
                responseItem -> parseDataPoints(responseItem.datapoints)
        ));
    }

    private URI buildLoadMetricsURI(Map<String, String> metrics, ZonedDateTime from, ZonedDateTime to)
    {
        UriComponentsBuilder uriBuilder = UriComponentsBuilder
                .fromUriString(graphiteURL)
                .path("/render")
                .queryParam("format", "json")
                .queryParam("from", from.toEpochSecond())
                .queryParam("until", to.toEpochSecond());

        for (Map.Entry<String, String> metric : metrics.entrySet()) {
            String metricQueryExpr = metric.getValue();
            String metricName = metric.getKey();

            uriBuilder.queryParam("target", format("alias(%s,'%s')", metricQueryExpr, metricName));
        }

        return URI.create(uriBuilder.toUriString());
    }

    private double[] parseDataPoints(Double[][] inputDataPoints)
    {
        double[] dataPoints = new double[inputDataPoints.length];
        for (int i = 0; i < inputDataPoints.length; i++) {
            Double value = inputDataPoints[i][DATA_POINT_VALUE_INDEX];
            // rarely graphite does not return value for given timestamp, use 0 in this case
            dataPoints[i] = value == null ? 0 : value;
        }
        return dataPoints;
    }

    @SuppressWarnings("unused")
    @JsonAutoDetect(fieldVisibility = ANY)
    public static class GraphiteEventRequest
    {
        private String what;
        private String tags;
        private String data = "";
        private BigDecimal when;

        private GraphiteEventRequest()
        {
        }

        public static class GraphiteEventRequestBuilder
        {
            private GraphiteEventRequest request = new GraphiteEventRequest();

            public GraphiteEventRequestBuilder()
            {
                when(nowUtc());
            }

            public GraphiteEventRequestBuilder what(String what)
            {
                request.what = what;
                return this;
            }

            public GraphiteEventRequestBuilder tags(String... tags)
            {
                request.tags = Joiner.on(" ").join(tags);
                return this;
            }

            public GraphiteEventRequestBuilder data(String data)
            {
                request.data = data;
                return this;
            }

            public GraphiteEventRequestBuilder when(ZonedDateTime zonedDateTime)
            {
                request.when = new BigDecimal(format("%ld.%d", zonedDateTime.toEpochSecond(), zonedDateTime.getNano() / 1000));
                return this;
            }

            public GraphiteEventRequest build()
            {
                return request;
            }
        }

        @Override
        public String toString()
        {
            return toStringHelper(this)
                    .add("what", what)
                    .add("tags", tags)
                    .add("data", data)
                    .add("when", when)<commit_msg>[driver] hot fix, fix decimal format during building graphite request<commit_after>/*
 * Copyright 2013-2015, Teradata, Inc. All rights reserved.
 */
package com.teradata.benchmark.driver.graphite;

import com.facebook.presto.jdbc.internal.guava.base.Joiner;
import com.facebook.presto.jdbc.internal.guava.collect.ImmutableMap;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.teradata.benchmark.driver.BenchmarkExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.math.BigDecimal;
import java.net.URI;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Map;

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.teradata.benchmark.driver.graphite.GraphiteClient.GraphiteRenderResponseItem.DATA_POINT_VALUE_INDEX;
import static com.teradata.benchmark.driver.utils.TimeUtils.nowUtc;
import static java.lang.String.format;
import static java.util.stream.Collectors.toMap;
import static org.springframework.http.HttpStatus.OK;

@Component
@ConditionalOnProperty(prefix = "graphite", value = "url")
public class GraphiteClient
{

    private static final Logger LOGGER = LoggerFactory.getLogger(GraphiteClient.class);

    @Value("${graphite.url}")
    private String graphiteURL;

    @Autowired
    private RestTemplate restTemplate;

    public void storeEvent(GraphiteEventRequest request)
    {
        LOGGER.debug("Storing graphite event: {}", request);

        restTemplate.postForObject("{graphiteURL}/events/", request, Object.class, ImmutableMap.of("graphiteURL", graphiteURL));
    }

    public Map<String, double[]> loadMetrics(Map<String, String> metrics, ZonedDateTime from, ZonedDateTime to)
    {
        URI uri = buildLoadMetricsURI(metrics, from, to);

        LOGGER.debug("Loading metrics: {}", uri);

        ResponseEntity<GraphiteRenderResponseItem[]> response = restTemplate.getForEntity(uri, GraphiteRenderResponseItem[].class);

        if (response.getStatusCode() != OK) {
            throw new BenchmarkExecutionException("Could not load metrics: " + metrics + " - error: " + response);
        }

        return Arrays.stream(response.getBody()).collect(toMap(
                GraphiteRenderResponseItem::getTarget,
                responseItem -> parseDataPoints(responseItem.datapoints)
        ));
    }

    private URI buildLoadMetricsURI(Map<String, String> metrics, ZonedDateTime from, ZonedDateTime to)
    {
        UriComponentsBuilder uriBuilder = UriComponentsBuilder
                .fromUriString(graphiteURL)
                .path("/render")
                .queryParam("format", "json")
                .queryParam("from", from.toEpochSecond())
                .queryParam("until", to.toEpochSecond());

        for (Map.Entry<String, String> metric : metrics.entrySet()) {
            String metricQueryExpr = metric.getValue();
            String metricName = metric.getKey();

            uriBuilder.queryParam("target", format("alias(%s,'%s')", metricQueryExpr, metricName));
        }

        return URI.create(uriBuilder.toUriString());
    }

    private double[] parseDataPoints(Double[][] inputDataPoints)
    {
        double[] dataPoints = new double[inputDataPoints.length];
        for (int i = 0; i < inputDataPoints.length; i++) {
            Double value = inputDataPoints[i][DATA_POINT_VALUE_INDEX];
            // rarely graphite does not return value for given timestamp, use 0 in this case
            dataPoints[i] = value == null ? 0 : value;
        }
        return dataPoints;
    }

    @SuppressWarnings("unused")
    @JsonAutoDetect(fieldVisibility = ANY)
    public static class GraphiteEventRequest
    {
        private String what;
        private String tags;
        private String data = "";
        private BigDecimal when;

        private GraphiteEventRequest()
        {
        }

        public static class GraphiteEventRequestBuilder
        {
            private GraphiteEventRequest request = new GraphiteEventRequest();

            public GraphiteEventRequestBuilder()
            {
                when(nowUtc());
            }

            public GraphiteEventRequestBuilder what(String what)
            {
                request.what = what;
                return this;
            }

            public GraphiteEventRequestBuilder tags(String... tags)
            {
                request.tags = Joiner.on(" ").join(tags);
                return this;
            }

            public GraphiteEventRequestBuilder data(String data)
            {
                request.data = data;
                return this;
            }

            public GraphiteEventRequestBuilder when(ZonedDateTime zonedDateTime)
            {
                request.when = new BigDecimal(format("%d.%d", zonedDateTime.toEpochSecond(), zonedDateTime.getNano() / 1000));
                return this;
            }

            public GraphiteEventRequest build()
            {
                return request;
            }
        }

        @Override
        public String toString()
        {
            return toStringHelper(this)
                    .add("what", what)
                    .add("tags", tags)
                    .add("data", data)
                    .add("when", when)
{'fraction_non_alphanumeric': 0.09877081335541801, 'fraction_numerical': 0.002963996164240258, 'mean_word_length': 2.6326789107029764, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6004317', 'n_tokens_mistral': 3044, 'n_tokens_neox': 2922, 'n_words': 620}