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

com.google.apphosting.runtime.TraceContextHelper Maven / Gradle / Ivy

There is a newer version: 2.0.32
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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 com.google.apphosting.runtime;

import com.google.apphosting.api.CloudTraceContext;
import com.google.apphosting.base.protos.TraceId.TraceIdProto;
import com.google.apphosting.base.protos.TracePb.TraceContextProto;
import com.google.protobuf.ByteString;

/**
 * Helper functions for trace context. This object contains static functions for internal use only.
 * Functions used by external customers should be defined in {@link CloudTraceContext}.
 */
public class TraceContextHelper {
  private static final long INVALID_SPAN_ID = 0;
  private static final long MASK_TRACE_ENABLED = 0x01;
  private static final long MASK_STACK_TRACE_ENABLED = 0x02;

  private static final String OPTIONS_SEPARATOR_AND_VARIABLE = ";o=";
  private static final int TRACE_LENGTH = 32;

  /**
   * Convert the proto {@link TraceContextProto} to object {@link CloudTraceContext}.
   * @param proto the PB holding the trace context
   */
  static CloudTraceContext toObject(TraceContextProto proto) {
    return new CloudTraceContext(
        proto.getTraceId().toByteArray(), INVALID_SPAN_ID, proto.getSpanId(), proto.getTraceMask());
  }

  /**
   * Convert the object {@link CloudTraceContext} to proto {@link TraceContextProto}.
   *
   * 

Note that parent span ID is discarded during the conversion. The proto is used to pass trace * context from one process to another, and the parent span ID is not useful. If the proto is * converted back to an object, the object doesn't have parent span ID. */ static TraceContextProto toProto2(CloudTraceContext context) { return TraceContextProto.newBuilder() .setTraceId(ByteString.copyFrom(context.getTraceId())) .setSpanId(context.getSpanId()) .setTraceMask((int) context.getTraceMask()) .build(); } static boolean needsTrace(TraceContextProto contextProto) { return needsTrace(contextProto.getTraceMask()); } static boolean needsTrace(long traceMask) { return (traceMask & MASK_TRACE_ENABLED) != 0; } private static boolean needsStackTrace(long traceMask) { return (traceMask & MASK_STACK_TRACE_ENABLED) != 0; } static boolean needsStackTrace(TraceContextProto contextProto) { return needsStackTrace(contextProto.getTraceMask()); } static boolean isStackTraceEnabled(CloudTraceContext context) { return needsStackTrace(context.getTraceMask()); } /** * Create TraceContext from header, based on * C++ source. * *

Examples of valid X-Cloud-Trace-Context headers: *

   * 000000000000007b00000000000001c8/789;o=1 (trace, span, and options)
   * 000000000000007b00000000000001c8/789;o= (trace and span, empty options)
   * 000000000000007b00000000000001c8/789 (trace and span, no options)
   * 000000000000007b00000000000001c8/;o=1 (trace and options, empty span)
   * 000000000000007b00000000000001c8/;o= (trace, empty span and options)
   * 000000000000007b00000000000001c8/ (trace, empty span, no options)
   * 000000000000007b00000000000001c8;o=1 (trace and options, no span)
   * 000000000000007b00000000000001c8;o= (trace, empty options, no span)
   * 000000000000007b00000000000001c8 (trace, no span, no options)
   * 
* * @param traceContextHeader a String representing the "X-Cloud-Trace-Context" which has the form * "TRACE_ID/SPAN_ID;o=TRACE_TRUE" where TRACE_TRUE = 0 or 1. See * this link * for details. * @return TraceContextProto containing the trace id, span id, and trace mask * @throws NumberFormatException if the trace id is less than 32 characters, or the trace mask or * span id are not numerical values */ public static TraceContextProto parseTraceContextHeader(String traceContextHeader) { TraceContextProto.Builder protoBuilder = TraceContextProto.newBuilder(); // Trace ID is up to the first slash, semicolon, or end of string, whatever comes first int slashStart = traceContextHeader.indexOf('/'); int semiStart = traceContextHeader.indexOf(';'); int traceEnd = slashStart >= 0 ? slashStart : semiStart >= 0 ? semiStart : traceContextHeader.length(); String traceId = traceContextHeader.substring(0, traceEnd); protoBuilder.setTraceId(parseTraceId(traceId).toByteString()); // Options is the last ';o=[0|1]' entry in the string; could be empty (";o=") as well int optionsStart = traceContextHeader.lastIndexOf(OPTIONS_SEPARATOR_AND_VARIABLE); if (optionsStart > 0) { optionsStart = optionsStart + OPTIONS_SEPARATOR_AND_VARIABLE.length(); if (optionsStart < traceContextHeader.length()) { String options = traceContextHeader.substring(optionsStart); protoBuilder.setTraceMask(Integer.parseUnsignedInt(options)); } } // Span ID starts after the first '/' up to ';' or the end; can be empty as well if (slashStart > 0) { int spanIdEnd = semiStart > slashStart ? semiStart : traceContextHeader.length(); if (slashStart + 1 < spanIdEnd) { String spanId = traceContextHeader.substring(slashStart + 1, spanIdEnd); protoBuilder.setSpanId(Long.parseUnsignedLong(spanId)); } } return protoBuilder.build(); } private static TraceIdProto parseTraceId(String traceId) { if (traceId.length() < TRACE_LENGTH) { throw new NumberFormatException("Invalid TRACE ID: length too short"); } String traceIdHi = traceId.substring(0, 16); String traceIdLo = traceId.substring(16, 32); return TraceIdProto.newBuilder() .setHi(Long.parseUnsignedLong(traceIdHi, 16)) .setLo(Long.parseUnsignedLong(traceIdLo, 16)) .build(); } private TraceContextHelper() {} }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy