com.google.appengine.repackaged.io.opencensus.contrib.http.AbstractHttpHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of appengine-api-1.0-sdk
Show all versions of appengine-api-1.0-sdk
API for Google App Engine standard environment with some of the dependencies shaded (repackaged)
/*
* Copyright 2018, OpenCensus Authors
*
* 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 permissions and
* limitations under the License.
*/
package io.opencensus.contrib.http;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.VisibleForTesting;
import io.opencensus.contrib.http.util.HttpTraceAttributeConstants;
import io.opencensus.contrib.http.util.HttpTraceUtil;
import io.opencensus.tags.TagContext;
import io.opencensus.trace.AttributeValue;
import io.opencensus.trace.MessageEvent;
import io.opencensus.trace.MessageEvent.Type;
import io.opencensus.trace.Span;
import io.opencensus.trace.Span.Options;
import javax.annotation.Nullable;
/** Base class for handling request on http client and server. */
abstract class AbstractHttpHandler {
/** The {@link HttpExtractor} used to extract information from request/response. */
@VisibleForTesting final HttpExtractor extractor;
/** Constructor to allow access from same package subclasses only. */
AbstractHttpHandler(HttpExtractor extractor) {
checkNotNull(extractor, "extractor");
this.extractor = extractor;
}
/**
* A convenience to record a {@link MessageEvent} with given parameters.
*
* @param span the span which this {@code MessageEvent} will be added to.
* @param id the id of the event.
* @param type the {@code MessageEvent.Type} of the event.
* @param uncompressedMessageSize size of the message before compressed (optional).
* @param compressedMessageSize size of the message after compressed (optional).
* @since 0.19
*/
static void recordMessageEvent(
Span span, long id, Type type, long uncompressedMessageSize, long compressedMessageSize) {
MessageEvent messageEvent =
MessageEvent.builder(type, id)
.setUncompressedMessageSize(uncompressedMessageSize)
.setCompressedMessageSize(compressedMessageSize)
.build();
span.addMessageEvent(messageEvent);
}
private static void putAttributeIfNotEmptyOrNull(Span span, String key, @Nullable String value) {
if (value != null && !value.isEmpty()) {
span.putAttribute(key, AttributeValue.stringAttributeValue(value));
}
}
/**
* Instrument an HTTP span after a message is sent. Typically called for every chunk of request or
* response is sent.
*
* @param context request specific {@link HttpRequestContext}
* @param bytes bytes sent.
* @since 0.19
*/
public final void handleMessageSent(HttpRequestContext context, long bytes) {
checkNotNull(context, "context");
context.sentMessageSize.addAndGet(bytes);
if (context.span.getOptions().contains(Options.RECORD_EVENTS)) {
// record compressed size
recordMessageEvent(context.span, context.sentSeqId.addAndGet(1L), Type.SENT, bytes, 0L);
}
}
/**
* Instrument an HTTP span after a message is received. Typically called for every chunk of
* request or response is received.
*
* @param context request specific {@link HttpRequestContext}
* @param bytes bytes received.
* @since 0.19
*/
public final void handleMessageReceived(HttpRequestContext context, long bytes) {
checkNotNull(context, "context");
context.receiveMessageSize.addAndGet(bytes);
if (context.span.getOptions().contains(Options.RECORD_EVENTS)) {
// record compressed size
recordMessageEvent(
context.span, context.receviedSeqId.addAndGet(1L), Type.RECEIVED, bytes, 0L);
}
}
void spanEnd(Span span, int httpStatus, @Nullable Throwable error) {
if (span.getOptions().contains(Options.RECORD_EVENTS)) {
span.putAttribute(
HttpTraceAttributeConstants.HTTP_STATUS_CODE,
AttributeValue.longAttributeValue(httpStatus));
span.setStatus(HttpTraceUtil.parseResponseStatus(httpStatus, error));
}
span.end();
}
final String getSpanName(Q request, HttpExtractor extractor) {
// default span name
String path = extractor.getPath(request);
if (path == null) {
path = "/";
}
if (!path.startsWith("/")) {
path = "/" + path;
}
return path;
}
final void addSpanRequestAttributes(Span span, Q request, HttpExtractor extractor) {
putAttributeIfNotEmptyOrNull(
span, HttpTraceAttributeConstants.HTTP_USER_AGENT, extractor.getUserAgent(request));
putAttributeIfNotEmptyOrNull(
span, HttpTraceAttributeConstants.HTTP_HOST, extractor.getHost(request));
putAttributeIfNotEmptyOrNull(
span, HttpTraceAttributeConstants.HTTP_METHOD, extractor.getMethod(request));
putAttributeIfNotEmptyOrNull(
span, HttpTraceAttributeConstants.HTTP_PATH, extractor.getPath(request));
putAttributeIfNotEmptyOrNull(
span, HttpTraceAttributeConstants.HTTP_ROUTE, extractor.getRoute(request));
putAttributeIfNotEmptyOrNull(
span, HttpTraceAttributeConstants.HTTP_URL, extractor.getUrl(request));
}
/**
* Retrieves {@link Span} from the {@link HttpRequestContext}.
*
* @param context request specific {@link HttpRequestContext}
* @return {@link Span} associated with the request.
* @since 0.19
*/
public Span getSpanFromContext(HttpRequestContext context) {
checkNotNull(context, "context");
return context.span;
}
HttpRequestContext getNewContext(Span span, TagContext tagContext) {
return new HttpRequestContext(span, tagContext);
}
}