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

com.rt.storage.api.client.http.OpenCensusUtils Maven / Gradle / Ivy

package com.rt.storage.api.client.http;

import com.rt.storage.api.client.util.Beta;
import com.rt.storage.api.client.util.Preconditions;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import io.opencensus.contrib.http.util.HttpPropagationUtil;
import io.opencensus.trace.BlankSpan;
import io.opencensus.trace.EndSpanOptions;
import io.opencensus.trace.MessageEvent;
import io.opencensus.trace.MessageEvent.Type;
import io.opencensus.trace.Span;
import io.opencensus.trace.Status;
import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing;
import io.opencensus.trace.propagation.TextFormat;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
 * {@link Beta} 
* Utilities for Census monitoring and tracing. * * @author Hailong Wen * @since 1.28 */ @Beta public class OpenCensusUtils { private static final Logger logger = Logger.getLogger(OpenCensusUtils.class.getName()); /** Span name for tracing {@link HttpRequest#execute()}. */ public static final String SPAN_NAME_HTTP_REQUEST_EXECUTE = "Sent." + HttpRequest.class.getName() + ".execute"; /** * OpenCensus tracing component. When no OpenCensus implementation is provided, it will return a * no-op tracer. */ private static final Tracer tracer = Tracing.getTracer(); /** Sequence id generator for message event. */ private static final AtomicLong idGenerator = new AtomicLong(); /** Whether spans should be recorded locally. Defaults to true. */ private static volatile boolean isRecordEvent = true; /** {@link TextFormat} used in tracing context propagation. */ @Nullable @VisibleForTesting static volatile TextFormat propagationTextFormat = null; /** {@link TextFormat.Setter} for {@link #propagationTextFormat}. */ @Nullable @VisibleForTesting static volatile TextFormat.Setter propagationTextFormatSetter = null; /** * Sets the {@link TextFormat} used in context propagation. * *

This API allows users of http-client to specify other text format, or disable context * propagation by setting it to {@code null}. It should be used along with {@link * #setPropagationTextFormatSetter} for setting purpose. * * @param textFormat the text format. */ public static void setPropagationTextFormat(@Nullable TextFormat textFormat) { propagationTextFormat = textFormat; } /** * Sets the {@link io.opencensus.trace.propagation.TextFormat.Setter} used in context propagation. * *

This API allows users of http-client to specify other text format setter, or disable * context propagation by setting it to {@code null}. It should be used along with {@link * #setPropagationTextFormat} for setting purpose. * * @param textFormatSetter the {@code TextFormat.Setter} for the text format. */ public static void setPropagationTextFormatSetter(@Nullable TextFormat.Setter textFormatSetter) { propagationTextFormatSetter = textFormatSetter; } /** * Sets whether spans should be recorded locally. * *

This API allows users of http-client to turn on/off local span collection. * * @param recordEvent record span locally if true. */ public static void setIsRecordEvent(boolean recordEvent) { isRecordEvent = recordEvent; } /** * Returns the tracing component of OpenCensus. * * @return the tracing component of OpenCensus. */ public static Tracer getTracer() { return tracer; } /** * Returns whether spans should be recorded locally. * * @return whether spans should be recorded locally. */ public static boolean isRecordEvent() { return isRecordEvent; } /** * Propagate information of current tracing context. This information will be injected into HTTP * header. * * @param span the span to be propagated. * @param headers the headers used in propagation. */ public static void propagateTracingContext(Span span, HttpHeaders headers) { Preconditions.checkArgument(span != null, "span should not be null."); Preconditions.checkArgument(headers != null, "headers should not be null."); if (propagationTextFormat != null && propagationTextFormatSetter != null) { if (!span.equals(BlankSpan.INSTANCE)) { propagationTextFormat.inject(span.getContext(), headers, propagationTextFormatSetter); } } } /** * Returns an {@link EndSpanOptions} to end a http span according to the status code. * * @param statusCode the status code, can be null to represent no valid response is returned. * @return an {@code EndSpanOptions} that best suits the status code. */ public static EndSpanOptions getEndSpanOptions(@Nullable Integer statusCode) { // Always sample the span, but optionally export it. EndSpanOptions.Builder builder = EndSpanOptions.builder(); if (statusCode == null) { builder.setStatus(Status.UNKNOWN); } else if (!HttpStatusCodes.isSuccess(statusCode)) { switch (statusCode) { case HttpStatusCodes.STATUS_CODE_BAD_REQUEST: builder.setStatus(Status.INVALID_ARGUMENT); break; case HttpStatusCodes.STATUS_CODE_UNAUTHORIZED: builder.setStatus(Status.UNAUTHENTICATED); break; case HttpStatusCodes.STATUS_CODE_FORBIDDEN: builder.setStatus(Status.PERMISSION_DENIED); break; case HttpStatusCodes.STATUS_CODE_NOT_FOUND: builder.setStatus(Status.NOT_FOUND); break; case HttpStatusCodes.STATUS_CODE_PRECONDITION_FAILED: builder.setStatus(Status.FAILED_PRECONDITION); break; case HttpStatusCodes.STATUS_CODE_SERVER_ERROR: builder.setStatus(Status.UNAVAILABLE); break; default: builder.setStatus(Status.UNKNOWN); } } else { builder.setStatus(Status.OK); } return builder.build(); } /** * Records a new message event which contains the size of the request content. Note that the size * represents the message size in application layer, i.e., content-length. * * @param span The {@code span} in which the send event occurs. * @param size Size of the request. */ public static void recordSentMessageEvent(Span span, long size) { recordMessageEvent(span, size, Type.SENT); } /** * Records a new message event which contains the size of the response content. Note that the size * represents the message size in application layer, i.e., content-length. * * @param span The {@code span} in which the receive event occurs. * @param size Size of the response. */ public static void recordReceivedMessageEvent(Span span, long size) { recordMessageEvent(span, size, Type.RECEIVED); } /** * Records a message event of a certain {@link MessageEvent.Type}. This method is package * protected since {@link MessageEvent} might be deprecated in future releases. * * @param span The {@code span} in which the event occurs. * @param size Size of the message. * @param eventType The {@code NetworkEvent.Type} of the message event. */ @VisibleForTesting static void recordMessageEvent(Span span, long size, Type eventType) { Preconditions.checkArgument(span != null, "span should not be null."); if (size < 0) { size = 0; } MessageEvent event = MessageEvent.builder(eventType, idGenerator.getAndIncrement()) .setUncompressedMessageSize(size) .build(); span.addMessageEvent(event); } static { try { propagationTextFormat = HttpPropagationUtil.getCloudTraceFormat(); propagationTextFormatSetter = new TextFormat.Setter() { @Override public void put(HttpHeaders carrier, String key, String value) { carrier.set(key, value); } }; } catch (Exception e) { logger.log( Level.WARNING, "Cannot initialize default OpenCensus HTTP propagation text format.", e); } try { Tracing.getExportComponent() .getSampledSpanStore() .registerSpanNamesForCollection(ImmutableList.of(SPAN_NAME_HTTP_REQUEST_EXECUTE)); } catch (Exception e) { logger.log(Level.WARNING, "Cannot register default OpenCensus span names for collection.", e); } } private OpenCensusUtils() {} }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy