
com.google.cloud.logging.Context Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-cloud-logging Show documentation
Show all versions of google-cloud-logging Show documentation
Java idiomatic client for Cloud Logging
/*
* 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.cloud.logging;
import com.google.cloud.logging.HttpRequest.RequestMethod;
import com.google.common.base.Ascii;
import com.google.common.base.MoreObjects;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** Class to hold context attributes including information about {@see HttpRequest} and tracing. */
public class Context {
// validate W3C trace context value on load according to the existing version format.
// see https://www.w3.org/TR/trace-context/#traceparent-header-field-values for details.
private static final Pattern W3C_TRACE_CONTEXT_FORMAT =
Pattern.compile(
"^00-(?!00000000000000000000000000000000)[0-9a-f]{32}-(?!0000000000000000)[0-9a-f]{16}-[0-9a-f]{2}$");
private final HttpRequest request;
private final String traceId;
private final String spanId;
/** A builder for {@see Context} objects. */
public static final class Builder {
private HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
private String traceId;
private String spanId;
Builder() {}
Builder(Context context) {
this.requestBuilder = context.request.toBuilder();
this.traceId = context.traceId;
this.spanId = context.spanId;
}
/** Sets the HTTP request. */
@CanIgnoreReturnValue
public Builder setRequest(HttpRequest request) {
this.requestBuilder = request != null ? request.toBuilder() : HttpRequest.newBuilder();
return this;
}
@CanIgnoreReturnValue
public Builder setRequestUrl(String url) {
this.requestBuilder.setRequestUrl(url);
return this;
}
/** Sets the HTTP request method. */
@CanIgnoreReturnValue
public Builder setRequestMethod(RequestMethod method) {
this.requestBuilder.setRequestMethod(method);
return this;
}
/**
* Sets the referer URL of the request, as defined in HTTP/1.1 Header Field Definitions.
*
* @see HTTP/1.1 Header Field
* Definitions
*/
@CanIgnoreReturnValue
public Builder setReferer(String referer) {
this.requestBuilder.setReferer(referer);
return this;
}
/**
* Sets the IP address (IPv4 or IPv6) of the client that issued the HTTP request. Examples:
* {@code 192.168.1.1}, {@code FE80::0202:B3FF:FE1E:8329}.
*/
@CanIgnoreReturnValue
public Builder setRemoteIp(String remoteIp) {
this.requestBuilder.setRemoteIp(remoteIp);
return this;
}
/**
* Sets the IP address (IPv4 or IPv6) of the origin server that the request was sent to.
* Examples: {@code 192.168.1.1}, {@code FE80::0202:B3FF:FE1E:8329}.
*/
@CanIgnoreReturnValue
public Builder setServerIp(String serverIp) {
this.requestBuilder.setServerIp(serverIp);
return this;
}
/** Sets the string as a trace id value. */
@CanIgnoreReturnValue
public Builder setTraceId(String traceId) {
this.traceId = traceId;
return this;
}
/** Sets the string as a span id value. */
@CanIgnoreReturnValue
public Builder setSpanId(String spanId) {
this.spanId = spanId;
return this;
}
/**
* Sets the trace id and span id values by parsing the string which represents xCloud Trace
* Context. The Cloud Trace Context is passed as {@code x-cloud-trace-context} header (can be in
* Pascal case format). The string format is TRACE_ID/SPAN_ID;o=TRACE_TRUE
.
*
* @see Cloud Trace header
* format.
*/
@CanIgnoreReturnValue
public Builder loadCloudTraceContext(String cloudTrace) {
if (cloudTrace != null) {
cloudTrace = Iterables.get(Splitter.on(';').split(cloudTrace), 0);
int split = cloudTrace.indexOf('/');
if (split >= 0) {
String traceId = cloudTrace.substring(0, split);
String spanId = cloudTrace.substring(split + 1);
if (!traceId.isEmpty()) {
setTraceId(traceId);
// do not set span Id without trace Id
if (!spanId.isEmpty()) {
setSpanId(spanId);
}
}
} else if (!cloudTrace.isEmpty()) {
setTraceId(cloudTrace);
}
}
return this;
}
/**
* Sets the trace id and span id values by parsing the string which represents the standard W3C
* trace context propagation header. The context propagation header is passed as {@code
* traceparent} header. The method currently supports ONLY version {@code "00"}. The string
* format is 00-TRACE_ID-SPAN_ID-FLAGS
. field of the {@code version-format} value.
*
* @see traceparent header
* value format
* @throws IllegalArgumentException if passed argument does not follow the @W3C trace format or
* the format version is not supported.
*/
@CanIgnoreReturnValue
public Builder loadW3CTraceParentContext(String traceParent) {
if (traceParent != null) {
Matcher validator = W3C_TRACE_CONTEXT_FORMAT.matcher(Ascii.toLowerCase(traceParent));
if (!validator.matches()) {
throw new IllegalArgumentException(
"Invalid format of the header value. The value does not match W3C Trace Context version \"00\"");
}
List fields = Splitter.on('-').splitToList(traceParent);
setTraceId(fields.get(1));
setSpanId(fields.get(2));
// fields[3] contains flag(s)
}
return this;
}
/** Creates a {@see Context} object for this builder. */
public Context build() {
return new Context(this);
}
}
Context(Builder builder) {
HttpRequest request = builder.requestBuilder.build();
if (!HttpRequest.EMPTY.equals(request)) {
this.request = request;
} else {
this.request = null;
}
this.traceId = builder.traceId;
this.spanId = builder.spanId;
}
public HttpRequest getHttpRequest() {
return this.request;
}
public String getTraceId() {
return this.traceId;
}
public String getSpanId() {
return this.spanId;
}
@Override
public int hashCode() {
return Objects.hash(request, traceId, spanId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("request", request)
.add("traceId", traceId)
.add("spanId", spanId)
.toString();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Context)) {
return false;
}
Context other = (Context) obj;
return Objects.equals(request, other.request)
&& Objects.equals(traceId, other.traceId)
&& Objects.equals(spanId, other.spanId);
}
/** Returns a builder for this object. */
public Builder toBuilder() {
return new Builder(this);
}
/** Returns a builder for {@code HttpRequest} objects. */
public static Builder newBuilder() {
return new Builder();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy