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

com.vlkan.hrrs.replayer.http.ApacheHttpRequestRecordReplayer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2022 Volkan Yazıcı
 *
 * Licensed 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 permits and
 * limitations under the License.
 */

package com.vlkan.hrrs.replayer.http;

import com.codahale.metrics.MetricRegistry;
import com.vlkan.hrrs.api.HttpRequestHeader;
import com.vlkan.hrrs.api.HttpRequestPayload;
import com.vlkan.hrrs.api.HttpRequestRecord;
import com.vlkan.hrrs.replayer.cli.Config;
import com.vlkan.hrrs.replayer.jtl.JtlPrinter;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Preconditions.checkNotNull;

@Singleton
public class ApacheHttpRequestRecordReplayer implements HttpRequestRecordReplayer {

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

    private final MetricRegistry metricRegistry;

    private final JtlPrinter jtlPrinter;

    private final HttpHost httpHost;

    private final CloseableHttpClient httpClient;

    @Inject
    public ApacheHttpRequestRecordReplayer(
            Config config,
            ApacheHttpClientFactory httpClientFactory,
            MetricRegistry metricRegistry,
            JtlPrinter jtlPrinter) {

        // Check arguments.
        checkNotNull(config, "config");
        checkNotNull(httpClientFactory, "httpClientFactory");
        checkNotNull(metricRegistry, "metricRegistry");
        checkNotNull(jtlPrinter, "jtlPrinter");

        // Set class fields.
        this.metricRegistry = metricRegistry;
        this.jtlPrinter = jtlPrinter;
        this.httpHost = new HttpHost(config.getTargetHost(), config.getTargetPort());
        this.httpClient = httpClientFactory.create();
        LOGGER.debug("instantiated");

    }

    @Override
    public void replay(HttpRequestRecord record) {
        LOGGER.trace("replaying record (id={})", record.getId());
        long startTimeMillis = System.currentTimeMillis();
        try {
            int statusCode = execute(record);
            long stopTimeMillis = System.currentTimeMillis();
            long durationMillis = stopTimeMillis - startTimeMillis;
            report(record, statusCode, durationMillis);
        } catch (Throwable error) {
            String message = String.format("failed replaying record (id=%s)", record.getId());
            LOGGER.error(message, error);
        }
    }

    private int execute(HttpRequestRecord record) throws IOException {
        HttpUriRequest httpUriRequest = createHttpUriRequest(record);
        try (CloseableHttpResponse httpResponse = httpClient.execute(httpHost, httpUriRequest)) {
            HttpEntity entity = httpResponse.getEntity();
            if (entity != null) {
                entity.getContent().close();
            }
            return httpResponse.getStatusLine().getStatusCode();
        } catch (SocketTimeoutException error) {
            return HttpStatus.SC_GATEWAY_TIMEOUT;
        }
    }

    private void report(HttpRequestRecord record, int statusCode, long durationMillis) {
        String threadName = Thread.currentThread().getName();
        long timestampMillis = record.getTimestamp().getTime();
        jtlPrinter.print(timestampMillis, record.getGroupName(), statusCode, durationMillis, threadName);
        metricRegistry.timer("__all__").update(durationMillis, TimeUnit.MILLISECONDS);
        metricRegistry.timer("__all__." + statusCode).update(durationMillis, TimeUnit.MILLISECONDS);
        metricRegistry.timer(record.getGroupName()).update(durationMillis, TimeUnit.MILLISECONDS);
        metricRegistry.timer(record.getGroupName() + "." + statusCode).update(durationMillis, TimeUnit.MILLISECONDS);
        LOGGER.trace(
                "replayed record (id={}, method={}, groupName={}, statusCode={}, durationMillis={})",
                record.getId(),
                record.getMethod(),
                record.getGroupName(),
                statusCode,
                durationMillis);
    }

    private HttpUriRequest createHttpUriRequest(HttpRequestRecord record) {
        HttpUriRequest request;
        switch (record.getMethod()) {

            case DELETE:
                request = new HttpDelete(record.getUri());
                break;

            case GET:
                request = new HttpGet(record.getUri());
                break;

            case HEAD:
                request = new HttpHead(record.getUri());
                break;

            case OPTIONS:
                request = new HttpOptions(record.getUri());
                break;

            case PATCH:
                HttpPatch httpPatch = new HttpPatch(record.getUri());
                addHttpRequestPayload(record, httpPatch);
                request = httpPatch;
                break;

            case POST:
                HttpPost httpPost = new HttpPost(record.getUri());
                addHttpRequestPayload(record, httpPost);
                request = httpPost;
                break;

            case PUT:
                HttpPut httpPut = new HttpPut(record.getUri());
                addHttpRequestPayload(record, httpPut);
                request = httpPut;
                break;

            case TRACE:
                request = new HttpTrace(record.getUri());
                break;

            default:
                throw new UnsupportedOperationException("unknown method: " + record.getMethod());

        }
        addHttpUriRequestHeaders(request, record);
        return request;
    }

    private static void addHttpRequestPayload(HttpRequestRecord record, HttpEntityEnclosingRequest request) {
        HttpRequestPayload payload = record.getPayload();
        byte[] payloadBytes = payload.getBytes();
        if (payloadBytes.length > 0) {
            ByteArrayEntity payloadEntity = new ByteArrayEntity(payloadBytes);
            request.setEntity(payloadEntity);
        }
    }

    private void addHttpUriRequestHeaders(HttpUriRequest request, HttpRequestRecord record) {
        for (HttpRequestHeader header : record.getHeaders()) {
            request.setHeader(header.getName(), header.getValue());
        }
    }

    @Override
    public void close() throws IOException {
        LOGGER.debug("closing");
        httpClient.close();
        jtlPrinter.close();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy