mirror of https://github.com/grpc/grpc-java.git
gcp-o11y: Remove monitored resource detection for logging (#10020)
* removed populating monitored resource to k8s_conatiner by default for logging; Delegating the resource detection to cloud logging library instead (enabled by default) * remove kubernetes resource detection logic from observability
This commit is contained in:
parent
18e274de65
commit
cc6be5f8c6
|
|
@ -90,12 +90,10 @@ public final class GcpObservability implements AutoCloseable {
|
|||
*/
|
||||
public static synchronized GcpObservability grpcInit() throws IOException {
|
||||
if (instance == null) {
|
||||
GlobalLocationTags globalLocationTags = new GlobalLocationTags();
|
||||
ObservabilityConfigImpl observabilityConfig = ObservabilityConfigImpl.getInstance();
|
||||
TraceLoggingHelper traceLoggingHelper = new TraceLoggingHelper(
|
||||
observabilityConfig.getProjectId());
|
||||
Sink sink = new GcpLogSink(observabilityConfig.getProjectId(),
|
||||
globalLocationTags.getLocationTags(), observabilityConfig,
|
||||
Sink sink = new GcpLogSink(observabilityConfig.getProjectId(), observabilityConfig,
|
||||
SERVICES_TO_EXCLUDE, traceLoggingHelper);
|
||||
LogHelper helper = new LogHelper(sink);
|
||||
ConfigFilterHelper configFilterHelper = ConfigFilterHelper.getInstance(observabilityConfig);
|
||||
|
|
|
|||
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 The gRPC 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.grpc.gcp.observability;
|
||||
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.util.Strings;
|
||||
import com.google.auth.http.HttpTransportFactory;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/** A container of all global location tags used for observability. */
|
||||
final class GlobalLocationTags {
|
||||
private static final Logger logger = Logger.getLogger(GlobalLocationTags.class.getName());
|
||||
|
||||
private final Map<String, String> locationTags;
|
||||
|
||||
GlobalLocationTags() {
|
||||
ImmutableMap.Builder<String, String> locationTagsBuilder = ImmutableMap.builder();
|
||||
populate(locationTagsBuilder);
|
||||
locationTags = locationTagsBuilder.buildOrThrow();
|
||||
}
|
||||
|
||||
private static String applyTrim(String value) {
|
||||
if (!Strings.isNullOrEmpty(value)) {
|
||||
value = value.trim();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Map<String, String> getLocationTags() {
|
||||
return locationTags;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void populateFromMetadataServer(ImmutableMap.Builder<String, String> locationTags) {
|
||||
MetadataConfig metadataConfig = new MetadataConfig(new DefaultHttpTransportFactory());
|
||||
metadataConfig.init();
|
||||
locationTags.putAll(metadataConfig.getAllValues());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void populateFromKubernetesValues(ImmutableMap.Builder<String, String> locationTags,
|
||||
String namespaceFile,
|
||||
String hostnameFile, String cgroupFile) {
|
||||
// namespace name: contents of file /var/run/secrets/kubernetes.io/serviceaccount/namespace
|
||||
populateFromFileContents(locationTags, "namespace_name",
|
||||
namespaceFile, GlobalLocationTags::applyTrim);
|
||||
|
||||
// pod_name: hostname i.e. contents of /etc/hostname
|
||||
populateFromFileContents(locationTags, "pod_name", hostnameFile,
|
||||
GlobalLocationTags::applyTrim);
|
||||
|
||||
// container_id: parsed from /proc/self/cgroup . Note: only works for Linux-based containers
|
||||
populateFromFileContents(locationTags, "container_id", cgroupFile,
|
||||
(value) -> getContainerIdFromFileContents(value));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void populateFromFileContents(ImmutableMap.Builder<String, String> locationTags,
|
||||
String key, String filePath, Function<String, String> parser) {
|
||||
String value = parser.apply(readFileContents(filePath));
|
||||
if (value != null) {
|
||||
locationTags.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse from a line such as this.
|
||||
* 1:name=systemd:/kubepods/burstable/podf5143dd2/de67c4419b20924eaa141813
|
||||
*
|
||||
* @param value file contents
|
||||
* @return container-id parsed ("podf5143dd2/de67c4419b20924eaa141813" from the above snippet)
|
||||
*/
|
||||
@VisibleForTesting static String getContainerIdFromFileContents(String value) {
|
||||
if (value != null) {
|
||||
try (Scanner scanner = new Scanner(value)) {
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
String[] tokens = line.split(":");
|
||||
if (tokens.length == 3 && tokens[2].startsWith("/kubepods/burstable/")) {
|
||||
tokens = tokens[2].split("/");
|
||||
if (tokens.length == 5) {
|
||||
return tokens[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String readFileContents(String file) {
|
||||
Path fileName = Paths.get(file);
|
||||
if (Files.isReadable(fileName)) {
|
||||
try {
|
||||
byte[] bytes = Files.readAllBytes(fileName);
|
||||
return new String(bytes, Charsets.US_ASCII);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.FINE, "Reading file:" + file, e);
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.FINE, "File:" + file + " is not readable (or missing?)");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void populate(ImmutableMap.Builder<String, String> locationTags) {
|
||||
populateFromMetadataServer(locationTags);
|
||||
populateFromKubernetesValues(locationTags,
|
||||
"/var/run/secrets/kubernetes.io/serviceaccount/namespace",
|
||||
"/etc/hostname", "/proc/self/cgroup");
|
||||
}
|
||||
|
||||
private static class DefaultHttpTransportFactory implements HttpTransportFactory {
|
||||
|
||||
private static final HttpTransport netHttpTransport = new NetHttpTransport();
|
||||
|
||||
@Override
|
||||
public HttpTransport create() {
|
||||
return netHttpTransport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 The gRPC 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.grpc.gcp.observability;
|
||||
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpHeaders;
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.auth.http.HttpTransportFactory;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/** Class to read Google Metadata Server values. */
|
||||
final class MetadataConfig {
|
||||
private static final Logger logger = Logger.getLogger(MetadataConfig.class.getName());
|
||||
|
||||
private static final int TIMEOUT_MS = 5000;
|
||||
private static final String METADATA_URL = "http://metadata.google.internal/computeMetadata/v1/";
|
||||
private HttpRequestFactory requestFactory;
|
||||
private HttpTransportFactory transportFactory;
|
||||
|
||||
@VisibleForTesting public MetadataConfig(HttpTransportFactory transportFactory) {
|
||||
this.transportFactory = transportFactory;
|
||||
|
||||
}
|
||||
|
||||
void init() {
|
||||
HttpTransport httpTransport = transportFactory.create();
|
||||
requestFactory = httpTransport.createRequestFactory();
|
||||
}
|
||||
|
||||
/** gets all the values from the MDS we need to set in our logging tags. */
|
||||
ImmutableMap<String, String> getAllValues() {
|
||||
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
|
||||
//addValueFor(builder, "instance/hostname", "GCE_INSTANCE_HOSTNAME");
|
||||
addValueFor(builder, "instance/id", "gke_node_id");
|
||||
//addValueFor(builder, "instance/zone", "GCE_INSTANCE_ZONE");
|
||||
addValueFor(builder, "project/project-id", "project_id");
|
||||
addValueFor(builder, "project/numeric-project-id", "project_numeric_id");
|
||||
addValueFor(builder, "instance/attributes/cluster-name", "cluster_name");
|
||||
addValueFor(builder, "instance/attributes/cluster-uid", "cluster_uid");
|
||||
addValueFor(builder, "instance/attributes/cluster-location", "location");
|
||||
try {
|
||||
requestFactory.getTransport().shutdown();
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.FINE, "Calling HttpTransport.shutdown()", e);
|
||||
}
|
||||
return builder.buildOrThrow();
|
||||
}
|
||||
|
||||
void addValueFor(ImmutableMap.Builder<String, String> builder, String attribute, String key) {
|
||||
try {
|
||||
String value = getAttribute(attribute);
|
||||
if (value != null) {
|
||||
builder.put(key, value);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.FINE, "Calling getAttribute('" + attribute + "')", e);
|
||||
}
|
||||
}
|
||||
|
||||
String getAttribute(String attributeName) throws IOException {
|
||||
GenericUrl url = new GenericUrl(METADATA_URL + attributeName);
|
||||
HttpRequest request = requestFactory.buildGetRequest(url);
|
||||
request = request.setReadTimeout(TIMEOUT_MS);
|
||||
request = request.setConnectTimeout(TIMEOUT_MS);
|
||||
request = request.setHeaders(new HttpHeaders().set("Metadata-Flavor", "Google"));
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = request.execute();
|
||||
if (response.getStatusCode() == HttpStatusCodes.STATUS_CODE_OK) {
|
||||
InputStream stream = response.getContent();
|
||||
if (stream != null) {
|
||||
byte[] bytes = new byte[stream.available()];
|
||||
stream.read(bytes);
|
||||
return new String(bytes, response.getContentCharset());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (response != null) {
|
||||
response.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import com.google.api.gax.batching.BatchingSettings;
|
||||
import com.google.api.gax.batching.FlowController;
|
||||
import com.google.cloud.MonitoredResource;
|
||||
import com.google.cloud.logging.LogEntry;
|
||||
import com.google.cloud.logging.Logging;
|
||||
import com.google.cloud.logging.LoggingOptions;
|
||||
|
|
@ -30,7 +29,6 @@ import com.google.cloud.logging.v2.stub.LoggingServiceV2StubSettings;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.protobuf.util.JsonFormat;
|
||||
import io.grpc.Internal;
|
||||
import io.grpc.gcp.observability.ObservabilityConfig;
|
||||
|
|
@ -42,8 +40,6 @@ import java.time.Instant;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.threeten.bp.Duration;
|
||||
|
|
@ -58,13 +54,8 @@ public class GcpLogSink implements Sink {
|
|||
private static final String DEFAULT_LOG_NAME =
|
||||
"microservices.googleapis.com%2Fobservability%2Fgrpc";
|
||||
private static final Severity DEFAULT_LOG_LEVEL = Severity.DEBUG;
|
||||
private static final String K8S_MONITORED_RESOURCE_TYPE = "k8s_container";
|
||||
private static final Set<String> kubernetesResourceLabelSet
|
||||
= ImmutableSet.of("project_id", "location", "cluster_name", "namespace_name",
|
||||
"pod_name", "container_name");
|
||||
private final String projectId;
|
||||
private final Map<String, String> customTags;
|
||||
private final MonitoredResource kubernetesResource;
|
||||
/** Lazily initialize cloud logging client to avoid circular initialization. Because cloud
|
||||
* logging APIs also uses gRPC. */
|
||||
private volatile Logging gcpLoggingClient;
|
||||
|
|
@ -75,10 +66,10 @@ public class GcpLogSink implements Sink {
|
|||
|
||||
|
||||
@VisibleForTesting
|
||||
GcpLogSink(Logging loggingClient, String projectId, Map<String, String> locationTags,
|
||||
GcpLogSink(Logging loggingClient, String projectId,
|
||||
ObservabilityConfig config, Collection<String> servicesToExclude,
|
||||
TraceLoggingHelper traceLoggingHelper) {
|
||||
this(projectId, locationTags, config, servicesToExclude, traceLoggingHelper);
|
||||
this(projectId, config, servicesToExclude, traceLoggingHelper);
|
||||
this.gcpLoggingClient = loggingClient;
|
||||
}
|
||||
|
||||
|
|
@ -88,12 +79,11 @@ public class GcpLogSink implements Sink {
|
|||
* @param projectId GCP project id to write logs
|
||||
* @param servicesToExclude service names for which log entries should not be generated
|
||||
*/
|
||||
public GcpLogSink(String projectId, Map<String, String> locationTags,
|
||||
public GcpLogSink(String projectId,
|
||||
ObservabilityConfig config, Collection<String> servicesToExclude,
|
||||
TraceLoggingHelper traceLoggingHelper) {
|
||||
this.projectId = projectId;
|
||||
this.customTags = getCustomTags(config.getCustomTags(), locationTags, projectId);
|
||||
this.kubernetesResource = getResource(locationTags);
|
||||
this.customTags = getCustomTags(config.getCustomTags());
|
||||
this.servicesToExclude = checkNotNull(servicesToExclude, "servicesToExclude");
|
||||
this.isTraceEnabled = config.isEnableCloudTracing();
|
||||
this.traceLoggingHelper = traceLoggingHelper;
|
||||
|
|
@ -126,7 +116,6 @@ public class GcpLogSink implements Sink {
|
|||
LogEntry.newBuilder(JsonPayload.of(logProtoMap))
|
||||
.setSeverity(DEFAULT_LOG_LEVEL)
|
||||
.setLogName(DEFAULT_LOG_NAME)
|
||||
.setResource(kubernetesResource)
|
||||
.setTimestamp(Instant.now());
|
||||
|
||||
if (!customTags.isEmpty()) {
|
||||
|
|
@ -178,34 +167,14 @@ public class GcpLogSink implements Sink {
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static Map<String, String> getCustomTags(Map<String, String> customTags,
|
||||
Map<String, String> locationTags, String projectId) {
|
||||
static Map<String, String> getCustomTags(Map<String, String> customTags) {
|
||||
ImmutableMap.Builder<String, String> tagsBuilder = ImmutableMap.builder();
|
||||
String sourceProjectId = locationTags.get("project_id");
|
||||
if (!Strings.isNullOrEmpty(projectId)
|
||||
&& !Strings.isNullOrEmpty(sourceProjectId)
|
||||
&& !Objects.equals(sourceProjectId, projectId)) {
|
||||
tagsBuilder.put("source_project_id", sourceProjectId);
|
||||
}
|
||||
if (customTags != null) {
|
||||
tagsBuilder.putAll(customTags);
|
||||
}
|
||||
return tagsBuilder.buildOrThrow();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static MonitoredResource getResource(Map<String, String> resourceTags) {
|
||||
MonitoredResource.Builder builder = MonitoredResource.newBuilder(K8S_MONITORED_RESOURCE_TYPE);
|
||||
if ((resourceTags != null) && !resourceTags.isEmpty()) {
|
||||
for (Map.Entry<String, String> entry : resourceTags.entrySet()) {
|
||||
String resourceKey = entry.getKey();
|
||||
if (kubernetesResourceLabelSet.contains(resourceKey)) {
|
||||
builder.addLabel(resourceKey, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> protoToMapConverter(GrpcLogRecord logProto)
|
||||
|
|
|
|||
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 The gRPC 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.grpc.gcp.observability;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.Files;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class GlobalLocationTagsTest {
|
||||
private static String FILE_CONTENTS =
|
||||
"12:perf_event:/kubepods/burstable/podc43b6442-0725-4fb8-bb1c-d17f5122155c/"
|
||||
+ "fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7\n"
|
||||
+ "11:freezer:/kubepods/burstable/podc43b6442-0725-4fb8-bb1c-d17f5122155c/"
|
||||
+ "fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7\n"
|
||||
+ "2:rdma:/\n"
|
||||
+ "1:name=systemd:/kubepods/burstable/podc43b6442-0725-4fb8-bb1c-d17f5122155c/"
|
||||
+ "fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7\n"
|
||||
+ "0::/system.slice/containerd.service\n";
|
||||
|
||||
private static String FILE_CONTENTS_LAST_LINE =
|
||||
"0::/system.slice/containerd.service\n"
|
||||
+ "6442-0725-4fb8-bb1c-d17f5122155cslslsl/fe61ca6482b58f4a9831d08d6ea15db25f\n"
|
||||
+ "\n"
|
||||
+ "12:perf_event:/kubepods/burstable/podc43b6442-0725-4fb8-bb1c-d17f5122155c/e19a54df\n";
|
||||
|
||||
@Rule public TemporaryFolder namespaceFolder = new TemporaryFolder();
|
||||
@Rule public TemporaryFolder hostnameFolder = new TemporaryFolder();
|
||||
@Rule public TemporaryFolder cgroupFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void testContainerIdParsing_lastLine() {
|
||||
String containerId = GlobalLocationTags.getContainerIdFromFileContents(FILE_CONTENTS_LAST_LINE);
|
||||
assertThat(containerId).isEqualTo("e19a54df");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainerIdParsing_fewerFields_notFound() {
|
||||
String containerId = GlobalLocationTags.getContainerIdFromFileContents(
|
||||
"12:/kubepods/burstable/podc43b6442-0725-4fb8-bb1c-d17f5122155c/"
|
||||
+ "fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7\n");
|
||||
assertThat(containerId).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainerIdParsing_fewerPaths_notFound() {
|
||||
String containerId = GlobalLocationTags.getContainerIdFromFileContents(
|
||||
"12:xdf:/kubepods/podc43b6442-0725-4fb8-bb1c-d17f5122155c/"
|
||||
+ "fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7\n");
|
||||
assertThat(containerId).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPopulateKubernetesValues() throws IOException {
|
||||
File namespaceFile = namespaceFolder.newFile();
|
||||
File hostnameFile = hostnameFolder.newFile();
|
||||
File cgroupFile = cgroupFolder.newFile();
|
||||
|
||||
Files.write("test-namespace1".getBytes(StandardCharsets.UTF_8), namespaceFile);
|
||||
Files.write("test-hostname2\n".getBytes(StandardCharsets.UTF_8), hostnameFile);
|
||||
Files.write(FILE_CONTENTS.getBytes(StandardCharsets.UTF_8), cgroupFile);
|
||||
|
||||
ImmutableMap.Builder<String, String> locationTags = ImmutableMap.builder();
|
||||
GlobalLocationTags.populateFromKubernetesValues(locationTags, namespaceFile.getAbsolutePath(),
|
||||
hostnameFile.getAbsolutePath(), cgroupFile.getAbsolutePath());
|
||||
assertThat(locationTags.buildOrThrow()).containsExactly("container_id",
|
||||
"fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7", "namespace_name",
|
||||
"test-namespace1", "pod_name", "test-hostname2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonKubernetesInstanceValues() throws IOException {
|
||||
String namespaceFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace";
|
||||
File hostnameFile = hostnameFolder.newFile();
|
||||
File cgroupFile = cgroupFolder.newFile();
|
||||
|
||||
Files.write("test-hostname2\n".getBytes(StandardCharsets.UTF_8), hostnameFile);
|
||||
Files.write(FILE_CONTENTS.getBytes(StandardCharsets.UTF_8), cgroupFile);
|
||||
|
||||
ImmutableMap.Builder<String, String> locationTags = ImmutableMap.builder();
|
||||
GlobalLocationTags.populateFromKubernetesValues(locationTags,
|
||||
namespaceFilePath, hostnameFile.getAbsolutePath(), cgroupFile.getAbsolutePath());
|
||||
assertThat(locationTags.buildOrThrow()).containsExactly("container_id",
|
||||
"fe61ca6482b58f4a9831d08d6ea15db25f9fd19b4be19a54df8c6c0eab8742b7",
|
||||
"pod_name", "test-hostname2");
|
||||
}
|
||||
}
|
||||
|
|
@ -63,12 +63,6 @@ public class LoggingTest {
|
|||
public static final GrpcCleanupRule cleanupRule = new GrpcCleanupRule();
|
||||
|
||||
private static final String PROJECT_ID = "PROJECT";
|
||||
private static final ImmutableMap<String, String> LOCATION_TAGS = ImmutableMap.of(
|
||||
"project_id", "PROJECT",
|
||||
"location", "us-central1-c",
|
||||
"cluster_name", "grpc-observability-cluster",
|
||||
"namespace_name", "default" ,
|
||||
"pod_name", "app1-6c7c58f897-n92c5");
|
||||
private static final ImmutableMap<String, String> CUSTOM_TAGS = ImmutableMap.of(
|
||||
"KEY1", "Value1",
|
||||
"KEY2", "VALUE2");
|
||||
|
|
@ -119,7 +113,7 @@ public class LoggingTest {
|
|||
when(config.getCustomTags()).thenReturn(CUSTOM_TAGS);
|
||||
Sink sink =
|
||||
new GcpLogSink(
|
||||
PROJECT_ID, LOCATION_TAGS, config, Collections.emptySet(),
|
||||
PROJECT_ID, config, Collections.emptySet(),
|
||||
mock(TraceLoggingHelper.class));
|
||||
LogHelper spyLogHelper = spy(new LogHelper(sink));
|
||||
ConfigFilterHelper mockFilterHelper = mock(ConfigFilterHelper.class);
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 The gRPC 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.grpc.gcp.observability;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.api.client.testing.http.MockHttpTransport;
|
||||
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
|
||||
import com.google.auth.http.HttpTransportFactory;
|
||||
import java.io.IOException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class MetadataConfigTest {
|
||||
|
||||
@Mock HttpTransportFactory httpTransportFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAttribute() throws IOException {
|
||||
MockHttpTransport.Builder builder = new MockHttpTransport.Builder();
|
||||
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
|
||||
response.setContent("foo");
|
||||
builder.setLowLevelHttpResponse(response);
|
||||
MockHttpTransport httpTransport = builder.build();
|
||||
when(httpTransportFactory.create()).thenReturn(httpTransport);
|
||||
MetadataConfig metadataConfig = new MetadataConfig(httpTransportFactory);
|
||||
metadataConfig.init();
|
||||
String val = metadataConfig.getAttribute("instance/attributes/cluster-name");
|
||||
assertThat(val).isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
|||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.cloud.MonitoredResource;
|
||||
import com.google.cloud.logging.LogEntry;
|
||||
import com.google.cloud.logging.Logging;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
|
@ -64,12 +63,6 @@ public class GcpLogSinkTest {
|
|||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
private static final ImmutableMap<String, String> LOCATION_TAGS =
|
||||
ImmutableMap.of("project_id", "PROJECT",
|
||||
"location", "us-central1-c",
|
||||
"cluster_name", "grpc-observability-cluster",
|
||||
"namespace_name", "default" ,
|
||||
"pod_name", "app1-6c7c58f897-n92c5");
|
||||
private static final ImmutableMap<String, String> CUSTOM_TAGS =
|
||||
ImmutableMap.of("KEY1", "Value1",
|
||||
"KEY2", "VALUE2");
|
||||
|
|
@ -119,7 +112,7 @@ public class GcpLogSinkTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void verifyWrite() throws Exception {
|
||||
when(mockConfig.getCustomTags()).thenReturn(CUSTOM_TAGS);
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), new TraceLoggingHelper(DEST_PROJECT_NAME));
|
||||
sink.write(LOG_PROTO, null);
|
||||
|
||||
|
|
@ -138,9 +131,8 @@ public class GcpLogSinkTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void verifyWriteWithTags() {
|
||||
when(mockConfig.getCustomTags()).thenReturn(CUSTOM_TAGS);
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), new TraceLoggingHelper(DEST_PROJECT_NAME));
|
||||
MonitoredResource expectedMonitoredResource = GcpLogSink.getResource(LOCATION_TAGS);
|
||||
sink.write(LOG_PROTO, null);
|
||||
|
||||
ArgumentCaptor<Collection<LogEntry>> logEntrySetCaptor = ArgumentCaptor.forClass(
|
||||
|
|
@ -149,7 +141,6 @@ public class GcpLogSinkTest {
|
|||
System.out.println(logEntrySetCaptor.getValue());
|
||||
for (Iterator<LogEntry> it = logEntrySetCaptor.getValue().iterator(); it.hasNext(); ) {
|
||||
LogEntry entry = it.next();
|
||||
assertThat(entry.getResource()).isEqualTo(expectedMonitoredResource);
|
||||
assertThat(entry.getLabels()).isEqualTo(CUSTOM_TAGS);
|
||||
assertThat(entry.getPayload().getData()).isEqualTo(EXPECTED_STRUCT_LOG_PROTO);
|
||||
assertThat(entry.getLogName()).isEqualTo(EXPECTED_LOG_NAME);
|
||||
|
|
@ -163,7 +154,7 @@ public class GcpLogSinkTest {
|
|||
Map<String, String> emptyCustomTags = null;
|
||||
when(mockConfig.getCustomTags()).thenReturn(emptyCustomTags);
|
||||
Map<String, String> expectedEmptyLabels = new HashMap<>();
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), new TraceLoggingHelper(DEST_PROJECT_NAME));
|
||||
sink.write(LOG_PROTO, null);
|
||||
|
||||
|
|
@ -183,9 +174,9 @@ public class GcpLogSinkTest {
|
|||
Map<String, String> emptyCustomTags = null;
|
||||
when(mockConfig.getCustomTags()).thenReturn(emptyCustomTags);
|
||||
String projectId = "PROJECT";
|
||||
Map<String, String> expectedLabels = GcpLogSink.getCustomTags(emptyCustomTags, LOCATION_TAGS,
|
||||
projectId);
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, projectId, LOCATION_TAGS,
|
||||
Map<String, String> expectedLabels = GcpLogSink.getCustomTags(emptyCustomTags
|
||||
);
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, projectId,
|
||||
mockConfig, Collections.emptySet(), new TraceLoggingHelper(DEST_PROJECT_NAME));
|
||||
sink.write(LOG_PROTO, null);
|
||||
|
||||
|
|
@ -201,7 +192,7 @@ public class GcpLogSinkTest {
|
|||
|
||||
@Test
|
||||
public void verifyClose() throws Exception {
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), new TraceLoggingHelper(DEST_PROJECT_NAME));
|
||||
sink.write(LOG_PROTO, null);
|
||||
verify(mockLogging, times(1)).write(anyIterable());
|
||||
|
|
@ -212,7 +203,7 @@ public class GcpLogSinkTest {
|
|||
|
||||
@Test
|
||||
public void verifyExclude() throws Exception {
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.singleton("service"), new TraceLoggingHelper(DEST_PROJECT_NAME));
|
||||
mockSink.write(LOG_PROTO, null);
|
||||
verifyNoInteractions(mockLogging);
|
||||
|
|
@ -229,7 +220,7 @@ public class GcpLogSinkTest {
|
|||
|
||||
TraceLoggingHelper traceLoggingHelper = new TraceLoggingHelper(DEST_PROJECT_NAME);
|
||||
when(mockConfig.isEnableCloudTracing()).thenReturn(false);
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), traceLoggingHelper);
|
||||
mockSink.write(LOG_PROTO, validSpanContext);
|
||||
|
||||
|
|
@ -260,7 +251,7 @@ public class GcpLogSinkTest {
|
|||
|
||||
TraceLoggingHelper traceLoggingHelper = new TraceLoggingHelper(DEST_PROJECT_NAME);
|
||||
when(mockConfig.isEnableCloudTracing()).thenReturn(true);
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), traceLoggingHelper);
|
||||
mockSink.write(LOG_PROTO, validSpanContext);
|
||||
|
||||
|
|
@ -284,7 +275,7 @@ public class GcpLogSinkTest {
|
|||
public void verifyTraceDataLogs_withNullSpanContext() throws Exception {
|
||||
TraceLoggingHelper traceLoggingHelper = new TraceLoggingHelper(DEST_PROJECT_NAME);
|
||||
when(mockConfig.isEnableCloudTracing()).thenReturn(true);
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME,
|
||||
mockConfig, Collections.emptySet(), traceLoggingHelper);
|
||||
|
||||
String expectedTrace =
|
||||
|
|
|
|||
Loading…
Reference in New Issue