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

com.dnastack.audit.client.EventsClient Maven / Gradle / Ivy

The newest version!
package com.dnastack.audit.client;

import com.dnastack.audit.ObjectMapperFactory;
import com.dnastack.audit.exception.HttpRequestFailedException;
import com.dnastack.audit.model.AuditEventBody;
import com.dnastack.audit.model.AuditEventBodyBatch;
import com.dnastack.audit.model.AuditEventLoggerConfig;
import com.dnastack.audit.util.AuditTracer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import interceptor.AuthorizationInterceptor;
import interceptor.TokenDelegate;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.BufferedSink;

import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.Objects;

import static java.lang.String.format;

@Slf4j
public class EventsClient {

    private final AuditEventLoggerConfig.Publisher publisherConfig;
    private final ObjectMapper objectMapper;
    private final AuditTracer auditTracer;
    private final OkHttpClient eventsHttpClient;


    public EventsClient(
        AuditEventLoggerConfig.Publisher publisherConfig,
        TokenDelegate tokenDelegate,
        AuditTracer auditTracer
    ) {
        Objects.requireNonNull(publisherConfig, "publisherConfig must not be null");
        Objects.requireNonNull(tokenDelegate, "accessTokenSupplier must not be null");
        Objects.requireNonNull(auditTracer, "auditTracer must not be null");
        this.publisherConfig = publisherConfig;
        this.objectMapper = ObjectMapperFactory.create();
        this.auditTracer = auditTracer;

        eventsHttpClient = new OkHttpClient.Builder()
            .addInterceptor(
                new HttpLoggingInterceptor(log::info)
                    .setLevel(HttpLoggingInterceptor.Level.BASIC)
            )
            .addInterceptor(new AuthorizationInterceptor(tokenDelegate))
            .addInterceptor(new RetryInterceptor(publisherConfig.getGiveUpAfter(), publisherConfig.getDelayBetweenTriesInMillis()))
            .build();

    }

    public void publishBatch(AuditEventBodyBatch auditEventBodyBatch) {
        try {
            RequestBody requestBody = new RequestBody() {
                @Override public MediaType contentType() {
                    return MediaType.get("application/json");
                }
                @Override public void writeTo(BufferedSink sink) throws IOException {
                    OutputStream os = sink.outputStream();
                    objectMapper.writeValue(os, auditEventBodyBatch);
                }

            };
            final Request request = new Request.Builder()
                .url(publisherConfig.getEventsBatchUri())
                .header("Content-Type", "application/json")
                .header("X-B3-TraceId", auditTracer.currentTraceId())
                .header("X-B3-SpanId", auditTracer.currentSpanId())
                .method("POST", requestBody)
                .build();
            log.info("Preparing batch request [{}] [{}] - number of events in batch: [{}], content length: [{}] Bytes",
                request.method(),
                request.url(),
                auditEventBodyBatch.getEvents().size(),
                request.body() != null ? request.body().contentLength() : "unknown");
            send(request);
        } catch (JsonProcessingException | MalformedURLException ex) {
            throw new HttpRequestFailedException(format("Failed to process %s", auditEventBodyBatch), ex);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    public void publish(AuditEventBody auditEvent) {
        try {
            RequestBody requestBody = new RequestBody() {
                @Override public MediaType contentType() {
                    return MediaType.get("application/json");
                }
                @Override public void writeTo(BufferedSink sink) throws IOException {
                    OutputStream os = sink.outputStream();
                    objectMapper.writeValue(os, auditEvent);
                }

            };
            final Request request = new Request.Builder()
                .url(publisherConfig.getEventsUri())
                .header("Content-Type", "application/json")
                .header("X-B3-TraceId", auditTracer.currentTraceId())
                .header("X-B3-SpanId", auditTracer.currentSpanId())
                .method("POST", requestBody)
                .build();
            log.info("Preparing single request [{}] [{}] - content length: [{}] Bytes",
                request.method(),
                request.url(),
                request.body() != null ? request.body().contentLength() : "unknown");
            send(request);
        } catch (JsonProcessingException | MalformedURLException ex) {
            throw new HttpRequestFailedException(format("Failed to process %s", auditEvent), ex);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    private void send(final Request request) {
        try (Response response = eventsHttpClient.newCall(request).execute()) {
            if (response.code() == 200 && response.body() != null) {
                AuditEventBodyBatch auditEventBodyBatch = objectMapper.readValue(response.body().charStream(), AuditEventBodyBatch.class);
                if(auditEventBodyBatch.getEvents() != null) {
                    auditEventBodyBatch.getEvents().forEach((auditEventBody) -> log.error("Failed to store Audit Event {} ", auditEventBody));
                }
            } else if (!response.isSuccessful()) {
                log.warn("Failed request [{}] [{}] after [{}] retries with status [{}]",
                    request.method(),
                    request.url(),
                    publisherConfig.getGiveUpAfter(),
                    response.code()
                );
                auditTracer.setCurrentSpanError(new HttpRequestFailedException(format("Failed request [%s] [%s] after [%s] retries with status [%s]",
                    request.method(),
                    request.url(),
                    publisherConfig.getGiveUpAfter(),
                    response.code()
                )));
            }
        } catch (IOException e) {
            log.error(e.getMessage());
            auditTracer.setCurrentSpanError(e);
        } catch (RuntimeException re) {
            auditTracer.setCurrentSpanError(re);
            throw re;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy