diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 994dd04bf..88d9b926c 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:fecf6bd85f19eb046d913982ea36f6d434f9a49ab0545d25e31186aa64367c0c + digest: sha256:5b8c790f57cca57e6b37ba25f79291265c218cea3e6ba9714b001910ab3f1419 diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml new file mode 100644 index 000000000..ee3b8b2de --- /dev/null +++ b/.github/auto-label.yaml @@ -0,0 +1,5 @@ +product: true +staleness: + pullrequest: true + old: 30 + critical: 60 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 93b337c62..05de1f60d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -53,7 +53,7 @@ jobs: - uses: actions/setup-java@v2 with: distribution: zulu - java-version: 8 + java-version: 11 - run: java -version - run: .kokoro/build.sh env: diff --git a/.kokoro/build.sh b/.kokoro/build.sh index f8ec50dce..3446ae7d1 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -91,7 +91,6 @@ samples) pushd ${SAMPLES_DIR} mvn -B \ - -Penable-samples \ -ntp \ -DtrimStackTrace=false \ -Dclirr.skip=true \ diff --git a/.kokoro/release/publish_javadoc11.sh b/.kokoro/release/publish_javadoc11.sh index e38e02d2a..ff13ff848 100755 --- a/.kokoro/release/publish_javadoc11.sh +++ b/.kokoro/release/publish_javadoc11.sh @@ -36,13 +36,9 @@ mvn clean install -B -q -DskipTests=true export NAME=google-cloud-logging export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) -# V3 generates docfx yml from javadoc -# generate yml -mvn clean site -B -q -P docFX - -# copy README to docfx-yml dir and rename index.md -cp README.md target/docfx-yml/index.md -# copy CHANGELOG to docfx-yml dir and rename history.md +# cloud RAD generation +mvn clean javadoc:aggregate -B -q -P docFX +# include CHANGELOG cp CHANGELOG.md target/docfx-yml/history.md pushd target/docfx-yml diff --git a/.readme-partials.yaml b/.readme-partials.yaml index da4921d9a..95e214c54 100644 --- a/.readme-partials.yaml +++ b/.readme-partials.yaml @@ -94,7 +94,7 @@ custom_content: | imports at the top of your file: ```java - import com.google.cloud.Page; + import com.google.api.gax.paging.Page; import com.google.cloud.logging.LogEntry; import com.google.cloud.logging.Logging.EntryListOption; ``` @@ -104,12 +104,13 @@ custom_content: | ``` java Page entries = logging.listLogEntries( EntryListOption.filter("logName=projects/" + options.getProjectId() + "/logs/test-log")); - Iterator entryIterator = entries.iterateAll().iterator(); - while (entryIterator.hasNext()) { - System.out.println(entryIterator.next()); + while (entries != null) { + for (LogEntry logEntry : entries.iterateAll()) { + System.out.println(logEntry); + } + entries = entries.getNextPage(); } ``` - #### Add a Cloud Logging handler to a logger You can also register a `LoggingHandler` to a `java.util.logging.Logger` that publishes log entries @@ -133,13 +134,3 @@ custom_content: | ``` com.google.cloud.examples.logging.snippets.AddLoggingHandler.handlers=com.google.cloud.logging.LoggingHandler ``` - - #### Complete source code - - In - [CreateAndListMetrics.java](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListMetrics.java), - [WriteAndListLogEntries.java](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/WriteAndListLogEntries.java) - and - [AddLoggingHandler.java](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/AddLoggingHandler.java) - we put together all the code shown above into three programs. The programs assume that you are - running on Compute Engine or from your own desktop. \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a01dddb42..9a71f81f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [3.5.0](https://www.github.com/googleapis/java-logging/compare/v3.4.0...v3.5.0) (2021-11-24) + + +### Features + +* Enable auto-label bot to mark stale pull requests ([#758](https://www.github.com/googleapis/java-logging/issues/758)) ([23f7fa5](https://www.github.com/googleapis/java-logging/commit/23f7fa559add710b96bad90002fcebef8ac0e5c9)) +* implement context handler to store HTTP request and tracing information ([#752](https://www.github.com/googleapis/java-logging/issues/752)) ([86223ff](https://www.github.com/googleapis/java-logging/commit/86223ff36f9c4b147f322ba646607727b92fbe7b)) + + +### Bug Fixes + +* handle null pointer when parsing metadata attributes ([#759](https://www.github.com/googleapis/java-logging/issues/759)) ([e8cf6f9](https://www.github.com/googleapis/java-logging/commit/e8cf6f91b56529d28cc002cedb0976ce952e0e0e)) +* modify list log entries example documentation ([#740](https://www.github.com/googleapis/java-logging/issues/740)) ([790fb1a](https://www.github.com/googleapis/java-logging/commit/790fb1a342d63704298d16a576f6cce15bfd4398)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.0 ([#743](https://www.github.com/googleapis/java-logging/issues/743)) ([c003417](https://www.github.com/googleapis/java-logging/commit/c003417aade41e025082f47f2185e66707bffcff)) + ## [3.4.0](https://www.github.com/googleapis/java-logging/compare/v3.3.0...v3.4.0) (2021-11-06) diff --git a/README.md b/README.md index 1e26f283c..091e195a6 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ If you are using Maven without BOM, add this to your dependencies: com.google.cloud google-cloud-logging - 3.3.0 + 3.4.0 ``` @@ -58,13 +58,13 @@ implementation 'com.google.cloud:google-cloud-logging' If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-logging:3.3.0' +implementation 'com.google.cloud:google-cloud-logging:3.4.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "3.3.0" +libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "3.4.0" ``` ## Authentication @@ -194,7 +194,7 @@ With Logging you can also list log entries that have been previously written. Ad imports at the top of your file: ```java -import com.google.cloud.Page; +import com.google.api.gax.paging.Page; import com.google.cloud.logging.LogEntry; import com.google.cloud.logging.Logging.EntryListOption; ``` @@ -204,12 +204,13 @@ Then, to list the log entries, use the following code: ``` java Page entries = logging.listLogEntries( EntryListOption.filter("logName=projects/" + options.getProjectId() + "/logs/test-log")); -Iterator entryIterator = entries.iterateAll().iterator(); -while (entryIterator.hasNext()) { - System.out.println(entryIterator.next()); +while (entries != null) { + for (LogEntry logEntry : entries.iterateAll()) { + System.out.println(logEntry); + } + entries = entries.getNextPage(); } ``` - #### Add a Cloud Logging handler to a logger You can also register a `LoggingHandler` to a `java.util.logging.Logger` that publishes log entries @@ -234,15 +235,6 @@ file. Adding, for instance, the following line: com.google.cloud.examples.logging.snippets.AddLoggingHandler.handlers=com.google.cloud.logging.LoggingHandler ``` -#### Complete source code - -In -[CreateAndListMetrics.java](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListMetrics.java), -[WriteAndListLogEntries.java](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/WriteAndListLogEntries.java) -and -[AddLoggingHandler.java](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/AddLoggingHandler.java) -we put together all the code shown above into three programs. The programs assume that you are -running on Compute Engine or from your own desktop. @@ -274,7 +266,7 @@ Cloud Logging uses gRPC for the transport layer. ## Supported Java Versions -Java 7 or above is required for using this client. +Java 8 or above is required for using this client. Google's Java client libraries, [Google Cloud Client Libraries][cloudlibs] @@ -343,7 +335,6 @@ Apache 2.0 - See [LICENSE][license] for more information. Java Version | Status ------------ | ------ -Java 7 | [![Kokoro CI][kokoro-badge-image-1]][kokoro-badge-link-1] Java 8 | [![Kokoro CI][kokoro-badge-image-2]][kokoro-badge-link-2] Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] diff --git a/env-tests-logging b/env-tests-logging index c283c2943..8dbce5f6a 160000 --- a/env-tests-logging +++ b/env-tests-logging @@ -1 +1 @@ -Subproject commit c283c2943363d9c18d846827a44cac282a730437 +Subproject commit 8dbce5f6a710f210f0a3d2b0639b3b10439d2a73 diff --git a/google-cloud-logging-bom/pom.xml b/google-cloud-logging-bom/pom.xml index 72a939e6f..a202e7248 100644 --- a/google-cloud-logging-bom/pom.xml +++ b/google-cloud-logging-bom/pom.xml @@ -3,12 +3,12 @@ 4.0.0 com.google.cloud google-cloud-logging-bom - 3.4.0 + 3.5.0 pom com.google.cloud google-cloud-shared-config - 1.2.0 + 1.2.2 Google Cloud logging BOM @@ -53,17 +53,17 @@ com.google.cloud google-cloud-logging - 3.4.0 + 3.5.0 com.google.api.grpc grpc-google-cloud-logging-v2 - 0.93.0 + 0.94.0 com.google.api.grpc proto-google-cloud-logging-v2 - 0.93.0 + 0.94.0 diff --git a/google-cloud-logging/clirr-ignored-differences.xml b/google-cloud-logging/clirr-ignored-differences.xml deleted file mode 100644 index 49890ed46..000000000 --- a/google-cloud-logging/clirr-ignored-differences.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - 7012 - com/google/cloud/logging/Logging - * deleteLog*(java.lang.String, com.google.cloud.logging.LogDestinationName) - - diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index ad165f170..a102f5a72 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-logging - 3.4.0 + 3.5.0 jar Google Cloud Logging https://github.com/googleapis/java-logging @@ -11,7 +11,7 @@ com.google.cloud google-cloud-logging-parent - 3.4.0 + 3.5.0 google-cloud-logging diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java new file mode 100644 index 000000000..e88980d36 --- /dev/null +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -0,0 +1,235 @@ +/* + * 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.MoreObjects; +import com.google.common.base.Strings; +import java.util.Objects; + +/** Class to hold context attributes including information about {@see HttpRequest} and tracing. */ +public class Context { + 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. */ + public Builder setRequest(HttpRequest request) { + this.requestBuilder = request.toBuilder(); + return this; + } + + public Builder setRequestUrl(String url) { + this.requestBuilder.setRequestUrl(url); + return this; + } + + /** Sets the HTTP request method. */ + 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 + */ + 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}. + */ + 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}. + */ + public Builder setServerIp(String serverIp) { + this.requestBuilder.setServerIp(serverIp); + return this; + } + + /** Sets the string as a trace id value. */ + public Builder setTraceId(String traceId) { + this.traceId = traceId; + return this; + } + + /** Sets the string as a span id value. */ + 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. + */ + public Builder loadCloudTraceContext(String cloudTrace) { + if (cloudTrace != null) { + cloudTrace = cloudTrace.split(";")[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. + */ + public Builder loadW3CTraceParentContext(String traceParent) throws IllegalArgumentException { + if (traceParent != null) { + String[] fields = traceParent.split("-"); + if (fields.length > 3) { + String versionFormat = fields[0]; + if (!versionFormat.equals("00")) { + throw new IllegalArgumentException("Not supporting versionFormat other than \"00\""); + } + } else { + throw new IllegalArgumentException( + "Invalid format of the header value. Expected \"00-traceid-spanid-arguments\""); + } + String traceId = fields[1]; + if (!traceId.isEmpty()) { + setTraceId(traceId); + } + if (!Strings.isNullOrEmpty(traceId)) { + String spanId = fields[2]; + if (!spanId.isEmpty()) { + setSpanId(spanId); + } + } + } + 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(); + } +} diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java new file mode 100644 index 000000000..8af084f27 --- /dev/null +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -0,0 +1,50 @@ +/* + * 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; + +/** Class provides a per-thread storage of the {@see Context} instances. */ +public class ContextHandler { + private static final ThreadLocal contextHolder = initContextHolder(); + + /** + * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} + * configuration property {@code com.google.cloud.logging.ContextHandler.useInheritedContext} is + * set to {@code true} or to {@link ThreadLocal} otherwise. + * + * @return instance of the context holder. + */ + private static ThreadLocal initContextHolder() { + LoggingConfig config = new LoggingConfig(ContextHandler.class.getName()); + if (config.getUseInheritedContext()) { + return new InheritableThreadLocal<>(); + } else { + return new ThreadLocal<>(); + } + } + + public Context getCurrentContext() { + return contextHolder.get(); + } + + public void setCurrentContext(Context context) { + contextHolder.set(context); + } + + public void removeCurrentContext() { + contextHolder.remove(); + } +} diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/HttpRequest.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/HttpRequest.java index 2ba5e99dd..5c4b71ed9 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/HttpRequest.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/HttpRequest.java @@ -36,6 +36,7 @@ public final class HttpRequest implements Serializable { private static final long serialVersionUID = -274998005454709817L; + public static final HttpRequest EMPTY = newBuilder().build(); private final RequestMethod requestMethod; private final String requestUrl; diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LogDestinationName.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LogDestinationName.java index e23446b7a..9b284c070 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LogDestinationName.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LogDestinationName.java @@ -27,6 +27,7 @@ * parameter in https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry) */ public final class LogDestinationName extends Option { + private static final long serialVersionUID = 7944256748441111191L; enum DestinationType implements Option.OptionType { PROJECT, diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java index 3c220cfa7..d2a001fb0 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java @@ -40,6 +40,7 @@ class LoggingConfig { private static final String SYNCHRONICITY_TAG = "synchronicity"; private static final String RESOURCE_TYPE_TAG = "resourceType"; private static final String ENHANCERS_TAG = "enhancers"; + private static final String USE_INHERITED_CONTEXT = "useInheritedContext"; public LoggingConfig(String className) { this.className = className; @@ -100,6 +101,18 @@ List getEnhancers() { return Collections.emptyList(); } + /** + * Returns boolean value of the property {@code + * com.google.cloud.logging.context.ContextHandler.useInheritedContext}. If no value is defined or + * the property does not represent a valid boolean value returns {@code false}. + * + * @return {@code true} or {@code false} + */ + boolean getUseInheritedContext() { + String flag = getProperty(USE_INHERITED_CONTEXT, "FALSE"); + return Boolean.parseBoolean(flag); + } + private String getProperty(String name, String defaultValue) { return firstNonNull(getProperty(name), defaultValue); } @@ -121,7 +134,7 @@ private Filter getFilterProperty(String name, Filter defaultValue) { String stringFilter = getProperty(name); try { if (stringFilter != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(stringFilter); + Class clz = ClassLoader.getSystemClassLoader().loadClass(stringFilter); return (Filter) clz.getDeclaredConstructor().newInstance(); } } catch (Exception ex) { @@ -134,7 +147,7 @@ private Formatter getFormatterProperty(String name, Formatter defaultValue) { String stringFilter = getProperty(name); try { if (stringFilter != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(stringFilter); + Class clz = ClassLoader.getSystemClassLoader().loadClass(stringFilter); return (Formatter) clz.getDeclaredConstructor().newInstance(); } } catch (Exception ex) { diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index 2f2d194bf..789f825cb 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -200,6 +200,7 @@ public ApiFuture> getNextPage() { } private static class LogNamePageFetcher extends BasePageFetcher { + private static final long serialVersionUID = 5308841362690185583L; LogNamePageFetcher( LoggingOptions serviceOptions, String cursor, Map requestOptions) { @@ -244,6 +245,7 @@ public ApiFuture> getNextPage() { } private static class ExclusionPageFetcher extends BasePageFetcher { + private static final long serialVersionUID = -1414118808031778916L; ExclusionPageFetcher( LoggingOptions serviceOptions, String cursor, Map requestOptions) { diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/MetadataLoader.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/MetadataLoader.java index fdb61f64e..6f72d1b90 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/MetadataLoader.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/MetadataLoader.java @@ -137,10 +137,10 @@ private String getModuleId() { * K8S_POD_NAMESPACE_PATH} when available or read from a user defined environment variable * "NAMESPACE_NAME" * - * @return Namespace name or empty string if the name could not be discovered + * @return Namespace string or null if the name could not be discovered */ private String getNamespaceName() { - String value = ""; + String value = null; try { value = new String( @@ -151,9 +151,6 @@ private String getNamespaceName() { // if SA token is not shared the info about namespace is unavailable // allow users to define the namespace name explicitly value = getter.getEnv("NAMESPACE_NAME"); - if (value == null) { - value = ""; - } } return value; } @@ -178,7 +175,10 @@ private String getProjectId() { */ private String getRegion() { String loc = getter.getAttribute("instance/region"); - return loc.substring(loc.lastIndexOf('/') + 1); + if (loc != null) { + return loc.substring(loc.lastIndexOf('/') + 1); + } + return null; } private String getRevisionName() { @@ -199,6 +199,9 @@ private String getVersionId() { */ private String getZone() { String loc = getter.getAttribute("instance/zone"); - return loc.substring(loc.lastIndexOf('/') + 1); + if (loc != null) { + return loc.substring(loc.lastIndexOf('/') + 1); + } + return null; } } diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java index 80aea34ec..f1593eb8a 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java @@ -19,16 +19,9 @@ /* Adds tracing support for logging with thread-local trace ID tracking. */ public class TraceLoggingEnhancer implements LoggingEnhancer { - private static final String TRACE_ID = "trace_id"; - private final String traceIdLabel; + public TraceLoggingEnhancer() {} - public TraceLoggingEnhancer() { - traceIdLabel = TRACE_ID; - } - - public TraceLoggingEnhancer(String prefix) { - traceIdLabel = (prefix != null) ? prefix + TRACE_ID : TRACE_ID; - } + public TraceLoggingEnhancer(String prefix) {} private static final ThreadLocal traceId = new ThreadLocal<>(); diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/ConfigClient.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/ConfigClient.java index 2bce0705f..cf5b1db53 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/ConfigClient.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/ConfigClient.java @@ -329,9 +329,7 @@ public final ListBucketsPagedResponse listBuckets(OrganizationLocationName paren * *
{@code
    * try (ConfigClient configClient = ConfigClient.create()) {
-   *   String parent =
-   *       LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-   *           .toString();
+   *   String parent = LocationName.of("[PROJECT]", "[LOCATION]").toString();
    *   for (LogBucket element : configClient.listBuckets(parent).iterateAll()) {
    *     // doThingsWith(element);
    *   }
@@ -362,9 +360,7 @@ public final ListBucketsPagedResponse listBuckets(String parent) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListBucketsRequest request =
    *       ListBucketsRequest.newBuilder()
-   *           .setParent(
-   *               LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-   *                   .toString())
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -391,9 +387,7 @@ public final ListBucketsPagedResponse listBuckets(ListBucketsRequest request) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListBucketsRequest request =
    *       ListBucketsRequest.newBuilder()
-   *           .setParent(
-   *               LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-   *                   .toString())
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -420,9 +414,7 @@ public final ListBucketsPagedResponse listBuckets(ListBucketsRequest request) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListBucketsRequest request =
    *       ListBucketsRequest.newBuilder()
-   *           .setParent(
-   *               LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-   *                   .toString())
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -505,9 +497,7 @@ public final UnaryCallable getBucketCallable() {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   CreateBucketRequest request =
    *       CreateBucketRequest.newBuilder()
-   *           .setParent(
-   *               LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-   *                   .toString())
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
    *           .setBucketId("bucketId-1603305307")
    *           .setBucket(LogBucket.newBuilder().build())
    *           .build();
@@ -533,9 +523,7 @@ public final LogBucket createBucket(CreateBucketRequest request) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   CreateBucketRequest request =
    *       CreateBucketRequest.newBuilder()
-   *           .setParent(
-   *               LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-   *                   .toString())
+   *           .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
    *           .setBucketId("bucketId-1603305307")
    *           .setBucket(LogBucket.newBuilder().build())
    *           .build();
@@ -1146,7 +1134,7 @@ public final ListSinksPagedResponse listSinks(ProjectName parent) {
    *
    * 
{@code
    * try (ConfigClient configClient = ConfigClient.create()) {
-   *   String parent = LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString();
+   *   String parent = ProjectName.of("[PROJECT]").toString();
    *   for (LogSink element : configClient.listSinks(parent).iterateAll()) {
    *     // doThingsWith(element);
    *   }
@@ -1173,7 +1161,7 @@ public final ListSinksPagedResponse listSinks(String parent) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListSinksRequest request =
    *       ListSinksRequest.newBuilder()
-   *           .setParent(LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -1200,7 +1188,7 @@ public final ListSinksPagedResponse listSinks(ListSinksRequest request) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListSinksRequest request =
    *       ListSinksRequest.newBuilder()
-   *           .setParent(LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -1226,7 +1214,7 @@ public final UnaryCallable listSinksPa
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListSinksRequest request =
    *       ListSinksRequest.newBuilder()
-   *           .setParent(LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -1496,7 +1484,7 @@ public final LogSink createSink(ProjectName parent, LogSink sink) {
    *
    * 
{@code
    * try (ConfigClient configClient = ConfigClient.create()) {
-   *   String parent = LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString();
+   *   String parent = ProjectName.of("[PROJECT]").toString();
    *   LogSink sink = LogSink.newBuilder().build();
    *   LogSink response = configClient.createSink(parent, sink);
    * }
@@ -1529,7 +1517,7 @@ public final LogSink createSink(String parent, LogSink sink) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   CreateSinkRequest request =
    *       CreateSinkRequest.newBuilder()
-   *           .setParent(LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setSink(LogSink.newBuilder().build())
    *           .setUniqueWriterIdentity(true)
    *           .build();
@@ -1557,7 +1545,7 @@ public final LogSink createSink(CreateSinkRequest request) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   CreateSinkRequest request =
    *       CreateSinkRequest.newBuilder()
-   *           .setParent(LogSinkName.ofProjectSinkName("[PROJECT]", "[SINK]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setSink(LogSink.newBuilder().build())
    *           .setUniqueWriterIdentity(true)
    *           .build();
@@ -2027,8 +2015,7 @@ public final ListExclusionsPagedResponse listExclusions(ProjectName parent) {
    *
    * 
{@code
    * try (ConfigClient configClient = ConfigClient.create()) {
-   *   String parent =
-   *       LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString();
+   *   String parent = ProjectName.of("[PROJECT]").toString();
    *   for (LogExclusion element : configClient.listExclusions(parent).iterateAll()) {
    *     // doThingsWith(element);
    *   }
@@ -2055,8 +2042,7 @@ public final ListExclusionsPagedResponse listExclusions(String parent) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListExclusionsRequest request =
    *       ListExclusionsRequest.newBuilder()
-   *           .setParent(
-   *               LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -2083,8 +2069,7 @@ public final ListExclusionsPagedResponse listExclusions(ListExclusionsRequest re
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListExclusionsRequest request =
    *       ListExclusionsRequest.newBuilder()
-   *           .setParent(
-   *               LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -2112,8 +2097,7 @@ public final ListExclusionsPagedResponse listExclusions(ListExclusionsRequest re
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   ListExclusionsRequest request =
    *       ListExclusionsRequest.newBuilder()
-   *           .setParent(
-   *               LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageToken("pageToken873572522")
    *           .setPageSize(883849137)
    *           .build();
@@ -2374,8 +2358,7 @@ public final LogExclusion createExclusion(ProjectName parent, LogExclusion exclu
    *
    * 
{@code
    * try (ConfigClient configClient = ConfigClient.create()) {
-   *   String parent =
-   *       LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString();
+   *   String parent = ProjectName.of("[PROJECT]").toString();
    *   LogExclusion exclusion = LogExclusion.newBuilder().build();
    *   LogExclusion response = configClient.createExclusion(parent, exclusion);
    * }
@@ -2406,8 +2389,7 @@ public final LogExclusion createExclusion(String parent, LogExclusion exclusion)
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   CreateExclusionRequest request =
    *       CreateExclusionRequest.newBuilder()
-   *           .setParent(
-   *               LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setExclusion(LogExclusion.newBuilder().build())
    *           .build();
    *   LogExclusion response = configClient.createExclusion(request);
@@ -2432,8 +2414,7 @@ public final LogExclusion createExclusion(CreateExclusionRequest request) {
    * try (ConfigClient configClient = ConfigClient.create()) {
    *   CreateExclusionRequest request =
    *       CreateExclusionRequest.newBuilder()
-   *           .setParent(
-   *               LogExclusionName.ofProjectExclusionName("[PROJECT]", "[EXCLUSION]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setExclusion(LogExclusion.newBuilder().build())
    *           .build();
    *   ApiFuture future = configClient.createExclusionCallable().futureCall(request);
diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/LoggingClient.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/LoggingClient.java
index 759c5d2c8..01da1d3ed 100644
--- a/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/LoggingClient.java
+++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/LoggingClient.java
@@ -848,7 +848,7 @@ public final ListLogsPagedResponse listLogs(ProjectName parent) {
    *
    * 
{@code
    * try (LoggingClient loggingClient = LoggingClient.create()) {
-   *   String parent = LogName.ofProjectLogName("[PROJECT]", "[LOG]").toString();
+   *   String parent = ProjectName.of("[PROJECT]").toString();
    *   for (String element : loggingClient.listLogs(parent).iterateAll()) {
    *     // doThingsWith(element);
    *   }
@@ -876,7 +876,7 @@ public final ListLogsPagedResponse listLogs(String parent) {
    * try (LoggingClient loggingClient = LoggingClient.create()) {
    *   ListLogsRequest request =
    *       ListLogsRequest.newBuilder()
-   *           .setParent(LogName.ofProjectLogName("[PROJECT]", "[LOG]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageSize(883849137)
    *           .setPageToken("pageToken873572522")
    *           .addAllResourceNames(new ArrayList())
@@ -905,7 +905,7 @@ public final ListLogsPagedResponse listLogs(ListLogsRequest request) {
    * try (LoggingClient loggingClient = LoggingClient.create()) {
    *   ListLogsRequest request =
    *       ListLogsRequest.newBuilder()
-   *           .setParent(LogName.ofProjectLogName("[PROJECT]", "[LOG]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageSize(883849137)
    *           .setPageToken("pageToken873572522")
    *           .addAllResourceNames(new ArrayList())
@@ -933,7 +933,7 @@ public final UnaryCallable listLogsPaged
    * try (LoggingClient loggingClient = LoggingClient.create()) {
    *   ListLogsRequest request =
    *       ListLogsRequest.newBuilder()
-   *           .setParent(LogName.ofProjectLogName("[PROJECT]", "[LOG]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setPageSize(883849137)
    *           .setPageToken("pageToken873572522")
    *           .addAllResourceNames(new ArrayList())
diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/MetricsClient.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/MetricsClient.java
index e1fdf4365..15bec7571 100644
--- a/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/MetricsClient.java
+++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/v2/MetricsClient.java
@@ -423,7 +423,7 @@ public final LogMetric createLogMetric(ProjectName parent, LogMetric metric) {
    *
    * 
{@code
    * try (MetricsClient metricsClient = MetricsClient.create()) {
-   *   String parent = LogMetricName.of("[PROJECT]", "[METRIC]").toString();
+   *   String parent = ProjectName.of("[PROJECT]").toString();
    *   LogMetric metric = LogMetric.newBuilder().build();
    *   LogMetric response = metricsClient.createLogMetric(parent, metric);
    * }
@@ -452,7 +452,7 @@ public final LogMetric createLogMetric(String parent, LogMetric metric) {
    * try (MetricsClient metricsClient = MetricsClient.create()) {
    *   CreateLogMetricRequest request =
    *       CreateLogMetricRequest.newBuilder()
-   *           .setParent(LogMetricName.of("[PROJECT]", "[METRIC]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setMetric(LogMetric.newBuilder().build())
    *           .build();
    *   LogMetric response = metricsClient.createLogMetric(request);
@@ -476,7 +476,7 @@ public final LogMetric createLogMetric(CreateLogMetricRequest request) {
    * try (MetricsClient metricsClient = MetricsClient.create()) {
    *   CreateLogMetricRequest request =
    *       CreateLogMetricRequest.newBuilder()
-   *           .setParent(LogMetricName.of("[PROJECT]", "[METRIC]").toString())
+   *           .setParent(ProjectName.of("[PROJECT]").toString())
    *           .setMetric(LogMetric.newBuilder().build())
    *           .build();
    *   ApiFuture future = metricsClient.createLogMetricCallable().futureCall(request);
diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java
new file mode 100644
index 000000000..72c91236a
--- /dev/null
+++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.threeten.bp.Duration;
+
+public class ContextTest {
+
+  private static final HttpRequest.RequestMethod REQUEST_METHOD = HttpRequest.RequestMethod.GET;
+  private static final String REQUEST_URL = "https://test.domain?arg=val";
+  private static final String CLIENT_IP = "123.123.123.123";
+  private static final String SERVER_IP = "123.321.321.321";
+  private static final String REQUEST_REFERER = "Referer: https://referer.test.domain";
+  // DO NOT use dash in trace and span id because W3C traceparent format uses dash as a delimieter
+  private static final String TEST_TRACE_ID = "test_trace_id";
+  private static final String TEST_SPAN_ID = "test_span_id";
+
+  private static final HttpRequest REQUEST =
+      HttpRequest.newBuilder()
+          .setRequestMethod(REQUEST_METHOD)
+          .setRequestUrl(REQUEST_URL)
+          .setRequestSize(101L)
+          .setStatus(200)
+          .setResponseSize(202L)
+          .setUserAgent("Test User Agent")
+          .setRemoteIp(CLIENT_IP)
+          .setServerIp(SERVER_IP)
+          .setReferer(REQUEST_REFERER)
+          .setCacheLookup(true)
+          .setCacheHit(false)
+          .setCacheValidatedWithOriginServer(true)
+          .setCacheFillBytes(303L)
+          .setLatency(Duration.ofSeconds(123, 456))
+          .build();
+  private static final HttpRequest PARTIAL_REQUEST =
+      HttpRequest.newBuilder()
+          .setRequestMethod(REQUEST_METHOD)
+          .setRequestUrl(REQUEST_URL)
+          .setRemoteIp(CLIENT_IP)
+          .setServerIp(SERVER_IP)
+          .setReferer(REQUEST_REFERER)
+          .build();
+  private static final Context TEST_CONTEXT =
+      Context.newBuilder()
+          .setRequest(PARTIAL_REQUEST)
+          .setTraceId(TEST_TRACE_ID)
+          .setSpanId(TEST_SPAN_ID)
+          .build();
+
+  @Test
+  public void testCompareContexts() {
+    Context context1 =
+        Context.newBuilder()
+            .setRequest(REQUEST)
+            .setTraceId(TEST_TRACE_ID)
+            .setSpanId(TEST_SPAN_ID)
+            .build();
+    Context context2 =
+        Context.newBuilder()
+            .setRequestUrl(REQUEST_URL)
+            .setRequestMethod(REQUEST_METHOD)
+            .setReferer(REQUEST_REFERER)
+            .setRemoteIp(CLIENT_IP)
+            .setServerIp(SERVER_IP)
+            .setTraceId(TEST_TRACE_ID)
+            .setSpanId(TEST_SPAN_ID)
+            .build();
+
+    assertNotEquals(TEST_CONTEXT, context1);
+    assertFalse(TEST_CONTEXT.hashCode() == context1.hashCode());
+    assertTrue(TEST_CONTEXT.equals(context2));
+    assertTrue(TEST_CONTEXT.hashCode() == context2.hashCode());
+  }
+
+  @Test
+  public void testContextBuilder() {
+    Context emptyContext = Context.newBuilder().build();
+    Context anotherContext = TEST_CONTEXT.toBuilder().build();
+
+    assertEquals(PARTIAL_REQUEST, TEST_CONTEXT.getHttpRequest());
+    assertEquals(TEST_TRACE_ID, TEST_CONTEXT.getTraceId());
+    assertEquals(TEST_SPAN_ID, TEST_CONTEXT.getSpanId());
+    assertNull(emptyContext.getHttpRequest());
+    assertNull(emptyContext.getTraceId());
+    assertNull(emptyContext.getSpanId());
+    assertEquals(TEST_CONTEXT, anotherContext);
+  }
+
+  @Test
+  public void testParsingCloudTraceContext() {
+    final String X_CLOUD_TRACE_NO_TRACE = "/SPAN_ID;o=TRACE_TRUE";
+    final String X_CLOUD_TRACE_ONLY = TEST_TRACE_ID;
+    final String X_CLOUD_TRACE_WITH_SPAN = TEST_TRACE_ID + "/" + TEST_SPAN_ID;
+    final String X_CLOUD_TRACE_FULL = TEST_TRACE_ID + "/" + TEST_SPAN_ID + ";o=TRACE_TRUE";
+
+    Context.Builder builder = Context.newBuilder();
+
+    builder.loadCloudTraceContext(null);
+    assertTraceAndSpan(builder.build(), null, null);
+    builder.loadCloudTraceContext("");
+    assertTraceAndSpan(builder.build(), null, null);
+    builder.loadCloudTraceContext(X_CLOUD_TRACE_NO_TRACE);
+    assertTraceAndSpan(builder.build(), null, null);
+    builder.loadCloudTraceContext(X_CLOUD_TRACE_ONLY);
+    assertTraceAndSpan(builder.build(), TEST_TRACE_ID, null);
+    builder.loadCloudTraceContext(X_CLOUD_TRACE_WITH_SPAN);
+    assertTraceAndSpan(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID);
+    builder.loadCloudTraceContext(X_CLOUD_TRACE_FULL);
+    assertTraceAndSpan(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID);
+  }
+
+  @Test
+  public void testParsingW3CTraceParent() {
+    final String TRACEPARENT_NO_TRACE = "00--SPAN_ID-FLAGS";
+    final String TRACEPARENT_TRACE_ONLY = "00-" + TEST_TRACE_ID + "--SPAN_ID-FLAGS";
+    final String TRACEPARENT_TRACE_FULL = "00-" + TEST_TRACE_ID + "-" + TEST_SPAN_ID + "-FLAGS";
+
+    Context.Builder builder = Context.newBuilder();
+
+    builder.loadW3CTraceParentContext(null);
+    assertTraceAndSpan(builder.build(), null, null);
+    builder.loadW3CTraceParentContext(TRACEPARENT_NO_TRACE);
+    assertTraceAndSpan(builder.build(), null, null);
+    builder.loadW3CTraceParentContext(TRACEPARENT_TRACE_ONLY);
+    assertTraceAndSpan(builder.build(), TEST_TRACE_ID, null);
+    builder.loadW3CTraceParentContext(TRACEPARENT_TRACE_FULL);
+    assertTraceAndSpan(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testEmptyW3CTraceParent() {
+    Context.Builder builder = Context.newBuilder();
+    builder.loadW3CTraceParentContext("");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testInvalidFormatW3CTraceParent() {
+    Context.Builder builder = Context.newBuilder();
+    builder.loadW3CTraceParentContext("TRACE_ID/SPAN_ID;o=TRACE_TRUE");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testInvalidFormatW3CTraceParent1Dash() {
+    Context.Builder builder = Context.newBuilder();
+    builder.loadW3CTraceParentContext("00-TRACE_ID");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testInvalidFormatW3CTraceParentWithoutFlag() {
+    Context.Builder builder = Context.newBuilder();
+    builder.loadW3CTraceParentContext("00-TRACE_ID-SPAN_ID-");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testInvalidVersionW3CTraceParent() {
+    Context.Builder builder = Context.newBuilder();
+    builder.loadW3CTraceParentContext("01-TRACE_ID-SPAN_ID-FLAGS");
+  }
+
+  private void assertTraceAndSpan(Context context, String expectedTraceId, String expectedSpanId) {
+    assertEquals(context.getTraceId(), expectedTraceId);
+    assertEquals(context.getSpanId(), expectedSpanId);
+  }
+}
diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/HttpRequestTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/HttpRequestTest.java
index bfcc2f86a..f5934f1ef 100644
--- a/google-cloud-logging/src/test/java/com/google/cloud/logging/HttpRequestTest.java
+++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/HttpRequestTest.java
@@ -92,6 +92,7 @@ public void testBuilderDefaultValues() {
     assertFalse(httpRequest.cacheHit());
     assertFalse(httpRequest.cacheValidatedWithOriginServer());
     assertNull(httpRequest.getCacheFillBytes());
+    assertEquals(httpRequest, HttpRequest.EMPTY);
   }
 
   @Test
diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/v2/ConfigClientTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/v2/ConfigClientTest.java
index 7ef61db2b..0cb699db3 100644
--- a/google-cloud-logging/src/test/java/com/google/cloud/logging/v2/ConfigClientTest.java
+++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/v2/ConfigClientTest.java
@@ -427,9 +427,7 @@ public void createBucketTest() throws Exception {
 
     CreateBucketRequest request =
         CreateBucketRequest.newBuilder()
-            .setParent(
-                LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-                    .toString())
+            .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
             .setBucketId("bucketId-1603305307")
             .setBucket(LogBucket.newBuilder().build())
             .build();
@@ -458,9 +456,7 @@ public void createBucketExceptionTest() throws Exception {
     try {
       CreateBucketRequest request =
           CreateBucketRequest.newBuilder()
-              .setParent(
-                  LogBucketName.ofProjectLocationBucketName("[PROJECT]", "[LOCATION]", "[BUCKET]")
-                      .toString())
+              .setParent(LocationName.of("[PROJECT]", "[LOCATION]").toString())
               .setBucketId("bucketId-1603305307")
               .setBucket(LogBucket.newBuilder().build())
               .build();
diff --git a/grpc-google-cloud-logging-v2/pom.xml b/grpc-google-cloud-logging-v2/pom.xml
index dd049b0d8..2f63cbbdb 100644
--- a/grpc-google-cloud-logging-v2/pom.xml
+++ b/grpc-google-cloud-logging-v2/pom.xml
@@ -4,13 +4,13 @@
   4.0.0
   com.google.api.grpc
   grpc-google-cloud-logging-v2
-  0.93.0
+  0.94.0
   grpc-google-cloud-logging-v2
   GRPC library for grpc-google-cloud-logging-v2
   
     com.google.cloud
     google-cloud-logging-parent
-    3.4.0
+    3.5.0
   
   
     
diff --git a/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/ConfigServiceV2Grpc.java b/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/ConfigServiceV2Grpc.java
index 5869ab967..f7a6f8d08 100644
--- a/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/ConfigServiceV2Grpc.java
+++ b/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/ConfigServiceV2Grpc.java
@@ -27,6 +27,7 @@
 @javax.annotation.Generated(
     value = "by gRPC proto compiler",
     comments = "Source: google/logging/v2/logging_config.proto")
+@io.grpc.stub.annotations.GrpcGenerated
 public final class ConfigServiceV2Grpc {
 
   private ConfigServiceV2Grpc() {}
diff --git a/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/LoggingServiceV2Grpc.java b/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/LoggingServiceV2Grpc.java
index 573e0544e..e84afbaaf 100644
--- a/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/LoggingServiceV2Grpc.java
+++ b/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/LoggingServiceV2Grpc.java
@@ -27,6 +27,7 @@
 @javax.annotation.Generated(
     value = "by gRPC proto compiler",
     comments = "Source: google/logging/v2/logging.proto")
+@io.grpc.stub.annotations.GrpcGenerated
 public final class LoggingServiceV2Grpc {
 
   private LoggingServiceV2Grpc() {}
diff --git a/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/MetricsServiceV2Grpc.java b/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/MetricsServiceV2Grpc.java
index e700fac26..d6b9a75ca 100644
--- a/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/MetricsServiceV2Grpc.java
+++ b/grpc-google-cloud-logging-v2/src/main/java/com/google/logging/v2/MetricsServiceV2Grpc.java
@@ -27,6 +27,7 @@
 @javax.annotation.Generated(
     value = "by gRPC proto compiler",
     comments = "Source: google/logging/v2/logging_metrics.proto")
+@io.grpc.stub.annotations.GrpcGenerated
 public final class MetricsServiceV2Grpc {
 
   private MetricsServiceV2Grpc() {}
diff --git a/pom.xml b/pom.xml
index b4703ae3b..b1f222d88 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
   com.google.cloud
   google-cloud-logging-parent
   pom
-  3.4.0
+  3.5.0
   Google Cloud Logging Parent
   https://github.com/googleapis/java-logging
   
@@ -14,7 +14,7 @@
   
     com.google.cloud
     google-cloud-shared-config
-    1.2.0
+    1.2.2
   
 
   
@@ -61,23 +61,23 @@
       
         com.google.api.grpc
         proto-google-cloud-logging-v2
-        0.93.0
+        0.94.0
       
       
         com.google.api.grpc
         grpc-google-cloud-logging-v2
-        0.93.0
+        0.94.0
       
       
         com.google.cloud
         google-cloud-logging
-        3.4.0
+        3.5.0
       
 
       
         com.google.cloud
         google-cloud-shared-dependencies
-        2.4.0
+        2.5.0
         pom
         import
       
diff --git a/proto-google-cloud-logging-v2/pom.xml b/proto-google-cloud-logging-v2/pom.xml
index 7795577c2..c102ec975 100644
--- a/proto-google-cloud-logging-v2/pom.xml
+++ b/proto-google-cloud-logging-v2/pom.xml
@@ -4,13 +4,13 @@
   4.0.0
   com.google.api.grpc
   proto-google-cloud-logging-v2
-  0.93.0
+  0.94.0
   proto-google-cloud-logging-v2
   PROTO library for proto-google-cloud-logging-v2
   
     com.google.cloud
     google-cloud-logging-parent
-    3.4.0
+    3.5.0
   
   
     
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 65391b1ba..b9e0aee02 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -28,7 +28,7 @@
     
       com.google.cloud
       google-cloud-logging
-      3.3.0
+      3.4.0
     
     
 
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 93ed9477b..a49c0a288 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
     
       com.google.cloud
       google-cloud-logging
-      3.4.0
+      3.5.0
     
     
     
diff --git a/versions.txt b/versions.txt
index 9965d995e..54603e50b 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,6 +1,6 @@
 # Format:
 # module:released-version:current-version
 
-google-cloud-logging:3.4.0:3.4.0
-grpc-google-cloud-logging-v2:0.93.0:0.93.0
-proto-google-cloud-logging-v2:0.93.0:0.93.0
+google-cloud-logging:3.5.0:3.5.0
+grpc-google-cloud-logging-v2:0.94.0:0.94.0
+proto-google-cloud-logging-v2:0.94.0:0.94.0