mirror of https://github.com/grpc/grpc-java.git
gcp-observability: update observability logging proto (#9608)
This commit is contained in:
parent
e16f1436a9
commit
43942623fb
|
|
@ -35,7 +35,6 @@ import io.grpc.gcp.observability.interceptors.InternalLoggingServerInterceptor;
|
|||
import io.grpc.gcp.observability.interceptors.LogHelper;
|
||||
import io.grpc.gcp.observability.logging.GcpLogSink;
|
||||
import io.grpc.gcp.observability.logging.Sink;
|
||||
import io.grpc.internal.TimeProvider;
|
||||
import io.opencensus.common.Duration;
|
||||
import io.opencensus.contrib.grpc.metrics.RpcViewConstants;
|
||||
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
|
||||
|
|
@ -79,8 +78,8 @@ public final class GcpObservability implements AutoCloseable {
|
|||
ObservabilityConfigImpl observabilityConfig = ObservabilityConfigImpl.getInstance();
|
||||
Sink sink = new GcpLogSink(observabilityConfig.getDestinationProjectId(),
|
||||
globalLocationTags.getLocationTags(), observabilityConfig.getCustomTags(),
|
||||
observabilityConfig.getFlushMessageCount(), SERVICES_TO_EXCLUDE);
|
||||
LogHelper helper = new LogHelper(sink, TimeProvider.SYSTEM_TIME_PROVIDER);
|
||||
SERVICES_TO_EXCLUDE);
|
||||
LogHelper helper = new LogHelper(sink);
|
||||
ConfigFilterHelper configFilterHelper = ConfigFilterHelper.factory(observabilityConfig);
|
||||
instance = grpcInit(sink, observabilityConfig,
|
||||
new InternalLoggingChannelInterceptor.FactoryImpl(helper, configFilterHelper),
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ public interface ObservabilityConfig {
|
|||
/** Get destination project ID - where logs will go. */
|
||||
String getDestinationProjectId();
|
||||
|
||||
/** Get message count threshold to flush - flush once message count is reached. */
|
||||
Long getFlushMessageCount();
|
||||
|
||||
/** Get filters set for logging. */
|
||||
List<LogFilter> getLogFilters();
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ final class ObservabilityConfigImpl implements ObservabilityConfig {
|
|||
private boolean enableCloudMonitoring = false;
|
||||
private boolean enableCloudTracing = false;
|
||||
private String destinationProjectId = null;
|
||||
private Long flushMessageCount = null;
|
||||
private List<LogFilter> logFilters;
|
||||
private List<EventType> eventTypes;
|
||||
private Sampler sampler;
|
||||
|
|
@ -87,7 +86,6 @@ final class ObservabilityConfigImpl implements ObservabilityConfig {
|
|||
enableCloudTracing = value;
|
||||
}
|
||||
destinationProjectId = JsonUtil.getString(config, "destination_project_id");
|
||||
flushMessageCount = JsonUtil.getNumberAsLong(config, "flush_message_count");
|
||||
List<?> rawList = JsonUtil.getList(config, "log_filters");
|
||||
if (rawList != null) {
|
||||
List<Map<String, ?>> jsonLogFilters = JsonUtil.checkObjectList(rawList);
|
||||
|
|
@ -102,7 +100,7 @@ final class ObservabilityConfigImpl implements ObservabilityConfig {
|
|||
List<String> jsonEventTypes = JsonUtil.checkStringList(rawList);
|
||||
ImmutableList.Builder<EventType> eventTypesBuilder = new ImmutableList.Builder<>();
|
||||
for (String jsonEventType : jsonEventTypes) {
|
||||
eventTypesBuilder.add(convertEventType(jsonEventType));
|
||||
eventTypesBuilder.add(EventType.valueOf(jsonEventType));
|
||||
}
|
||||
this.eventTypes = eventTypesBuilder.build();
|
||||
}
|
||||
|
|
@ -136,28 +134,6 @@ final class ObservabilityConfigImpl implements ObservabilityConfig {
|
|||
}
|
||||
}
|
||||
|
||||
private EventType convertEventType(String val) {
|
||||
switch (val) {
|
||||
case "GRPC_CALL_UNKNOWN":
|
||||
return EventType.GRPC_CALL_UNKNOWN;
|
||||
case "GRPC_CALL_REQUEST_HEADER":
|
||||
return EventType.GRPC_CALL_REQUEST_HEADER;
|
||||
case "GRPC_CALL_RESPONSE_HEADER":
|
||||
return EventType.GRPC_CALL_RESPONSE_HEADER;
|
||||
case "GRPC_CALL_REQUEST_MESSAGE":
|
||||
return EventType.GRPC_CALL_REQUEST_MESSAGE;
|
||||
case "GRPC_CALL_RESPONSE_MESSAGE":
|
||||
return EventType.GRPC_CALL_RESPONSE_MESSAGE;
|
||||
case "GRPC_CALL_TRAILER":
|
||||
return EventType.GRPC_CALL_TRAILER;
|
||||
case "GRPC_CALL_HALF_CLOSE":
|
||||
return EventType.GRPC_CALL_HALF_CLOSE;
|
||||
case "GRPC_CALL_CANCEL":
|
||||
return EventType.GRPC_CALL_CANCEL;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown event type value:" + val);
|
||||
}
|
||||
}
|
||||
|
||||
private LogFilter parseJsonLogFilter(Map<String, ?> logFilterMap) {
|
||||
return new LogFilter(JsonUtil.getString(logFilterMap, "pattern"),
|
||||
|
|
@ -185,11 +161,6 @@ final class ObservabilityConfigImpl implements ObservabilityConfig {
|
|||
return destinationProjectId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getFlushMessageCount() {
|
||||
return flushMessageCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LogFilter> getLogFilters() {
|
||||
return logFilters;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
CallOptions callOptions, Channel next) {
|
||||
|
||||
final AtomicLong seq = new AtomicLong(1);
|
||||
final String rpcId = UUID.randomUUID().toString();
|
||||
final String callId = UUID.randomUUID().toString();
|
||||
final String authority = next.authority();
|
||||
final String serviceName = method.getServiceName();
|
||||
final String methodName = method.getBareMethodName();
|
||||
|
|
@ -105,15 +105,15 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
|
||||
@Override
|
||||
public void start(Listener<RespT> responseListener, Metadata headers) {
|
||||
// Event: EventType.GRPC_CALL_REQUEST_HEADER
|
||||
// Event: EventType.CLIENT_HEADER
|
||||
// The timeout should reflect the time remaining when the call is started, so compute
|
||||
// remaining time here.
|
||||
final Duration timeout = deadline == null ? null
|
||||
: Durations.fromNanos(deadline.timeRemaining(TimeUnit.NANOSECONDS));
|
||||
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_REQUEST_HEADER)) {
|
||||
if (filterHelper.isEventToBeLogged(EventType.CLIENT_HEADER)) {
|
||||
try {
|
||||
helper.logRequestHeader(
|
||||
helper.logClientHeader(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
|
|
@ -121,8 +121,8 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
timeout,
|
||||
headers,
|
||||
maxHeaderBytes,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
null);
|
||||
} catch (Exception e) {
|
||||
// Catching generic exceptions instead of specific ones for all the events.
|
||||
|
|
@ -139,19 +139,20 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
new SimpleForwardingClientCallListener<RespT>(responseListener) {
|
||||
@Override
|
||||
public void onMessage(RespT message) {
|
||||
// Event: EventType.GRPC_CALL_RESPONSE_MESSAGE
|
||||
EventType responseMessageType = EventType.GRPC_CALL_RESPONSE_MESSAGE;
|
||||
// Event: EventType.SERVER_MESSAGE
|
||||
EventType responseMessageType = EventType.SERVER_MESSAGE;
|
||||
if (filterHelper.isEventToBeLogged(responseMessageType)) {
|
||||
try {
|
||||
helper.logRpcMessage(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
responseMessageType,
|
||||
message,
|
||||
maxMessageBytes,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId);
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log response message", e);
|
||||
}
|
||||
|
|
@ -161,17 +162,18 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
|
||||
@Override
|
||||
public void onHeaders(Metadata headers) {
|
||||
// Event: EventType.GRPC_CALL_RESPONSE_HEADER
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_RESPONSE_HEADER)) {
|
||||
// Event: EventType.SERVER_HEADER
|
||||
if (filterHelper.isEventToBeLogged(EventType.SERVER_HEADER)) {
|
||||
try {
|
||||
helper.logResponseHeader(
|
||||
helper.logServerHeader(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
headers,
|
||||
maxHeaderBytes,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
LogHelper.getPeerAddress(getAttributes()));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log response header", e);
|
||||
|
|
@ -182,18 +184,19 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
|
||||
@Override
|
||||
public void onClose(Status status, Metadata trailers) {
|
||||
// Event: EventType.GRPC_CALL_TRAILER
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_TRAILER)) {
|
||||
// Event: EventType.SERVER_TRAILER
|
||||
if (filterHelper.isEventToBeLogged(EventType.SERVER_TRAILER)) {
|
||||
try {
|
||||
helper.logTrailer(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
status,
|
||||
trailers,
|
||||
maxHeaderBytes,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
LogHelper.getPeerAddress(getAttributes()));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log trailer", e);
|
||||
|
|
@ -207,19 +210,20 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
|
||||
@Override
|
||||
public void sendMessage(ReqT message) {
|
||||
// Event: EventType.GRPC_CALL_REQUEST_MESSAGE
|
||||
EventType requestMessageType = EventType.GRPC_CALL_REQUEST_MESSAGE;
|
||||
// Event: EventType.CLIENT_MESSAGE
|
||||
EventType requestMessageType = EventType.CLIENT_MESSAGE;
|
||||
if (filterHelper.isEventToBeLogged(requestMessageType)) {
|
||||
try {
|
||||
helper.logRpcMessage(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
requestMessageType,
|
||||
message,
|
||||
maxMessageBytes,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId);
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log request message", e);
|
||||
}
|
||||
|
|
@ -229,15 +233,16 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
|
||||
@Override
|
||||
public void halfClose() {
|
||||
// Event: EventType.GRPC_CALL_HALF_CLOSE
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_HALF_CLOSE)) {
|
||||
// Event: EventType.CLIENT_HALF_CLOSE
|
||||
if (filterHelper.isEventToBeLogged(EventType.CLIENT_HALF_CLOSE)) {
|
||||
try {
|
||||
helper.logHalfClose(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId);
|
||||
authority,
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log half close", e);
|
||||
}
|
||||
|
|
@ -247,15 +252,16 @@ public final class InternalLoggingChannelInterceptor implements ClientIntercepto
|
|||
|
||||
@Override
|
||||
public void cancel(String message, Throwable cause) {
|
||||
// Event: EventType.GRPC_CALL_CANCEL
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_CANCEL)) {
|
||||
// Event: EventType.CANCEL
|
||||
if (filterHelper.isEventToBeLogged(EventType.CANCEL)) {
|
||||
try {
|
||||
helper.logCancel(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId);
|
||||
authority,
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log cancel", e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call,
|
||||
Metadata headers, ServerCallHandler<ReqT, RespT> next) {
|
||||
final AtomicLong seq = new AtomicLong(1);
|
||||
final String rpcId = UUID.randomUUID().toString();
|
||||
final String callId = UUID.randomUUID().toString();
|
||||
final String authority = call.getAuthority();
|
||||
final String serviceName = call.getMethodDescriptor().getServiceName();
|
||||
final String methodName = call.getMethodDescriptor().getBareMethodName();
|
||||
|
|
@ -101,10 +101,10 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
final int maxHeaderBytes = filterParams.headerBytes();
|
||||
final int maxMessageBytes = filterParams.messageBytes();
|
||||
|
||||
// Event: EventType.GRPC_CALL_REQUEST_HEADER
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_REQUEST_HEADER)) {
|
||||
// Event: EventType.CLIENT_HEADER
|
||||
if (filterHelper.isEventToBeLogged(EventType.CLIENT_HEADER)) {
|
||||
try {
|
||||
helper.logRequestHeader(
|
||||
helper.logClientHeader(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
|
|
@ -112,8 +112,8 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
timeout,
|
||||
headers,
|
||||
maxHeaderBytes,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
peerAddress);
|
||||
} catch (Exception e) {
|
||||
// Catching generic exceptions instead of specific ones for all the events.
|
||||
|
|
@ -130,17 +130,18 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
new SimpleForwardingServerCall<ReqT, RespT>(call) {
|
||||
@Override
|
||||
public void sendHeaders(Metadata headers) {
|
||||
// Event: EventType.GRPC_CALL_RESPONSE_HEADER
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_RESPONSE_HEADER)) {
|
||||
// Event: EventType.SERVER_HEADER
|
||||
if (filterHelper.isEventToBeLogged(EventType.SERVER_HEADER)) {
|
||||
try {
|
||||
helper.logResponseHeader(
|
||||
helper.logServerHeader(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
headers,
|
||||
maxHeaderBytes,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
null);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log response header", e);
|
||||
|
|
@ -151,19 +152,20 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
|
||||
@Override
|
||||
public void sendMessage(RespT message) {
|
||||
// Event: EventType.GRPC_CALL_RESPONSE_MESSAGE
|
||||
EventType responseMessageType = EventType.GRPC_CALL_RESPONSE_MESSAGE;
|
||||
// Event: EventType.SERVER_MESSAGE
|
||||
EventType responseMessageType = EventType.SERVER_MESSAGE;
|
||||
if (filterHelper.isEventToBeLogged(responseMessageType)) {
|
||||
try {
|
||||
helper.logRpcMessage(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
responseMessageType,
|
||||
message,
|
||||
maxMessageBytes,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId);
|
||||
EventLogger.SERVER,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log response message", e);
|
||||
}
|
||||
|
|
@ -173,18 +175,19 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
|
||||
@Override
|
||||
public void close(Status status, Metadata trailers) {
|
||||
// Event: EventType.GRPC_CALL_TRAILER
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_TRAILER)) {
|
||||
// Event: EventType.SERVER_TRAILER
|
||||
if (filterHelper.isEventToBeLogged(EventType.SERVER_TRAILER)) {
|
||||
try {
|
||||
helper.logTrailer(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
status,
|
||||
trailers,
|
||||
maxHeaderBytes,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
null);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log trailer", e);
|
||||
|
|
@ -198,19 +201,20 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
return new SimpleForwardingServerCallListener<ReqT>(listener) {
|
||||
@Override
|
||||
public void onMessage(ReqT message) {
|
||||
// Event: EventType.GRPC_CALL_REQUEST_MESSAGE
|
||||
EventType requestMessageType = EventType.GRPC_CALL_REQUEST_MESSAGE;
|
||||
// Event: EventType.CLIENT_MESSAGE
|
||||
EventType requestMessageType = EventType.CLIENT_MESSAGE;
|
||||
if (filterHelper.isEventToBeLogged(requestMessageType)) {
|
||||
try {
|
||||
helper.logRpcMessage(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
requestMessageType,
|
||||
message,
|
||||
maxMessageBytes,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId);
|
||||
EventLogger.SERVER,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log request message", e);
|
||||
}
|
||||
|
|
@ -220,15 +224,16 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
|
||||
@Override
|
||||
public void onHalfClose() {
|
||||
// Event: EventType.GRPC_CALL_HALF_CLOSE
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_HALF_CLOSE)) {
|
||||
// Event: EventType.CLIENT_HALF_CLOSE
|
||||
if (filterHelper.isEventToBeLogged(EventType.CLIENT_HALF_CLOSE)) {
|
||||
try {
|
||||
helper.logHalfClose(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId);
|
||||
authority,
|
||||
EventLogger.SERVER,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log half close", e);
|
||||
}
|
||||
|
|
@ -238,15 +243,16 @@ public final class InternalLoggingServerInterceptor implements ServerInterceptor
|
|||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// Event: EventType.GRPC_CALL_CANCEL
|
||||
if (filterHelper.isEventToBeLogged(EventType.GRPC_CALL_CANCEL)) {
|
||||
// Event: EventType.CANCEL
|
||||
if (filterHelper.isEventToBeLogged(EventType.CANCEL)) {
|
||||
try {
|
||||
helper.logCancel(
|
||||
seq.getAndIncrement(),
|
||||
serviceName,
|
||||
methodName,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId);
|
||||
authority,
|
||||
EventLogger.SERVER,
|
||||
callId);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable to log cancel", e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,32 +18,32 @@ package io.grpc.gcp.observability.interceptors;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static io.grpc.InternalMetadata.BASE64_ENCODING_OMIT_PADDING;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Duration;
|
||||
import com.google.protobuf.util.Timestamps;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.Deadline;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.Internal;
|
||||
import io.grpc.InternalMetadata;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.gcp.observability.logging.Sink;
|
||||
import io.grpc.internal.TimeProvider;
|
||||
import io.grpc.observabilitylog.v1.Address;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.Address;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.EventLogger;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.EventType;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.LogLevel;
|
||||
import io.grpc.observabilitylog.v1.Payload;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
|
@ -63,23 +63,20 @@ public class LogHelper {
|
|||
Metadata.BINARY_BYTE_MARSHALLER);
|
||||
|
||||
private final Sink sink;
|
||||
private final TimeProvider timeProvider;
|
||||
|
||||
/**
|
||||
* Creates a LogHelper instance.
|
||||
*
|
||||
* @param sink sink
|
||||
* @param timeProvider timeprovider
|
||||
*
|
||||
*/
|
||||
public LogHelper(Sink sink, TimeProvider timeProvider) {
|
||||
public LogHelper(Sink sink) {
|
||||
this.sink = sink;
|
||||
this.timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the request header. Binary logging equivalent of logClientHeader.
|
||||
*/
|
||||
void logRequestHeader(
|
||||
void logClientHeader(
|
||||
long seqId,
|
||||
String serviceName,
|
||||
String methodName,
|
||||
|
|
@ -88,35 +85,33 @@ public class LogHelper {
|
|||
Metadata metadata,
|
||||
int maxHeaderBytes,
|
||||
GrpcLogRecord.EventLogger eventLogger,
|
||||
String rpcId,
|
||||
String callId,
|
||||
// null on client side
|
||||
@Nullable SocketAddress peerAddress) {
|
||||
checkNotNull(serviceName, "serviceName");
|
||||
checkNotNull(methodName, "methodName");
|
||||
checkNotNull(rpcId, "rpcId");
|
||||
checkNotNull(authority, "authority");
|
||||
checkNotNull(callId, "callId");
|
||||
checkArgument(
|
||||
peerAddress == null || eventLogger == GrpcLogRecord.EventLogger.LOGGER_SERVER,
|
||||
peerAddress == null || eventLogger == GrpcLogRecord.EventLogger.SERVER,
|
||||
"peerAddress can only be specified by server");
|
||||
|
||||
PayloadBuilder<GrpcLogRecord.Metadata.Builder> pair =
|
||||
PayloadBuilderHelper<Payload.Builder> pair =
|
||||
createMetadataProto(metadata, maxHeaderBytes);
|
||||
GrpcLogRecord.Builder logEntryBuilder = createTimestamp()
|
||||
if (timeout != null) {
|
||||
pair.payloadBuilder.setTimeout(timeout);
|
||||
}
|
||||
GrpcLogRecord.Builder logEntryBuilder = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setAuthority(authority)
|
||||
.setEventType(EventType.GRPC_CALL_REQUEST_HEADER)
|
||||
.setEventLogger(eventLogger)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setMetadata(pair.payload)
|
||||
.setPayloadSize(pair.size)
|
||||
.setType(EventType.CLIENT_HEADER)
|
||||
.setLogger(eventLogger)
|
||||
.setPayload(pair.payloadBuilder)
|
||||
.setPayloadTruncated(pair.truncated)
|
||||
.setRpcId(rpcId);
|
||||
if (timeout != null) {
|
||||
logEntryBuilder.setTimeout(timeout);
|
||||
}
|
||||
.setCallId(callId);
|
||||
if (peerAddress != null) {
|
||||
logEntryBuilder.setPeerAddress(socketAddressToProto(peerAddress));
|
||||
logEntryBuilder.setPeer(socketAddressToProto(peerAddress));
|
||||
}
|
||||
sink.write(logEntryBuilder.build());
|
||||
}
|
||||
|
|
@ -124,39 +119,40 @@ public class LogHelper {
|
|||
/**
|
||||
* Logs the response header. Binary logging equivalent of logServerHeader.
|
||||
*/
|
||||
void logResponseHeader(
|
||||
void logServerHeader(
|
||||
long seqId,
|
||||
String serviceName,
|
||||
String methodName,
|
||||
String authority,
|
||||
Metadata metadata,
|
||||
int maxHeaderBytes,
|
||||
GrpcLogRecord.EventLogger eventLogger,
|
||||
String rpcId,
|
||||
String callId,
|
||||
@Nullable SocketAddress peerAddress) {
|
||||
checkNotNull(serviceName, "serviceName");
|
||||
checkNotNull(methodName, "methodName");
|
||||
checkNotNull(rpcId, "rpcId");
|
||||
checkNotNull(authority, "authority");
|
||||
checkNotNull(callId, "callId");
|
||||
// Logging peer address only on the first incoming event. On server side, peer address will
|
||||
// of logging request header
|
||||
checkArgument(
|
||||
peerAddress == null || eventLogger == GrpcLogRecord.EventLogger.LOGGER_CLIENT,
|
||||
peerAddress == null || eventLogger == GrpcLogRecord.EventLogger.CLIENT,
|
||||
"peerAddress can only be specified for client");
|
||||
|
||||
PayloadBuilder<GrpcLogRecord.Metadata.Builder> pair =
|
||||
PayloadBuilderHelper<Payload.Builder> pair =
|
||||
createMetadataProto(metadata, maxHeaderBytes);
|
||||
GrpcLogRecord.Builder logEntryBuilder = createTimestamp()
|
||||
GrpcLogRecord.Builder logEntryBuilder = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_RESPONSE_HEADER)
|
||||
.setEventLogger(eventLogger)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setMetadata(pair.payload)
|
||||
.setPayloadSize(pair.size)
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.SERVER_HEADER)
|
||||
.setLogger(eventLogger)
|
||||
.setPayload(pair.payloadBuilder)
|
||||
.setPayloadTruncated(pair.truncated)
|
||||
.setRpcId(rpcId);
|
||||
.setCallId(callId);
|
||||
if (peerAddress != null) {
|
||||
logEntryBuilder.setPeerAddress(socketAddressToProto(peerAddress));
|
||||
logEntryBuilder.setPeer(socketAddressToProto(peerAddress));
|
||||
}
|
||||
sink.write(logEntryBuilder.build());
|
||||
}
|
||||
|
|
@ -168,44 +164,45 @@ public class LogHelper {
|
|||
long seqId,
|
||||
String serviceName,
|
||||
String methodName,
|
||||
String authority,
|
||||
Status status,
|
||||
Metadata metadata,
|
||||
int maxHeaderBytes,
|
||||
GrpcLogRecord.EventLogger eventLogger,
|
||||
String rpcId,
|
||||
String callId,
|
||||
@Nullable SocketAddress peerAddress) {
|
||||
checkNotNull(serviceName, "serviceName");
|
||||
checkNotNull(methodName, "methodName");
|
||||
checkNotNull(authority, "authority");
|
||||
checkNotNull(status, "status");
|
||||
checkNotNull(rpcId, "rpcId");
|
||||
checkNotNull(callId, "callId");
|
||||
checkArgument(
|
||||
peerAddress == null || eventLogger == GrpcLogRecord.EventLogger.LOGGER_CLIENT,
|
||||
peerAddress == null || eventLogger == GrpcLogRecord.EventLogger.CLIENT,
|
||||
"peerAddress can only be specified for client");
|
||||
|
||||
PayloadBuilder<GrpcLogRecord.Metadata.Builder> pair =
|
||||
PayloadBuilderHelper<Payload.Builder> pair =
|
||||
createMetadataProto(metadata, maxHeaderBytes);
|
||||
GrpcLogRecord.Builder logEntryBuilder = createTimestamp()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_TRAILER)
|
||||
.setEventLogger(eventLogger)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setMetadata(pair.payload)
|
||||
.setPayloadSize(pair.size)
|
||||
.setPayloadTruncated(pair.truncated)
|
||||
.setStatusCode(status.getCode().value())
|
||||
.setRpcId(rpcId);
|
||||
pair.payloadBuilder.setStatusCode(status.getCode().value());
|
||||
String statusDescription = status.getDescription();
|
||||
if (statusDescription != null) {
|
||||
logEntryBuilder.setStatusMessage(statusDescription);
|
||||
pair.payloadBuilder.setStatusMessage(statusDescription);
|
||||
}
|
||||
byte[] statusDetailBytes = metadata.get(STATUS_DETAILS_KEY);
|
||||
if (statusDetailBytes != null) {
|
||||
logEntryBuilder.setStatusDetails(ByteString.copyFrom(statusDetailBytes));
|
||||
pair.payloadBuilder.setStatusDetails(ByteString.copyFrom(statusDetailBytes));
|
||||
}
|
||||
GrpcLogRecord.Builder logEntryBuilder = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.SERVER_TRAILER)
|
||||
.setLogger(eventLogger)
|
||||
.setPayload(pair.payloadBuilder)
|
||||
.setPayloadTruncated(pair.truncated)
|
||||
.setCallId(callId);
|
||||
if (peerAddress != null) {
|
||||
logEntryBuilder.setPeerAddress(socketAddressToProto(peerAddress));
|
||||
logEntryBuilder.setPeer(socketAddressToProto(peerAddress));
|
||||
}
|
||||
sink.write(logEntryBuilder.build());
|
||||
}
|
||||
|
|
@ -217,17 +214,19 @@ public class LogHelper {
|
|||
long seqId,
|
||||
String serviceName,
|
||||
String methodName,
|
||||
String authority,
|
||||
EventType eventType,
|
||||
T message,
|
||||
int maxMessageBytes,
|
||||
EventLogger eventLogger,
|
||||
String rpcId) {
|
||||
String callId) {
|
||||
checkNotNull(serviceName, "serviceName");
|
||||
checkNotNull(methodName, "methodName");
|
||||
checkNotNull(rpcId, "rpcId");
|
||||
checkNotNull(authority, "authority");
|
||||
checkNotNull(callId, "callId");
|
||||
checkArgument(
|
||||
eventType == EventType.GRPC_CALL_REQUEST_MESSAGE
|
||||
|| eventType == EventType.GRPC_CALL_RESPONSE_MESSAGE,
|
||||
eventType == EventType.CLIENT_MESSAGE
|
||||
|| eventType == EventType.SERVER_MESSAGE,
|
||||
"event type must correspond to client message or server message");
|
||||
checkNotNull(message, "message");
|
||||
|
||||
|
|
@ -244,24 +243,20 @@ public class LogHelper {
|
|||
logger.log(Level.WARNING, "message is of UNKNOWN type, message and payload_size fields "
|
||||
+ "of GrpcLogRecord proto will not be logged");
|
||||
}
|
||||
PayloadBuilder<ByteString> pair = null;
|
||||
PayloadBuilderHelper<Payload.Builder> pair = null;
|
||||
if (messageBytesArray != null) {
|
||||
pair = createMessageProto(messageBytesArray, maxMessageBytes);
|
||||
}
|
||||
|
||||
GrpcLogRecord.Builder logEntryBuilder = createTimestamp()
|
||||
GrpcLogRecord.Builder logEntryBuilder = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(eventType)
|
||||
.setEventLogger(eventLogger)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setRpcId(rpcId);
|
||||
if (pair != null && pair.size != 0) {
|
||||
logEntryBuilder.setPayloadSize(pair.size);
|
||||
}
|
||||
if (pair != null && pair.payload != null) {
|
||||
logEntryBuilder.setMessage(pair.payload)
|
||||
.setAuthority(authority)
|
||||
.setType(eventType)
|
||||
.setLogger(eventLogger)
|
||||
.setCallId(callId);
|
||||
if (pair != null) {
|
||||
logEntryBuilder.setPayload(pair.payloadBuilder)
|
||||
.setPayloadTruncated(pair.truncated);
|
||||
}
|
||||
sink.write(logEntryBuilder.build());
|
||||
|
|
@ -274,20 +269,22 @@ public class LogHelper {
|
|||
long seqId,
|
||||
String serviceName,
|
||||
String methodName,
|
||||
String authority,
|
||||
GrpcLogRecord.EventLogger eventLogger,
|
||||
String rpcId) {
|
||||
String callId) {
|
||||
checkNotNull(serviceName, "serviceName");
|
||||
checkNotNull(methodName, "methodName");
|
||||
checkNotNull(rpcId, "rpcId");
|
||||
checkNotNull(authority, "authority");
|
||||
checkNotNull(callId, "callId");
|
||||
|
||||
GrpcLogRecord.Builder logEntryBuilder = createTimestamp()
|
||||
GrpcLogRecord.Builder logEntryBuilder = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_HALF_CLOSE)
|
||||
.setEventLogger(eventLogger)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setRpcId(rpcId);
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.CLIENT_HALF_CLOSE)
|
||||
.setLogger(eventLogger)
|
||||
.setCallId(callId);
|
||||
sink.write(logEntryBuilder.build());
|
||||
}
|
||||
|
||||
|
|
@ -298,28 +295,25 @@ public class LogHelper {
|
|||
long seqId,
|
||||
String serviceName,
|
||||
String methodName,
|
||||
String authority,
|
||||
GrpcLogRecord.EventLogger eventLogger,
|
||||
String rpcId) {
|
||||
String callId) {
|
||||
checkNotNull(serviceName, "serviceName");
|
||||
checkNotNull(methodName, "methodName");
|
||||
checkNotNull(rpcId, "rpcId");
|
||||
checkNotNull(authority, "authority");
|
||||
checkNotNull(callId, "callId");
|
||||
|
||||
GrpcLogRecord.Builder logEntryBuilder = createTimestamp()
|
||||
GrpcLogRecord.Builder logEntryBuilder = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_CANCEL)
|
||||
.setEventLogger(eventLogger)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setRpcId(rpcId);
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.CANCEL)
|
||||
.setLogger(eventLogger)
|
||||
.setCallId(callId);
|
||||
sink.write(logEntryBuilder.build());
|
||||
}
|
||||
|
||||
GrpcLogRecord.Builder createTimestamp() {
|
||||
long nanos = timeProvider.currentTimeNanos();
|
||||
return GrpcLogRecord.newBuilder().setTimestamp(Timestamps.fromNanos(nanos));
|
||||
}
|
||||
|
||||
// TODO(DNVindhya): Evaluate if we need following clause for metadata logging in GcpObservability
|
||||
// Leaving the implementation for now as is to have same behavior across Java and Go
|
||||
private static final Set<String> NEVER_INCLUDED_METADATA = new HashSet<>(
|
||||
|
|
@ -331,58 +325,65 @@ public class LogHelper {
|
|||
Collections.singletonList(
|
||||
"grpc-trace-bin"));
|
||||
|
||||
static final class PayloadBuilder<T> {
|
||||
T payload;
|
||||
int size;
|
||||
static final class PayloadBuilderHelper<T> {
|
||||
T payloadBuilder;
|
||||
boolean truncated;
|
||||
|
||||
private PayloadBuilder(T payload, int size, boolean truncated) {
|
||||
this.payload = payload;
|
||||
this.size = size;
|
||||
private PayloadBuilderHelper(T payload, boolean truncated) {
|
||||
this.payloadBuilder = payload;
|
||||
this.truncated = truncated;
|
||||
}
|
||||
}
|
||||
|
||||
static PayloadBuilder<GrpcLogRecord.Metadata.Builder> createMetadataProto(Metadata metadata,
|
||||
static PayloadBuilderHelper<Payload.Builder> createMetadataProto(Metadata metadata,
|
||||
int maxHeaderBytes) {
|
||||
checkNotNull(metadata, "metadata");
|
||||
checkArgument(maxHeaderBytes >= 0,
|
||||
"maxHeaderBytes must be non negative");
|
||||
GrpcLogRecord.Metadata.Builder metadataBuilder = GrpcLogRecord.Metadata.newBuilder();
|
||||
// This code is tightly coupled with io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata
|
||||
// implementation
|
||||
byte[][] serialized = InternalMetadata.serialize(metadata);
|
||||
Joiner joiner = Joiner.on(",").skipNulls();
|
||||
Payload.Builder payloadBuilder = Payload.newBuilder();
|
||||
boolean truncated = false;
|
||||
int totalMetadataBytes = 0;
|
||||
if (serialized != null) {
|
||||
// Calculate bytes for each GrpcLogRecord.Metadata.MetadataEntry
|
||||
for (int i = 0; i < serialized.length; i += 2) {
|
||||
String key = new String(serialized[i], Charsets.UTF_8);
|
||||
byte[] value = serialized[i + 1];
|
||||
for (String key : metadata.keys()) {
|
||||
if (NEVER_INCLUDED_METADATA.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
boolean forceInclude = ALWAYS_INCLUDED_METADATA.contains(key);
|
||||
int metadataBytesAfterAdd = totalMetadataBytes + key.length() + value.length;
|
||||
String metadataValue;
|
||||
if (key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
|
||||
Iterable<byte[]> metadataValues =
|
||||
metadata.getAll(Metadata.Key.of(key, Metadata.BINARY_BYTE_MARSHALLER));
|
||||
List<String> numList = new ArrayList<String>();
|
||||
metadataValues.forEach(
|
||||
(element) -> {
|
||||
numList.add(BASE64_ENCODING_OMIT_PADDING.encode(element));
|
||||
});
|
||||
metadataValue = joiner.join(numList);
|
||||
} else {
|
||||
Iterable<String> metadataValues = metadata.getAll(
|
||||
Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER));
|
||||
metadataValue = joiner.join(metadataValues);
|
||||
}
|
||||
|
||||
int metadataBytesAfterAdd = totalMetadataBytes + key.length() + metadataValue.length();
|
||||
if (!forceInclude && metadataBytesAfterAdd > maxHeaderBytes) {
|
||||
truncated = true;
|
||||
continue;
|
||||
}
|
||||
metadataBuilder.addEntryBuilder()
|
||||
.setKey(key)
|
||||
.setValue(ByteString.copyFrom(value));
|
||||
payloadBuilder.putMetadata(key, metadataValue);
|
||||
if (!forceInclude) {
|
||||
// force included keys do not count towards the size limit
|
||||
totalMetadataBytes = metadataBytesAfterAdd;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PayloadBuilder<>(metadataBuilder, totalMetadataBytes, truncated);
|
||||
return new PayloadBuilderHelper<>(payloadBuilder, truncated);
|
||||
}
|
||||
|
||||
static PayloadBuilder<ByteString> createMessageProto(byte[] message, int maxMessageBytes) {
|
||||
static PayloadBuilderHelper<Payload.Builder> createMessageProto(
|
||||
byte[] message, int maxMessageBytes) {
|
||||
checkArgument(maxMessageBytes >= 0,
|
||||
"maxMessageBytes must be non negative");
|
||||
Payload.Builder payloadBuilder = Payload.newBuilder();
|
||||
int desiredBytes = 0;
|
||||
int messageLength = message.length;
|
||||
if (maxMessageBytes > 0) {
|
||||
|
|
@ -390,8 +391,10 @@ public class LogHelper {
|
|||
}
|
||||
ByteString messageData =
|
||||
ByteString.copyFrom(message, 0, desiredBytes);
|
||||
payloadBuilder.setMessage(messageData);
|
||||
payloadBuilder.setMessageLength(messageLength);
|
||||
|
||||
return new PayloadBuilder<>(messageData, messageLength,
|
||||
return new PayloadBuilderHelper<>(payloadBuilder,
|
||||
maxMessageBytes < message.length);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import io.grpc.Internal;
|
|||
import io.grpc.internal.JsonParser;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
|
@ -50,41 +51,36 @@ 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 static final long FALLBACK_FLUSH_LIMIT = 100L;
|
||||
private final String projectId;
|
||||
private final Map<String, String> customTags;
|
||||
private final MonitoredResource kubernetesResource;
|
||||
private final Long flushLimit;
|
||||
/** Lazily initialize cloud logging client to avoid circular initialization. Because cloud
|
||||
* logging APIs also uses gRPC. */
|
||||
private volatile Logging gcpLoggingClient;
|
||||
private long flushCounter;
|
||||
private final Collection<String> servicesToExclude;
|
||||
|
||||
@VisibleForTesting
|
||||
GcpLogSink(Logging loggingClient, String destinationProjectId, Map<String, String> locationTags,
|
||||
Map<String, String> customTags, Long flushLimit, Collection<String> servicesToExclude) {
|
||||
this(destinationProjectId, locationTags, customTags, flushLimit, servicesToExclude);
|
||||
Map<String, String> customTags, Collection<String> servicesToExclude) {
|
||||
this(destinationProjectId, locationTags, customTags, servicesToExclude);
|
||||
this.gcpLoggingClient = loggingClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single instance of GcpLogSink.
|
||||
*
|
||||
* @param destinationProjectId cloud project id to write logs
|
||||
* @param servicesToExclude service names for which log entries should not be generated
|
||||
*/
|
||||
public GcpLogSink(String destinationProjectId, Map<String, String> locationTags,
|
||||
Map<String, String> customTags, Long flushLimit, Collection<String> servicesToExclude) {
|
||||
Map<String, String> customTags, Collection<String> servicesToExclude) {
|
||||
this.projectId = destinationProjectId;
|
||||
this.customTags = getCustomTags(customTags, locationTags, destinationProjectId);
|
||||
this.kubernetesResource = getResource(locationTags);
|
||||
this.flushLimit = flushLimit != null ? flushLimit : FALLBACK_FLUSH_LIMIT;
|
||||
this.flushCounter = 0L;
|
||||
this.servicesToExclude = checkNotNull(servicesToExclude, "servicesToExclude");
|
||||
}
|
||||
|
||||
|
|
@ -106,28 +102,24 @@ public class GcpLogSink implements Sink {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
GrpcLogRecord.EventType event = logProto.getEventType();
|
||||
Severity logEntrySeverity = getCloudLoggingLevel(logProto.getLogLevel());
|
||||
GrpcLogRecord.EventType eventType = logProto.getType();
|
||||
// TODO(DNVindhya): make sure all (int, long) values are not displayed as double
|
||||
// For now, every value is being converted as string because of JsonFormat.printer().print
|
||||
Map<String, Object> logProtoMap = protoToMapConverter(logProto);
|
||||
LogEntry.Builder grpcLogEntryBuilder =
|
||||
LogEntry.newBuilder(JsonPayload.of(protoToMapConverter(logProto)))
|
||||
.setSeverity(logEntrySeverity)
|
||||
LogEntry.newBuilder(JsonPayload.of(logProtoMap))
|
||||
.setSeverity(DEFAULT_LOG_LEVEL)
|
||||
.setLogName(DEFAULT_LOG_NAME)
|
||||
.setResource(kubernetesResource);
|
||||
.setResource(kubernetesResource)
|
||||
.setTimestamp(Instant.now());
|
||||
|
||||
if (!customTags.isEmpty()) {
|
||||
grpcLogEntryBuilder.setLabels(customTags);
|
||||
}
|
||||
LogEntry grpcLogEntry = grpcLogEntryBuilder.build();
|
||||
synchronized (this) {
|
||||
logger.log(Level.FINEST, "Writing gRPC event : {0} to Cloud Logging", event);
|
||||
logger.log(Level.FINEST, "Writing gRPC event : {0} to Cloud Logging", eventType);
|
||||
gcpLoggingClient.write(Collections.singleton(grpcLogEntry));
|
||||
flushCounter = ++flushCounter;
|
||||
if (flushCounter >= flushLimit) {
|
||||
gcpLoggingClient.flush();
|
||||
flushCounter = 0L;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Caught exception while writing to Cloud Logging", e);
|
||||
|
|
@ -175,29 +167,11 @@ public class GcpLogSink implements Sink {
|
|||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> protoToMapConverter(GrpcLogRecord logProto)
|
||||
throws IOException {
|
||||
JsonFormat.Printer printer = JsonFormat.printer().preservingProtoFieldNames();
|
||||
JsonFormat.Printer printer = JsonFormat.printer();
|
||||
String recordJson = printer.print(logProto);
|
||||
return (Map<String, Object>) JsonParser.parse(recordJson);
|
||||
}
|
||||
|
||||
private Severity getCloudLoggingLevel(GrpcLogRecord.LogLevel recordLevel) {
|
||||
switch (recordLevel.getNumber()) {
|
||||
case 1: // GrpcLogRecord.LogLevel.LOG_LEVEL_TRACE
|
||||
case 2: // GrpcLogRecord.LogLevel.LOG_LEVEL_DEBUG
|
||||
return Severity.DEBUG;
|
||||
case 3: // GrpcLogRecord.LogLevel.LOG_LEVEL_INFO
|
||||
return Severity.INFO;
|
||||
case 4: // GrpcLogRecord.LogLevel.LOG_LEVEL_WARN
|
||||
return Severity.WARNING;
|
||||
case 5: // GrpcLogRecord.LogLevel.LOG_LEVEL_ERROR
|
||||
return Severity.ERROR;
|
||||
case 6: // GrpcLogRecord.LogLevel.LOG_LEVEL_CRITICAL
|
||||
return Severity.CRITICAL;
|
||||
default:
|
||||
return Severity.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes Cloud Logging Client.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,120 +28,87 @@ option java_outer_classname = "ObservabilityLogProto";
|
|||
message GrpcLogRecord {
|
||||
// List of event types
|
||||
enum EventType {
|
||||
GRPC_CALL_UNKNOWN = 0;
|
||||
EVENT_TYPE_UNKNOWN = 0;
|
||||
// Header sent from client to server
|
||||
GRPC_CALL_REQUEST_HEADER = 1;
|
||||
CLIENT_HEADER = 1;
|
||||
// Header sent from server to client
|
||||
GRPC_CALL_RESPONSE_HEADER = 2;
|
||||
SERVER_HEADER = 2;
|
||||
// Message sent from client to server
|
||||
GRPC_CALL_REQUEST_MESSAGE = 3;
|
||||
CLIENT_MESSAGE = 3;
|
||||
// Message sent from server to client
|
||||
GRPC_CALL_RESPONSE_MESSAGE = 4;
|
||||
// Trailer indicates the end of the gRPC call
|
||||
GRPC_CALL_TRAILER = 5;
|
||||
SERVER_MESSAGE = 4;
|
||||
// A signal that client is done sending
|
||||
GRPC_CALL_HALF_CLOSE = 6;
|
||||
CLIENT_HALF_CLOSE = 5;
|
||||
// Trailer indicates the end of the gRPC call
|
||||
SERVER_TRAILER = 6;
|
||||
// A signal that the rpc is canceled
|
||||
GRPC_CALL_CANCEL = 7;
|
||||
CANCEL = 7;
|
||||
}
|
||||
|
||||
// The entity that generates the log entry
|
||||
enum EventLogger {
|
||||
LOGGER_UNKNOWN = 0;
|
||||
LOGGER_CLIENT = 1;
|
||||
LOGGER_SERVER = 2;
|
||||
}
|
||||
// The log severity level of the log entry
|
||||
enum LogLevel {
|
||||
LOG_LEVEL_UNKNOWN = 0;
|
||||
LOG_LEVEL_TRACE = 1;
|
||||
LOG_LEVEL_DEBUG = 2;
|
||||
LOG_LEVEL_INFO = 3;
|
||||
LOG_LEVEL_WARN = 4;
|
||||
LOG_LEVEL_ERROR = 5;
|
||||
LOG_LEVEL_CRITICAL = 6;
|
||||
CLIENT = 1;
|
||||
SERVER = 2;
|
||||
}
|
||||
|
||||
// The timestamp of the log event
|
||||
google.protobuf.Timestamp timestamp = 1;
|
||||
|
||||
// Uniquely identifies a call. The value must not be 0 in order to disambiguate
|
||||
// from an unset value.
|
||||
// Each call may have several log entries. They will all have the same rpc_id.
|
||||
// Uniquely identifies a call.
|
||||
// Each call may have several log entries. They will all have the same call_id.
|
||||
// Nothing is guaranteed about their value other than they are unique across
|
||||
// different RPCs in the same gRPC process.
|
||||
string rpc_id = 2;
|
||||
|
||||
EventType event_type = 3; // one of the above EventType enum
|
||||
EventLogger event_logger = 4; // one of the above EventLogger enum
|
||||
|
||||
// the name of the service
|
||||
string service_name = 5;
|
||||
// the name of the RPC method
|
||||
string method_name = 6;
|
||||
|
||||
LogLevel log_level = 7; // one of the above LogLevel enum
|
||||
|
||||
// Peer address information. On client side, peer is logged on server
|
||||
// header event or trailer event (if trailer-only). On server side, peer
|
||||
// is always logged on the client header event.
|
||||
Address peer_address = 8;
|
||||
|
||||
// the RPC timeout value
|
||||
google.protobuf.Duration timeout = 11;
|
||||
|
||||
// A single process may be used to run multiple virtual servers with
|
||||
// different identities.
|
||||
// The authority is the name of such a server identify. It is typically a
|
||||
// portion of the URI in the form of <host> or <host>:<port>.
|
||||
string authority = 12;
|
||||
|
||||
// Size of the message or metadata, depending on the event type,
|
||||
// regardless of whether the full message or metadata is being logged
|
||||
// (i.e. could be truncated or omitted).
|
||||
uint32 payload_size = 13;
|
||||
|
||||
// true if message or metadata field is either truncated or omitted due
|
||||
// to config options
|
||||
bool payload_truncated = 14;
|
||||
|
||||
// Used by header event or trailer event
|
||||
Metadata metadata = 15;
|
||||
string call_id = 2;
|
||||
|
||||
// The entry sequence ID for this call. The first message has a value of 1,
|
||||
// to disambiguate from an unset value. The purpose of this field is to
|
||||
// detect missing entries in environments where durability or ordering is
|
||||
// not guaranteed.
|
||||
uint64 sequence_id = 16;
|
||||
uint64 sequence_id = 3;
|
||||
|
||||
// Used by message event
|
||||
bytes message = 17;
|
||||
EventType type = 4; // one of the above EventType enum
|
||||
EventLogger logger = 5; // one of the above EventLogger enum
|
||||
|
||||
// The gRPC status code
|
||||
uint32 status_code = 18;
|
||||
// Payload for log entry.
|
||||
// It can include a combination of {metadata, message, status based on type of
|
||||
// the event event being logged and config options.
|
||||
Payload payload = 6;
|
||||
|
||||
// The gRPC status message
|
||||
string status_message = 19;
|
||||
// true if message or metadata field is either truncated or omitted due
|
||||
// to config options
|
||||
bool payload_truncated = 7;
|
||||
// Peer address information. On client side, peer is logged on server
|
||||
// header event or trailer event (if trailer-only). On server side, peer
|
||||
// is always logged on the client header event.
|
||||
Address peer = 8;
|
||||
|
||||
// The value of the grpc-status-details-bin metadata key, if any.
|
||||
// This is always an encoded google.rpc.Status message
|
||||
bytes status_details = 20;
|
||||
|
||||
// Attributes of the environment generating log record. The purpose of this
|
||||
// field is to identify the source environment.
|
||||
EnvironmentTags env_tags = 21;
|
||||
|
||||
// A list of non-gRPC custom values specified by the application
|
||||
repeated CustomTags custom_tags = 22;
|
||||
|
||||
// A list of metadata pairs
|
||||
message Metadata {
|
||||
repeated MetadataEntry entry = 1;
|
||||
// A single process may be used to run multiple virtual servers with
|
||||
// different identities.
|
||||
// The authority is the name of such a server identify. It is typically a
|
||||
// portion of the URI in the form of <host> or <host>:<port>.
|
||||
string authority = 10;
|
||||
// the name of the service
|
||||
string service_name = 11;
|
||||
// the name of the RPC method
|
||||
string method_name = 12;
|
||||
}
|
||||
|
||||
// One metadata key value pair
|
||||
message MetadataEntry {
|
||||
string key = 1;
|
||||
bytes value = 2;
|
||||
message Payload {
|
||||
// A list of metadata pairs
|
||||
map<string, string> metadata = 1;
|
||||
// the RPC timeout value
|
||||
google.protobuf.Duration timeout = 2;
|
||||
// The gRPC status code
|
||||
uint32 status_code = 3;
|
||||
// The gRPC status message
|
||||
string status_message = 4;
|
||||
// The value of the grpc-status-details-bin metadata key, if any.
|
||||
// This is always an encoded google.rpc.Status message
|
||||
bytes status_details = 5;
|
||||
// Size of the message or metadata, depending on the event type,
|
||||
// regardless of whether the full message or metadata is being logged
|
||||
// (i.e. could be truncated or omitted).
|
||||
uint32 message_length = 6;
|
||||
// Used by message event
|
||||
bytes message = 7;
|
||||
}
|
||||
|
||||
// Address information
|
||||
|
|
@ -157,22 +124,3 @@ message GrpcLogRecord {
|
|||
// only for TYPE_IPV4 and TYPE_IPV6
|
||||
uint32 ip_port = 3;
|
||||
}
|
||||
|
||||
// Source Environment information
|
||||
message EnvironmentTags {
|
||||
string gcp_project_id = 1;
|
||||
string gcp_numeric_project_id = 2;
|
||||
string gce_instance_id = 3;
|
||||
string gce_instance_hostname = 4;
|
||||
string gce_instance_zone = 5;
|
||||
string gke_cluster_uid = 6;
|
||||
string gke_cluster_name = 7;
|
||||
string gke_cluster_location = 8;
|
||||
}
|
||||
|
||||
// Custom key value pair
|
||||
message CustomTags {
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import io.grpc.gcp.observability.interceptors.InternalLoggingServerInterceptor;
|
|||
import io.grpc.gcp.observability.interceptors.LogHelper;
|
||||
import io.grpc.gcp.observability.logging.GcpLogSink;
|
||||
import io.grpc.gcp.observability.logging.Sink;
|
||||
import io.grpc.internal.TimeProvider;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.EventType;
|
||||
import io.grpc.testing.GrpcCleanupRule;
|
||||
|
|
@ -67,7 +66,6 @@ public class LoggingTest {
|
|||
private static final ImmutableMap<String, String> CUSTOM_TAGS = ImmutableMap.of(
|
||||
"KEY1", "Value1",
|
||||
"KEY2", "VALUE2");
|
||||
private static final long FLUSH_LIMIT = 100L;
|
||||
|
||||
private final StaticTestingClassLoader classLoader =
|
||||
new StaticTestingClassLoader(getClass().getClassLoader(), Pattern.compile("io\\.grpc\\..*"));
|
||||
|
|
@ -113,9 +111,9 @@ public class LoggingTest {
|
|||
public void run() {
|
||||
Sink sink =
|
||||
new GcpLogSink(
|
||||
PROJECT_ID, LOCATION_TAGS, CUSTOM_TAGS, FLUSH_LIMIT, Collections.emptySet());
|
||||
PROJECT_ID, LOCATION_TAGS, CUSTOM_TAGS, Collections.emptySet());
|
||||
ObservabilityConfig config = mock(ObservabilityConfig.class);
|
||||
LogHelper spyLogHelper = spy(new LogHelper(sink, TimeProvider.SYSTEM_TIME_PROVIDER));
|
||||
LogHelper spyLogHelper = spy(new LogHelper(sink));
|
||||
ConfigFilterHelper mockFilterHelper = mock(ConfigFilterHelper.class);
|
||||
InternalLoggingChannelInterceptor.Factory channelInterceptorFactory =
|
||||
new InternalLoggingChannelInterceptor.FactoryImpl(spyLogHelper, mockFilterHelper);
|
||||
|
|
@ -123,7 +121,7 @@ public class LoggingTest {
|
|||
new InternalLoggingServerInterceptor.FactoryImpl(spyLogHelper, mockFilterHelper);
|
||||
|
||||
when(config.isEnableCloudLogging()).thenReturn(true);
|
||||
FilterParams logAlwaysFilterParams = FilterParams.create(true, 0, 0);
|
||||
FilterParams logAlwaysFilterParams = FilterParams.create(true, 1024, 10);
|
||||
when(mockFilterHelper.isMethodToBeLogged(any(MethodDescriptor.class)))
|
||||
.thenReturn(logAlwaysFilterParams);
|
||||
when(mockFilterHelper.isEventToBeLogged(any(GrpcLogRecord.EventType.class))).thenReturn(true);
|
||||
|
|
@ -156,7 +154,7 @@ public class LoggingTest {
|
|||
public void run() {
|
||||
Sink mockSink = mock(GcpLogSink.class);
|
||||
ObservabilityConfig config = mock(ObservabilityConfig.class);
|
||||
LogHelper spyLogHelper = spy(new LogHelper(mockSink, TimeProvider.SYSTEM_TIME_PROVIDER));
|
||||
LogHelper spyLogHelper = spy(new LogHelper(mockSink));
|
||||
ConfigFilterHelper mockFilterHelper = mock(ConfigFilterHelper.class);
|
||||
InternalLoggingChannelInterceptor.Factory channelInterceptorFactory =
|
||||
new InternalLoggingChannelInterceptor.FactoryImpl(spyLogHelper, mockFilterHelper);
|
||||
|
|
@ -209,16 +207,16 @@ public class LoggingTest {
|
|||
FilterParams logAlwaysFilterParams = FilterParams.create(true, 0, 0);
|
||||
when(mockFilterHelper2.isMethodToBeLogged(any(MethodDescriptor.class)))
|
||||
.thenReturn(logAlwaysFilterParams);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_REQUEST_HEADER))
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.CLIENT_HEADER))
|
||||
.thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_RESPONSE_HEADER))
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.SERVER_HEADER))
|
||||
.thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_HALF_CLOSE)).thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_TRAILER)).thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_CANCEL)).thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_REQUEST_MESSAGE))
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.CLIENT_HALF_CLOSE)).thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.SERVER_TRAILER)).thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.CANCEL)).thenReturn(true);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.CLIENT_MESSAGE))
|
||||
.thenReturn(false);
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.GRPC_CALL_RESPONSE_MESSAGE))
|
||||
when(mockFilterHelper2.isEventToBeLogged(EventType.SERVER_MESSAGE))
|
||||
.thenReturn(false);
|
||||
|
||||
try (GcpObservability observability =
|
||||
|
|
|
|||
|
|
@ -46,13 +46,12 @@ public class ObservabilityConfigImplTest {
|
|||
private static final String EVENT_TYPES = "{\n"
|
||||
+ " \"enable_cloud_logging\": false,\n"
|
||||
+ " \"event_types\": "
|
||||
+ "[\"GRPC_CALL_REQUEST_HEADER\", \"GRPC_CALL_HALF_CLOSE\", \"GRPC_CALL_TRAILER\"]\n"
|
||||
+ "[\"CLIENT_HEADER\", \"CLIENT_HALF_CLOSE\", \"SERVER_TRAILER\"]\n"
|
||||
+ "}";
|
||||
|
||||
private static final String LOG_FILTERS = "{\n"
|
||||
+ " \"enable_cloud_logging\": true,\n"
|
||||
+ " \"destination_project_id\": \"grpc-testing\",\n"
|
||||
+ " \"flush_message_count\": 1000,\n"
|
||||
+ " \"log_filters\": [{\n"
|
||||
+ " \"pattern\": \"*/*\",\n"
|
||||
+ " \"header_bytes\": 4096,\n"
|
||||
|
|
@ -69,11 +68,6 @@ public class ObservabilityConfigImplTest {
|
|||
+ " \"destination_project_id\": \"grpc-testing\"\n"
|
||||
+ "}";
|
||||
|
||||
private static final String FLUSH_MESSAGE_COUNT = "{\n"
|
||||
+ " \"enable_cloud_logging\": true,\n"
|
||||
+ " \"flush_message_count\": 500\n"
|
||||
+ "}";
|
||||
|
||||
private static final String DISABLE_CLOUD_LOGGING = "{\n"
|
||||
+ " \"enable_cloud_logging\": false\n"
|
||||
+ "}";
|
||||
|
|
@ -146,7 +140,6 @@ public class ObservabilityConfigImplTest {
|
|||
assertFalse(observabilityConfig.isEnableCloudMonitoring());
|
||||
assertFalse(observabilityConfig.isEnableCloudTracing());
|
||||
assertNull(observabilityConfig.getDestinationProjectId());
|
||||
assertNull(observabilityConfig.getFlushMessageCount());
|
||||
assertNull(observabilityConfig.getLogFilters());
|
||||
assertNull(observabilityConfig.getEventTypes());
|
||||
}
|
||||
|
|
@ -158,7 +151,6 @@ public class ObservabilityConfigImplTest {
|
|||
assertFalse(observabilityConfig.isEnableCloudMonitoring());
|
||||
assertFalse(observabilityConfig.isEnableCloudTracing());
|
||||
assertNull(observabilityConfig.getDestinationProjectId());
|
||||
assertNull(observabilityConfig.getFlushMessageCount());
|
||||
assertNull(observabilityConfig.getLogFilters());
|
||||
assertNull(observabilityConfig.getEventTypes());
|
||||
}
|
||||
|
|
@ -170,19 +162,11 @@ public class ObservabilityConfigImplTest {
|
|||
assertThat(observabilityConfig.getDestinationProjectId()).isEqualTo("grpc-testing");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushMessageCount() throws Exception {
|
||||
observabilityConfig.parse(FLUSH_MESSAGE_COUNT);
|
||||
assertTrue(observabilityConfig.isEnableCloudLogging());
|
||||
assertThat(observabilityConfig.getFlushMessageCount()).isEqualTo(500L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logFilters() throws IOException {
|
||||
observabilityConfig.parse(LOG_FILTERS);
|
||||
assertTrue(observabilityConfig.isEnableCloudLogging());
|
||||
assertThat(observabilityConfig.getDestinationProjectId()).isEqualTo("grpc-testing");
|
||||
assertThat(observabilityConfig.getFlushMessageCount()).isEqualTo(1000L);
|
||||
List<LogFilter> logFilters = observabilityConfig.getLogFilters();
|
||||
assertThat(logFilters).hasSize(2);
|
||||
assertThat(logFilters.get(0).pattern).isEqualTo("*/*");
|
||||
|
|
@ -199,8 +183,8 @@ public class ObservabilityConfigImplTest {
|
|||
assertFalse(observabilityConfig.isEnableCloudLogging());
|
||||
List<EventType> eventTypes = observabilityConfig.getEventTypes();
|
||||
assertThat(eventTypes).isEqualTo(
|
||||
ImmutableList.of(EventType.GRPC_CALL_REQUEST_HEADER, EventType.GRPC_CALL_HALF_CLOSE,
|
||||
EventType.GRPC_CALL_TRAILER));
|
||||
ImmutableList.of(EventType.CLIENT_HEADER, EventType.CLIENT_HALF_CLOSE,
|
||||
EventType.SERVER_TRAILER));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -265,7 +249,6 @@ public class ObservabilityConfigImplTest {
|
|||
observabilityConfig.parseFile(configFile.getAbsolutePath());
|
||||
assertTrue(observabilityConfig.isEnableCloudLogging());
|
||||
assertThat(observabilityConfig.getDestinationProjectId()).isEqualTo("grpc-testing");
|
||||
assertThat(observabilityConfig.getFlushMessageCount()).isEqualTo(1000L);
|
||||
List<LogFilter> logFilters = observabilityConfig.getLogFilters();
|
||||
assertThat(logFilters).hasSize(2);
|
||||
assertThat(logFilters.get(0).pattern).isEqualTo("*/*");
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ public class ConfigFilterHelperTest {
|
|||
|
||||
private static final ImmutableList<EventType> configEventTypes =
|
||||
ImmutableList.of(
|
||||
EventType.GRPC_CALL_REQUEST_HEADER,
|
||||
EventType.GRPC_CALL_HALF_CLOSE,
|
||||
EventType.GRPC_CALL_TRAILER);
|
||||
EventType.CLIENT_HEADER,
|
||||
EventType.CLIENT_HALF_CLOSE,
|
||||
EventType.SERVER_TRAILER);
|
||||
|
||||
private final MethodDescriptor.Builder<Void, Void> builder = TestMethodDescriptors.voidMethod()
|
||||
.toBuilder();
|
||||
|
|
@ -171,13 +171,13 @@ public class ConfigFilterHelperTest {
|
|||
@Test
|
||||
public void checkEventToBeLogged_noFilter_defaultLogAllEventTypes() {
|
||||
List<EventType> eventList = new ArrayList<>();
|
||||
eventList.add(EventType.GRPC_CALL_REQUEST_HEADER);
|
||||
eventList.add(EventType.GRPC_CALL_RESPONSE_HEADER);
|
||||
eventList.add(EventType.GRPC_CALL_REQUEST_MESSAGE);
|
||||
eventList.add(EventType.GRPC_CALL_RESPONSE_MESSAGE);
|
||||
eventList.add(EventType.GRPC_CALL_HALF_CLOSE);
|
||||
eventList.add(EventType.GRPC_CALL_TRAILER);
|
||||
eventList.add(EventType.GRPC_CALL_CANCEL);
|
||||
eventList.add(EventType.CLIENT_HEADER);
|
||||
eventList.add(EventType.SERVER_HEADER);
|
||||
eventList.add(EventType.CLIENT_MESSAGE);
|
||||
eventList.add(EventType.SERVER_MESSAGE);
|
||||
eventList.add(EventType.CLIENT_HALF_CLOSE);
|
||||
eventList.add(EventType.SERVER_TRAILER);
|
||||
eventList.add(EventType.CANCEL);
|
||||
|
||||
for (EventType event : eventList) {
|
||||
assertTrue(configFilterHelper.isEventToBeLogged(event));
|
||||
|
|
@ -191,13 +191,13 @@ public class ConfigFilterHelperTest {
|
|||
configFilterHelper.setEventFilterSet();
|
||||
|
||||
List<EventType> eventList = new ArrayList<>();
|
||||
eventList.add(EventType.GRPC_CALL_REQUEST_HEADER);
|
||||
eventList.add(EventType.GRPC_CALL_RESPONSE_HEADER);
|
||||
eventList.add(EventType.GRPC_CALL_REQUEST_MESSAGE);
|
||||
eventList.add(EventType.GRPC_CALL_RESPONSE_MESSAGE);
|
||||
eventList.add(EventType.GRPC_CALL_HALF_CLOSE);
|
||||
eventList.add(EventType.GRPC_CALL_TRAILER);
|
||||
eventList.add(EventType.GRPC_CALL_CANCEL);
|
||||
eventList.add(EventType.CLIENT_HEADER);
|
||||
eventList.add(EventType.SERVER_HEADER);
|
||||
eventList.add(EventType.CLIENT_MESSAGE);
|
||||
eventList.add(EventType.SERVER_MESSAGE);
|
||||
eventList.add(EventType.CLIENT_HALF_CLOSE);
|
||||
eventList.add(EventType.SERVER_TRAILER);
|
||||
eventList.add(EventType.CANCEL);
|
||||
|
||||
for (EventType event : eventList) {
|
||||
assertFalse(configFilterHelper.isEventToBeLogged(event));
|
||||
|
|
@ -209,10 +209,10 @@ public class ConfigFilterHelperTest {
|
|||
when(mockConfig.getEventTypes()).thenReturn(configEventTypes);
|
||||
configFilterHelper.setEventFilterSet();
|
||||
|
||||
EventType logEventType = EventType.GRPC_CALL_REQUEST_HEADER;
|
||||
EventType logEventType = EventType.CLIENT_HEADER;
|
||||
assertTrue(configFilterHelper.isEventToBeLogged(logEventType));
|
||||
|
||||
EventType doNotLogEventType = EventType.GRPC_CALL_RESPONSE_MESSAGE;
|
||||
EventType doNotLogEventType = EventType.SERVER_MESSAGE;
|
||||
assertFalse(configFilterHelper.isEventToBeLogged(doNotLogEventType));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
clientInitial.put(keyA, dataA);
|
||||
clientInitial.put(keyB, dataB);
|
||||
interceptedLoggingCall.start(mockListener, clientInitial);
|
||||
verify(mockLogHelper).logRequestHeader(
|
||||
verify(mockLogHelper).logClientHeader(
|
||||
/*seq=*/ eq(1L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
|
|
@ -193,7 +193,7 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
ArgumentMatchers.isNull(),
|
||||
same(clientInitial),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString(),
|
||||
ArgumentMatchers.isNull());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -207,13 +207,14 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
{
|
||||
Metadata serverInitial = new Metadata();
|
||||
interceptedListener.get().onHeaders(serverInitial);
|
||||
verify(mockLogHelper).logResponseHeader(
|
||||
verify(mockLogHelper).logServerHeader(
|
||||
/*seq=*/ eq(2L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq("the-authority"),
|
||||
same(serverInitial),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString(),
|
||||
same(peer));
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -231,10 +232,11 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
/*seq=*/ eq(3L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventType.GRPC_CALL_REQUEST_MESSAGE),
|
||||
eq("the-authority"),
|
||||
eq(EventType.CLIENT_MESSAGE),
|
||||
same(request),
|
||||
eq(filterParams.messageBytes()),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
assertSame(request, actualRequest.get());
|
||||
|
|
@ -250,7 +252,8 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
/*seq=*/ eq(4L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq("the-authority"),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString());
|
||||
halfCloseCalled.get(1, TimeUnit.MILLISECONDS);
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -267,10 +270,11 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
/*seq=*/ eq(5L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventType.GRPC_CALL_RESPONSE_MESSAGE),
|
||||
eq("the-authority"),
|
||||
eq(EventType.SERVER_MESSAGE),
|
||||
same(response),
|
||||
eq(filterParams.messageBytes()),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
verify(mockListener).onMessage(same(response));
|
||||
|
|
@ -288,10 +292,11 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
/*seq=*/ eq(6L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq("the-authority"),
|
||||
same(status),
|
||||
same(trailers),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString(),
|
||||
same(peer));
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -308,7 +313,8 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
/*seq=*/ eq(7L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventLogger.LOGGER_CLIENT),
|
||||
eq("the-authority"),
|
||||
eq(EventLogger.CLIENT),
|
||||
anyString());
|
||||
cancelCalled.get(1, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
|
@ -349,7 +355,7 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
interceptedLoggingCall.start(mockListener, new Metadata());
|
||||
ArgumentCaptor<Duration> callOptTimeoutCaptor = ArgumentCaptor.forClass(Duration.class);
|
||||
verify(mockLogHelper, times(1))
|
||||
.logRequestHeader(
|
||||
.logClientHeader(
|
||||
anyLong(),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
|
|
@ -408,7 +414,7 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
Objects.requireNonNull(callFuture.get()).start(mockListener, new Metadata());
|
||||
ArgumentCaptor<Duration> contextTimeoutCaptor = ArgumentCaptor.forClass(Duration.class);
|
||||
verify(mockLogHelper, times(1))
|
||||
.logRequestHeader(
|
||||
.logClientHeader(
|
||||
anyLong(),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
|
|
@ -470,7 +476,7 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
Objects.requireNonNull(callFuture.get()).start(mockListener, new Metadata());
|
||||
ArgumentCaptor<Duration> timeoutCaptor = ArgumentCaptor.forClass(Duration.class);
|
||||
verify(mockLogHelper, times(1))
|
||||
.logRequestHeader(
|
||||
.logClientHeader(
|
||||
anyLong(),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
|
|
@ -633,8 +639,8 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
|
||||
@Test
|
||||
public void eventFilter_enabled() {
|
||||
when(mockFilterHelper.isEventToBeLogged(EventType.GRPC_CALL_REQUEST_HEADER)).thenReturn(false);
|
||||
when(mockFilterHelper.isEventToBeLogged(EventType.GRPC_CALL_RESPONSE_HEADER)).thenReturn(false);
|
||||
when(mockFilterHelper.isEventToBeLogged(EventType.CLIENT_HEADER)).thenReturn(false);
|
||||
when(mockFilterHelper.isEventToBeLogged(EventType.SERVER_HEADER)).thenReturn(false);
|
||||
|
||||
Channel channel = new Channel() {
|
||||
@Override
|
||||
|
|
@ -697,7 +703,7 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
|
||||
{
|
||||
interceptedLoggingCall.start(mockListener, new Metadata());
|
||||
verify(mockLogHelper, never()).logRequestHeader(
|
||||
verify(mockLogHelper, never()).logClientHeader(
|
||||
anyLong(),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
|
|
@ -710,10 +716,11 @@ public class InternalLoggingChannelInterceptorTest {
|
|||
AdditionalMatchers.or(ArgumentMatchers.isNull(),
|
||||
ArgumentMatchers.any()));
|
||||
interceptedListener.get().onHeaders(new Metadata());
|
||||
verify(mockLogHelper, never()).logResponseHeader(
|
||||
verify(mockLogHelper, never()).logServerHeader(
|
||||
anyLong(),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
any(Metadata.class),
|
||||
anyInt(),
|
||||
any(GrpcLogRecord.EventLogger.class),
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ public class InternalLoggingServerInterceptorTest {
|
|||
});
|
||||
// receive request header
|
||||
{
|
||||
verify(mockLogHelper).logRequestHeader(
|
||||
verify(mockLogHelper).logClientHeader(
|
||||
/*seq=*/ eq(1L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
|
|
@ -175,7 +175,7 @@ public class InternalLoggingServerInterceptorTest {
|
|||
ArgumentMatchers.isNull(),
|
||||
same(clientInitial),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString(),
|
||||
same(peer));
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -188,13 +188,14 @@ public class InternalLoggingServerInterceptorTest {
|
|||
{
|
||||
Metadata serverInitial = new Metadata();
|
||||
interceptedLoggingCall.get().sendHeaders(serverInitial);
|
||||
verify(mockLogHelper).logResponseHeader(
|
||||
verify(mockLogHelper).logServerHeader(
|
||||
/*seq=*/ eq(2L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq("the-authority"),
|
||||
same(serverInitial),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString(),
|
||||
ArgumentMatchers.isNull());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -212,10 +213,11 @@ public class InternalLoggingServerInterceptorTest {
|
|||
/*seq=*/ eq(3L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventType.GRPC_CALL_REQUEST_MESSAGE),
|
||||
eq("the-authority"),
|
||||
eq(EventType.CLIENT_MESSAGE),
|
||||
same(request),
|
||||
eq(filterParams.messageBytes()),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
verify(mockListener).onMessage(same(request));
|
||||
|
|
@ -231,7 +233,8 @@ public class InternalLoggingServerInterceptorTest {
|
|||
/*seq=*/ eq(4L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq("the-authority"),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
verify(mockListener).onHalfClose();
|
||||
|
|
@ -248,10 +251,11 @@ public class InternalLoggingServerInterceptorTest {
|
|||
/*seq=*/ eq(5L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventType.GRPC_CALL_RESPONSE_MESSAGE),
|
||||
eq("the-authority"),
|
||||
eq(EventType.SERVER_MESSAGE),
|
||||
same(response),
|
||||
eq(filterParams.messageBytes()),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
assertSame(response, actualResponse.get());
|
||||
|
|
@ -269,10 +273,11 @@ public class InternalLoggingServerInterceptorTest {
|
|||
/*seq=*/ eq(6L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq("the-authority"),
|
||||
same(status),
|
||||
same(trailers),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString(),
|
||||
ArgumentMatchers.isNull());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -290,7 +295,8 @@ public class InternalLoggingServerInterceptorTest {
|
|||
/*seq=*/ eq(7L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq("the-authority"),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString());
|
||||
verify(mockListener).onCancel();
|
||||
}
|
||||
|
|
@ -332,7 +338,7 @@ public class InternalLoggingServerInterceptorTest {
|
|||
});
|
||||
ArgumentCaptor<Duration> timeoutCaptor = ArgumentCaptor.forClass(Duration.class);
|
||||
verify(mockLogHelper, times(1))
|
||||
.logRequestHeader(
|
||||
.logClientHeader(
|
||||
/*seq=*/ eq(1L),
|
||||
eq("service"),
|
||||
eq("method"),
|
||||
|
|
@ -340,7 +346,7 @@ public class InternalLoggingServerInterceptorTest {
|
|||
timeoutCaptor.capture(),
|
||||
any(Metadata.class),
|
||||
eq(filterParams.headerBytes()),
|
||||
eq(EventLogger.LOGGER_SERVER),
|
||||
eq(EventLogger.SERVER),
|
||||
anyString(),
|
||||
ArgumentMatchers.isNull());
|
||||
verifyNoMoreInteractions(mockLogHelper);
|
||||
|
|
@ -480,7 +486,7 @@ public class InternalLoggingServerInterceptorTest {
|
|||
|
||||
@Test
|
||||
public void eventFilter_enabled() {
|
||||
when(mockFilterHelper.isEventToBeLogged(EventType.GRPC_CALL_HALF_CLOSE)).thenReturn(false);
|
||||
when(mockFilterHelper.isEventToBeLogged(EventType.CLIENT_HALF_CLOSE)).thenReturn(false);
|
||||
|
||||
Metadata clientInitial = new Metadata();
|
||||
final MethodDescriptor<byte[], byte[]> method =
|
||||
|
|
@ -551,6 +557,7 @@ public class InternalLoggingServerInterceptorTest {
|
|||
anyLong(),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
AdditionalMatchers.or(ArgumentMatchers.isNull(), anyString()),
|
||||
any(GrpcLogRecord.EventLogger.class),
|
||||
anyString());
|
||||
capturedListener.onCancel();
|
||||
|
|
|
|||
|
|
@ -26,26 +26,22 @@ import static org.junit.Assert.fail;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Duration;
|
||||
import com.google.protobuf.Timestamp;
|
||||
import com.google.protobuf.util.Durations;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor.Marshaller;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.gcp.observability.interceptors.LogHelper.PayloadBuilder;
|
||||
import io.grpc.gcp.observability.interceptors.LogHelper.PayloadBuilderHelper;
|
||||
import io.grpc.gcp.observability.logging.GcpLogSink;
|
||||
import io.grpc.gcp.observability.logging.Sink;
|
||||
import io.grpc.internal.TimeProvider;
|
||||
import io.grpc.observabilitylog.v1.Address;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.Address;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.EventLogger;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.EventType;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.LogLevel;
|
||||
import io.grpc.observabilitylog.v1.GrpcLogRecord.MetadataEntry;
|
||||
import io.grpc.observabilitylog.v1.Payload;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
|
@ -55,8 +51,7 @@ import java.net.InetAddress;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.HashMap;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -77,33 +72,12 @@ public class LogHelperTest {
|
|||
Metadata.Key.of("b", Metadata.ASCII_STRING_MARSHALLER);
|
||||
private static final Metadata.Key<String> KEY_C =
|
||||
Metadata.Key.of("c", Metadata.ASCII_STRING_MARSHALLER);
|
||||
private static final MetadataEntry ENTRY_A =
|
||||
MetadataEntry
|
||||
.newBuilder()
|
||||
.setKey(KEY_A.name())
|
||||
.setValue(ByteString.copyFrom(DATA_A.getBytes(StandardCharsets.US_ASCII)))
|
||||
.build();
|
||||
private static final MetadataEntry ENTRY_B =
|
||||
MetadataEntry
|
||||
.newBuilder()
|
||||
.setKey(KEY_B.name())
|
||||
.setValue(ByteString.copyFrom(DATA_B.getBytes(StandardCharsets.US_ASCII)))
|
||||
.build();
|
||||
private static final MetadataEntry ENTRY_C =
|
||||
MetadataEntry
|
||||
.newBuilder()
|
||||
.setKey(KEY_C.name())
|
||||
.setValue(ByteString.copyFrom(DATA_C.getBytes(StandardCharsets.US_ASCII)))
|
||||
.build();
|
||||
private static final int HEADER_LIMIT = 10;
|
||||
private static final int MESSAGE_LIMIT = Integer.MAX_VALUE;
|
||||
|
||||
private final Metadata nonEmptyMetadata = new Metadata();
|
||||
private final Sink sink = mock(GcpLogSink.class);
|
||||
private final Timestamp timestamp
|
||||
= Timestamp.newBuilder().setSeconds(9876).setNanos(54321).build();
|
||||
private final TimeProvider timeProvider = () -> TimeUnit.SECONDS.toNanos(9876) + 54321;
|
||||
private final LogHelper logHelper = new LogHelper(sink, timeProvider);
|
||||
private final LogHelper logHelper = new LogHelper(sink);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
|
@ -159,29 +133,26 @@ public class LogHelperTest {
|
|||
@Test
|
||||
public void metadataToProto_empty() {
|
||||
assertThat(metadataToProtoTestHelper(
|
||||
EventType.GRPC_CALL_REQUEST_HEADER, new Metadata(), Integer.MAX_VALUE))
|
||||
EventType.CLIENT_HEADER, new Metadata(), Integer.MAX_VALUE))
|
||||
.isEqualTo(GrpcLogRecord.newBuilder()
|
||||
.setEventType(EventType.GRPC_CALL_REQUEST_HEADER)
|
||||
.setMetadata(
|
||||
GrpcLogRecord.Metadata.getDefaultInstance())
|
||||
.setType(EventType.CLIENT_HEADER)
|
||||
.setPayload(
|
||||
Payload.newBuilder().putAllMetadata(new HashMap<>()))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void metadataToProto() {
|
||||
int nonEmptyMetadataSize = 30;
|
||||
Payload.Builder payloadBuilder = Payload.newBuilder()
|
||||
.putMetadata("a", DATA_A)
|
||||
.putMetadata("b", DATA_B)
|
||||
.putMetadata("c", DATA_C);
|
||||
|
||||
assertThat(metadataToProtoTestHelper(
|
||||
EventType.GRPC_CALL_REQUEST_HEADER, nonEmptyMetadata, Integer.MAX_VALUE))
|
||||
EventType.CLIENT_HEADER, nonEmptyMetadata, Integer.MAX_VALUE))
|
||||
.isEqualTo(GrpcLogRecord.newBuilder()
|
||||
.setEventType(EventType.GRPC_CALL_REQUEST_HEADER)
|
||||
.setMetadata(
|
||||
GrpcLogRecord.Metadata
|
||||
.newBuilder()
|
||||
.addEntry(ENTRY_A)
|
||||
.addEntry(ENTRY_B)
|
||||
.addEntry(ENTRY_C)
|
||||
.build())
|
||||
.setPayloadSize(nonEmptyMetadataSize)
|
||||
.setType(EventType.CLIENT_HEADER)
|
||||
.setPayload(payloadBuilder)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
|
@ -193,43 +164,44 @@ public class LogHelperTest {
|
|||
@Test
|
||||
public void metadataToProto_truncated() {
|
||||
// 0 byte limit not enough for any metadata
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 0).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata.getDefaultInstance());
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 0).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder()
|
||||
.putAllMetadata(new HashMap<>())
|
||||
.build());
|
||||
// not enough bytes for first key value
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 9).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata.getDefaultInstance());
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 9).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder()
|
||||
.putAllMetadata(new HashMap<>())
|
||||
.build());
|
||||
// enough for first key value
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 10).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata
|
||||
.newBuilder()
|
||||
.addEntry(ENTRY_A)
|
||||
.build());
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 10).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder().putMetadata("a", DATA_A).build());
|
||||
// Test edge cases for >= 2 key values
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 19).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata
|
||||
.newBuilder()
|
||||
.addEntry(ENTRY_A)
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 19).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder().putMetadata("a", DATA_A).build());
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 20).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder()
|
||||
.putMetadata("a", DATA_A)
|
||||
.putMetadata("b", DATA_B)
|
||||
.build());
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 20).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata
|
||||
.newBuilder()
|
||||
.addEntry(ENTRY_A)
|
||||
.addEntry(ENTRY_B)
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 29).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder()
|
||||
.putMetadata("a", DATA_A)
|
||||
.putMetadata("b", DATA_B)
|
||||
.build());
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 29).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata
|
||||
.newBuilder()
|
||||
.addEntry(ENTRY_A)
|
||||
.addEntry(ENTRY_B)
|
||||
.build());
|
||||
|
||||
// not truncated: enough for all keys
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 30).payload.build())
|
||||
.isEqualTo(io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata
|
||||
.newBuilder()
|
||||
.addEntry(ENTRY_A)
|
||||
.addEntry(ENTRY_B)
|
||||
.addEntry(ENTRY_C)
|
||||
assertThat(LogHelper.createMetadataProto(nonEmptyMetadata, 30).payloadBuilder.build())
|
||||
.isEqualTo(
|
||||
io.grpc.observabilitylog.v1.Payload.newBuilder()
|
||||
.putMetadata("a", DATA_A)
|
||||
.putMetadata("b", DATA_B)
|
||||
.putMetadata("c", DATA_C)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
|
@ -240,8 +212,11 @@ public class LogHelperTest {
|
|||
StandardCharsets.US_ASCII);
|
||||
assertThat(messageTestHelper(bytes, Integer.MAX_VALUE))
|
||||
.isEqualTo(GrpcLogRecord.newBuilder()
|
||||
.setMessage(ByteString.copyFrom(bytes))
|
||||
.setPayloadSize(bytes.length)
|
||||
.setPayload(
|
||||
Payload.newBuilder()
|
||||
.setMessage(
|
||||
ByteString.copyFrom(bytes))
|
||||
.setMessageLength(bytes.length))
|
||||
.build());
|
||||
}
|
||||
|
||||
|
|
@ -252,16 +227,23 @@ public class LogHelperTest {
|
|||
StandardCharsets.US_ASCII);
|
||||
assertThat(messageTestHelper(bytes, 0))
|
||||
.isEqualTo(GrpcLogRecord.newBuilder()
|
||||
.setPayloadSize(bytes.length)
|
||||
.setPayload(
|
||||
Payload.newBuilder()
|
||||
.setMessageLength(bytes.length))
|
||||
.setPayloadTruncated(true)
|
||||
.build());
|
||||
|
||||
int limit = 10;
|
||||
String truncatedMessage = "this is a ";
|
||||
assertThat(messageTestHelper(bytes, limit))
|
||||
.isEqualTo(GrpcLogRecord.newBuilder()
|
||||
.setMessage(ByteString.copyFrom(truncatedMessage.getBytes(StandardCharsets.US_ASCII)))
|
||||
.setPayloadSize(bytes.length)
|
||||
.isEqualTo(
|
||||
GrpcLogRecord.newBuilder()
|
||||
.setPayload(
|
||||
Payload.newBuilder()
|
||||
.setMessage(
|
||||
ByteString.copyFrom(
|
||||
truncatedMessage.getBytes(StandardCharsets.US_ASCII)))
|
||||
.setMessageLength(bytes.length))
|
||||
.setPayloadTruncated(true)
|
||||
.build());
|
||||
}
|
||||
|
|
@ -274,30 +256,28 @@ public class LogHelperTest {
|
|||
String methodName = "method";
|
||||
String authority = "authority";
|
||||
Duration timeout = Durations.fromMillis(1234);
|
||||
String rpcId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
String callId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
InetAddress address = InetAddress.getByName("127.0.0.1");
|
||||
int port = 12345;
|
||||
InetSocketAddress peerAddress = new InetSocketAddress(address, port);
|
||||
|
||||
GrpcLogRecord.Builder builder =
|
||||
metadataToProtoTestHelper(EventType.GRPC_CALL_REQUEST_HEADER, nonEmptyMetadata,
|
||||
metadataToProtoTestHelper(EventType.CLIENT_HEADER, nonEmptyMetadata,
|
||||
HEADER_LIMIT)
|
||||
.toBuilder()
|
||||
.setTimestamp(timestamp)
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_REQUEST_HEADER)
|
||||
.setEventLogger(EventLogger.LOGGER_CLIENT)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setRpcId(rpcId);
|
||||
builder.setAuthority(authority)
|
||||
.setTimeout(timeout);
|
||||
.setType(EventType.CLIENT_HEADER)
|
||||
.setLogger(EventLogger.CLIENT)
|
||||
.setCallId(callId);
|
||||
builder.setAuthority(authority);
|
||||
builder.setPayload(builder.getPayload().toBuilder().setTimeout(timeout).build());
|
||||
GrpcLogRecord base = builder.build();
|
||||
|
||||
// logged on client
|
||||
{
|
||||
logHelper.logRequestHeader(
|
||||
logHelper.logClientHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
|
|
@ -305,15 +285,15 @@ public class LogHelperTest {
|
|||
timeout,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
null);
|
||||
verify(sink).write(base);
|
||||
}
|
||||
|
||||
// logged on server
|
||||
{
|
||||
logHelper.logRequestHeader(
|
||||
logHelper.logClientHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
|
|
@ -321,19 +301,19 @@ public class LogHelperTest {
|
|||
timeout,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
peerAddress);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.setPeerAddress(LogHelper.socketAddressToProto(peerAddress))
|
||||
.setEventLogger(EventLogger.LOGGER_SERVER)
|
||||
.setPeer(LogHelper.socketAddressToProto(peerAddress))
|
||||
.setLogger(EventLogger.SERVER)
|
||||
.build());
|
||||
}
|
||||
|
||||
// timeout is null
|
||||
{
|
||||
logHelper.logRequestHeader(
|
||||
logHelper.logClientHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
|
|
@ -341,18 +321,18 @@ public class LogHelperTest {
|
|||
null,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
null);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.clearTimeout()
|
||||
.setPayload(base.getPayload().toBuilder().clearTimeout().build())
|
||||
.build());
|
||||
}
|
||||
|
||||
// peerAddress is not null (error on client)
|
||||
try {
|
||||
logHelper.logRequestHeader(
|
||||
logHelper.logClientHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
|
|
@ -360,8 +340,8 @@ public class LogHelperTest {
|
|||
timeout,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
peerAddress);
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
|
|
@ -374,68 +354,71 @@ public class LogHelperTest {
|
|||
long seqId = 1;
|
||||
String serviceName = "service";
|
||||
String methodName = "method";
|
||||
String rpcId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
String authority = "authority";
|
||||
String callId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
InetAddress address = InetAddress.getByName("127.0.0.1");
|
||||
int port = 12345;
|
||||
InetSocketAddress peerAddress = new InetSocketAddress(address, port);
|
||||
|
||||
GrpcLogRecord.Builder builder =
|
||||
metadataToProtoTestHelper(EventType.GRPC_CALL_RESPONSE_HEADER, nonEmptyMetadata,
|
||||
metadataToProtoTestHelper(EventType.SERVER_HEADER, nonEmptyMetadata,
|
||||
HEADER_LIMIT)
|
||||
.toBuilder()
|
||||
.setTimestamp(timestamp)
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_RESPONSE_HEADER)
|
||||
.setEventLogger(EventLogger.LOGGER_CLIENT)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setRpcId(rpcId);
|
||||
builder.setPeerAddress(LogHelper.socketAddressToProto(peerAddress));
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.SERVER_HEADER)
|
||||
.setLogger(EventLogger.CLIENT)
|
||||
.setCallId(callId);
|
||||
builder.setPeer(LogHelper.socketAddressToProto(peerAddress));
|
||||
GrpcLogRecord base = builder.build();
|
||||
|
||||
// logged on client
|
||||
{
|
||||
logHelper.logResponseHeader(
|
||||
logHelper.logServerHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
peerAddress);
|
||||
verify(sink).write(base);
|
||||
}
|
||||
|
||||
// logged on server
|
||||
{
|
||||
logHelper.logResponseHeader(
|
||||
logHelper.logServerHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
null);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.setEventLogger(EventLogger.LOGGER_SERVER)
|
||||
.clearPeerAddress()
|
||||
.setLogger(EventLogger.SERVER)
|
||||
.clearPeer()
|
||||
.build());
|
||||
}
|
||||
|
||||
// peerAddress is not null (error on server)
|
||||
try {
|
||||
logHelper.logResponseHeader(
|
||||
logHelper.logServerHeader(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
peerAddress);
|
||||
|
||||
fail();
|
||||
|
|
@ -450,27 +433,30 @@ public class LogHelperTest {
|
|||
long seqId = 1;
|
||||
String serviceName = "service";
|
||||
String methodName = "method";
|
||||
String rpcId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
String authority = "authority";
|
||||
String callId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
InetAddress address = InetAddress.getByName("127.0.0.1");
|
||||
int port = 12345;
|
||||
InetSocketAddress peerAddress = new InetSocketAddress(address, port);
|
||||
InetSocketAddress peer = new InetSocketAddress(address, port);
|
||||
Status statusDescription = Status.INTERNAL.withDescription("test description");
|
||||
|
||||
GrpcLogRecord.Builder builder =
|
||||
metadataToProtoTestHelper(EventType.GRPC_CALL_RESPONSE_HEADER, nonEmptyMetadata,
|
||||
metadataToProtoTestHelper(EventType.SERVER_HEADER, nonEmptyMetadata,
|
||||
HEADER_LIMIT)
|
||||
.toBuilder()
|
||||
.setTimestamp(timestamp)
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_TRAILER)
|
||||
.setEventLogger(EventLogger.LOGGER_CLIENT)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.SERVER_TRAILER)
|
||||
.setLogger(EventLogger.CLIENT)
|
||||
.setCallId(callId);
|
||||
builder.setPeer(LogHelper.socketAddressToProto(peer));
|
||||
builder.setPayload(
|
||||
builder.getPayload().toBuilder()
|
||||
.setStatusCode(Status.INTERNAL.getCode().value())
|
||||
.setStatusMessage("test description")
|
||||
.setRpcId(rpcId);
|
||||
builder.setPeerAddress(LogHelper.socketAddressToProto(peerAddress));
|
||||
.build());
|
||||
GrpcLogRecord base = builder.build();
|
||||
|
||||
// logged on client
|
||||
|
|
@ -479,12 +465,13 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
statusDescription,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
peerAddress);
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
peer);
|
||||
verify(sink).write(base);
|
||||
}
|
||||
|
||||
|
|
@ -494,16 +481,17 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
statusDescription,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId,
|
||||
EventLogger.SERVER,
|
||||
callId,
|
||||
null);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.clearPeerAddress()
|
||||
.setEventLogger(EventLogger.LOGGER_SERVER)
|
||||
.clearPeer()
|
||||
.setLogger(EventLogger.SERVER)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
|
@ -513,15 +501,16 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
statusDescription,
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
null);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.clearPeerAddress()
|
||||
.clearPeer()
|
||||
.build());
|
||||
}
|
||||
|
||||
|
|
@ -531,15 +520,16 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
statusDescription.getCode().toStatus(),
|
||||
nonEmptyMetadata,
|
||||
HEADER_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId,
|
||||
peerAddress);
|
||||
EventLogger.CLIENT,
|
||||
callId,
|
||||
peer);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.clearStatusMessage()
|
||||
.setPayload(base.getPayload().toBuilder().clearStatusMessage().build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
|
@ -551,10 +541,9 @@ public class LogHelperTest {
|
|||
Metadata metadata = new Metadata();
|
||||
metadata.put(key, new byte[1]);
|
||||
int zeroHeaderBytes = 0;
|
||||
PayloadBuilder<io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata.Builder> pair =
|
||||
PayloadBuilderHelper<Payload.Builder> pair =
|
||||
LogHelper.createMetadataProto(metadata, zeroHeaderBytes);
|
||||
assertThat(Objects.requireNonNull(Iterables.getOnlyElement(pair.payload.getEntryBuilderList()))
|
||||
.getKey()).isEqualTo(key.name());
|
||||
assertThat(pair.payloadBuilder.build().getMetadataMap().containsKey(key.name())).isTrue();
|
||||
assertFalse(pair.truncated);
|
||||
}
|
||||
|
||||
|
|
@ -565,9 +554,9 @@ public class LogHelperTest {
|
|||
Metadata metadata = new Metadata();
|
||||
metadata.put(key, new byte[1]);
|
||||
int unlimitedHeaderBytes = Integer.MAX_VALUE;
|
||||
PayloadBuilder<io.grpc.observabilitylog.v1.GrpcLogRecord.Metadata.Builder> pair
|
||||
PayloadBuilderHelper<Payload.Builder> pair
|
||||
= LogHelper.createMetadataProto(metadata, unlimitedHeaderBytes);
|
||||
assertThat(pair.payload.getEntryBuilderList()).isEmpty();
|
||||
assertThat(pair.payloadBuilder.getMetadataMap()).isEmpty();
|
||||
assertFalse(pair.truncated);
|
||||
}
|
||||
|
||||
|
|
@ -576,19 +565,19 @@ public class LogHelperTest {
|
|||
long seqId = 1;
|
||||
String serviceName = "service";
|
||||
String methodName = "method";
|
||||
String rpcId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
String authority = "authority";
|
||||
String callId = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
byte[] message = new byte[100];
|
||||
|
||||
GrpcLogRecord.Builder builder = messageTestHelper(message, MESSAGE_LIMIT)
|
||||
.toBuilder()
|
||||
.setTimestamp(timestamp)
|
||||
.setSequenceId(seqId)
|
||||
.setServiceName(serviceName)
|
||||
.setMethodName(methodName)
|
||||
.setEventType(EventType.GRPC_CALL_REQUEST_MESSAGE)
|
||||
.setEventLogger(EventLogger.LOGGER_CLIENT)
|
||||
.setLogLevel(LogLevel.LOG_LEVEL_DEBUG)
|
||||
.setRpcId(rpcId);
|
||||
.setAuthority(authority)
|
||||
.setType(EventType.CLIENT_MESSAGE)
|
||||
.setLogger(EventLogger.CLIENT)
|
||||
.setCallId(callId);
|
||||
GrpcLogRecord base = builder.build();
|
||||
// request message
|
||||
{
|
||||
|
|
@ -596,11 +585,12 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
EventType.GRPC_CALL_REQUEST_MESSAGE,
|
||||
authority,
|
||||
EventType.CLIENT_MESSAGE,
|
||||
message,
|
||||
MESSAGE_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId);
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
verify(sink).write(base);
|
||||
}
|
||||
// response message, logged on client
|
||||
|
|
@ -609,14 +599,15 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
EventType.GRPC_CALL_RESPONSE_MESSAGE,
|
||||
authority,
|
||||
EventType.SERVER_MESSAGE,
|
||||
message,
|
||||
MESSAGE_LIMIT,
|
||||
EventLogger.LOGGER_CLIENT,
|
||||
rpcId);
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.setEventType(EventType.GRPC_CALL_RESPONSE_MESSAGE)
|
||||
.setType(EventType.SERVER_MESSAGE)
|
||||
.build());
|
||||
}
|
||||
// request message, logged on server
|
||||
|
|
@ -625,14 +616,15 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
EventType.GRPC_CALL_REQUEST_MESSAGE,
|
||||
authority,
|
||||
EventType.CLIENT_MESSAGE,
|
||||
message,
|
||||
MESSAGE_LIMIT,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId);
|
||||
EventLogger.SERVER,
|
||||
callId);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.setEventLogger(EventLogger.LOGGER_SERVER)
|
||||
.setLogger(EventLogger.SERVER)
|
||||
.build());
|
||||
}
|
||||
// response message, logged on server
|
||||
|
|
@ -641,15 +633,34 @@ public class LogHelperTest {
|
|||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
EventType.GRPC_CALL_RESPONSE_MESSAGE,
|
||||
authority,
|
||||
EventType.SERVER_MESSAGE,
|
||||
message,
|
||||
MESSAGE_LIMIT,
|
||||
EventLogger.LOGGER_SERVER,
|
||||
rpcId);
|
||||
EventLogger.SERVER,
|
||||
callId);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.setEventType(EventType.GRPC_CALL_RESPONSE_MESSAGE)
|
||||
.setEventLogger(EventLogger.LOGGER_SERVER)
|
||||
.setType(EventType.SERVER_MESSAGE)
|
||||
.setLogger(EventLogger.SERVER)
|
||||
.build());
|
||||
}
|
||||
// message is not of type : com.google.protobuf.Message or byte[]
|
||||
{
|
||||
logHelper.logRpcMessage(
|
||||
seqId,
|
||||
serviceName,
|
||||
methodName,
|
||||
authority,
|
||||
EventType.CLIENT_MESSAGE,
|
||||
"message",
|
||||
MESSAGE_LIMIT,
|
||||
EventLogger.CLIENT,
|
||||
callId);
|
||||
verify(sink).write(
|
||||
base.toBuilder()
|
||||
.clearPayload()
|
||||
.clearPayloadTruncated()
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
|
@ -667,21 +678,19 @@ public class LogHelperTest {
|
|||
private static GrpcLogRecord metadataToProtoTestHelper(
|
||||
EventType type, Metadata metadata, int maxHeaderBytes) {
|
||||
GrpcLogRecord.Builder builder = GrpcLogRecord.newBuilder();
|
||||
PayloadBuilder<GrpcLogRecord.Metadata.Builder> pair
|
||||
PayloadBuilderHelper<Payload.Builder> pair
|
||||
= LogHelper.createMetadataProto(metadata, maxHeaderBytes);
|
||||
builder.setMetadata(pair.payload);
|
||||
builder.setPayloadSize(pair.size);
|
||||
builder.setPayload(pair.payloadBuilder);
|
||||
builder.setPayloadTruncated(pair.truncated);
|
||||
builder.setEventType(type);
|
||||
builder.setType(type);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static GrpcLogRecord messageTestHelper(byte[] message, int maxMessageBytes) {
|
||||
GrpcLogRecord.Builder builder = GrpcLogRecord.newBuilder();
|
||||
PayloadBuilder<ByteString> pair
|
||||
PayloadBuilderHelper<Payload.Builder> pair
|
||||
= LogHelper.createMessageProto(message, maxMessageBytes);
|
||||
builder.setMessage(pair.payload);
|
||||
builder.setPayloadSize(pair.size);
|
||||
builder.setPayload(pair.payloadBuilder);
|
||||
builder.setPayloadTruncated(pair.truncated);
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package io.grpc.gcp.observability.logging;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyIterable;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
|
@ -67,7 +66,6 @@ public class GcpLogSinkTest {
|
|||
private static final ImmutableMap<String, String> CUSTOM_TAGS =
|
||||
ImmutableMap.of("KEY1", "Value1",
|
||||
"KEY2", "VALUE2");
|
||||
private static final long FLUSH_LIMIT = 10L;
|
||||
// gRPC is expected to always use this log name when reporting to GCP cloud logging.
|
||||
private static final String EXPECTED_LOG_NAME =
|
||||
"microservices.googleapis.com%2Fobservability%2Fgrpc";
|
||||
|
|
@ -77,28 +75,33 @@ public class GcpLogSinkTest {
|
|||
private static final String METHOD_NAME = "method";
|
||||
private static final String AUTHORITY = "authority";
|
||||
private static final Duration TIMEOUT = Durations.fromMillis(1234);
|
||||
private static final String RPC_ID = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
private static final String CALL_ID = "d155e885-9587-4e77-81f7-3aa5a443d47f";
|
||||
private static final GrpcLogRecord LOG_PROTO = GrpcLogRecord.newBuilder()
|
||||
.setSequenceId(SEQ_ID)
|
||||
.setServiceName(SERVICE_NAME)
|
||||
.setMethodName(METHOD_NAME)
|
||||
.setAuthority(AUTHORITY)
|
||||
.setTimeout(TIMEOUT)
|
||||
.setEventType(EventType.GRPC_CALL_REQUEST_HEADER)
|
||||
.setEventLogger(EventLogger.LOGGER_CLIENT)
|
||||
.setRpcId(RPC_ID)
|
||||
.setPayload(io.grpc.observabilitylog.v1.Payload.newBuilder().setTimeout(TIMEOUT))
|
||||
.setType(EventType.CLIENT_HEADER)
|
||||
.setLogger(EventLogger.CLIENT)
|
||||
.setCallId(CALL_ID)
|
||||
.build();
|
||||
// .putFields("timeout", Value.newBuilder().setStringValue("1.234s").build())
|
||||
private static final Struct struct =
|
||||
Struct.newBuilder()
|
||||
.putFields("timeout", Value.newBuilder().setStringValue("1.234s").build())
|
||||
.build();
|
||||
private static final Struct EXPECTED_STRUCT_LOG_PROTO = Struct.newBuilder()
|
||||
.putFields("sequence_id", Value.newBuilder().setStringValue(String.valueOf(SEQ_ID)).build())
|
||||
.putFields("service_name", Value.newBuilder().setStringValue(SERVICE_NAME).build())
|
||||
.putFields("method_name", Value.newBuilder().setStringValue(METHOD_NAME).build())
|
||||
.putFields("sequenceId", Value.newBuilder().setStringValue(String.valueOf(SEQ_ID)).build())
|
||||
.putFields("serviceName", Value.newBuilder().setStringValue(SERVICE_NAME).build())
|
||||
.putFields("methodName", Value.newBuilder().setStringValue(METHOD_NAME).build())
|
||||
.putFields("authority", Value.newBuilder().setStringValue(AUTHORITY).build())
|
||||
.putFields("timeout", Value.newBuilder().setStringValue("1.234s").build())
|
||||
.putFields("event_type", Value.newBuilder().setStringValue(
|
||||
String.valueOf(EventType.GRPC_CALL_REQUEST_HEADER)).build())
|
||||
.putFields("event_logger", Value.newBuilder().setStringValue(
|
||||
String.valueOf(EventLogger.LOGGER_CLIENT)).build())
|
||||
.putFields("rpc_id", Value.newBuilder().setStringValue(RPC_ID).build())
|
||||
.putFields("payload", Value.newBuilder().setStructValue(struct).build())
|
||||
.putFields("type", Value.newBuilder().setStringValue(
|
||||
String.valueOf(EventType.CLIENT_HEADER)).build())
|
||||
.putFields("logger", Value.newBuilder().setStringValue(
|
||||
String.valueOf(EventLogger.CLIENT)).build())
|
||||
.putFields("callId", Value.newBuilder().setStringValue(CALL_ID).build())
|
||||
.build();
|
||||
@Mock
|
||||
private Logging mockLogging;
|
||||
|
|
@ -107,7 +110,7 @@ public class GcpLogSinkTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void verifyWrite() throws Exception {
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
CUSTOM_TAGS, FLUSH_LIMIT, Collections.emptySet());
|
||||
CUSTOM_TAGS, Collections.emptySet());
|
||||
sink.write(LOG_PROTO);
|
||||
|
||||
ArgumentCaptor<Collection<LogEntry>> logEntrySetCaptor = ArgumentCaptor.forClass(
|
||||
|
|
@ -125,7 +128,7 @@ public class GcpLogSinkTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void verifyWriteWithTags() {
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
CUSTOM_TAGS, FLUSH_LIMIT, Collections.emptySet());
|
||||
CUSTOM_TAGS, Collections.emptySet());
|
||||
MonitoredResource expectedMonitoredResource = GcpLogSink.getResource(LOCATION_TAGS);
|
||||
sink.write(LOG_PROTO);
|
||||
|
||||
|
|
@ -149,7 +152,7 @@ public class GcpLogSinkTest {
|
|||
Map<String, String> emptyCustomTags = null;
|
||||
Map<String, String> expectedEmptyLabels = new HashMap<>();
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
emptyCustomTags, FLUSH_LIMIT, Collections.emptySet());
|
||||
emptyCustomTags, Collections.emptySet());
|
||||
sink.write(LOG_PROTO);
|
||||
|
||||
ArgumentCaptor<Collection<LogEntry>> logEntrySetCaptor = ArgumentCaptor.forClass(
|
||||
|
|
@ -170,7 +173,7 @@ public class GcpLogSinkTest {
|
|||
Map<String, String> expectedLabels = GcpLogSink.getCustomTags(emptyCustomTags, LOCATION_TAGS,
|
||||
destinationProjectId);
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, destinationProjectId, LOCATION_TAGS,
|
||||
emptyCustomTags, FLUSH_LIMIT, Collections.emptySet());
|
||||
emptyCustomTags, Collections.emptySet());
|
||||
sink.write(LOG_PROTO);
|
||||
|
||||
ArgumentCaptor<Collection<LogEntry>> logEntrySetCaptor = ArgumentCaptor.forClass(
|
||||
|
|
@ -183,24 +186,10 @@ public class GcpLogSinkTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyFlush() {
|
||||
long lowerFlushLimit = 2L;
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
CUSTOM_TAGS, lowerFlushLimit, Collections.emptySet());
|
||||
sink.write(LOG_PROTO);
|
||||
verify(mockLogging, never()).flush();
|
||||
sink.write(LOG_PROTO);
|
||||
verify(mockLogging, times(1)).flush();
|
||||
sink.write(LOG_PROTO);
|
||||
sink.write(LOG_PROTO);
|
||||
verify(mockLogging, times(2)).flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyClose() throws Exception {
|
||||
GcpLogSink sink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
CUSTOM_TAGS, FLUSH_LIMIT, Collections.emptySet());
|
||||
CUSTOM_TAGS, Collections.emptySet());
|
||||
sink.write(LOG_PROTO);
|
||||
verify(mockLogging, times(1)).write(anyIterable());
|
||||
sink.close();
|
||||
|
|
@ -211,7 +200,7 @@ public class GcpLogSinkTest {
|
|||
@Test
|
||||
public void verifyExclude() throws Exception {
|
||||
Sink mockSink = new GcpLogSink(mockLogging, DEST_PROJECT_NAME, LOCATION_TAGS,
|
||||
CUSTOM_TAGS, FLUSH_LIMIT, Collections.singleton("service"));
|
||||
CUSTOM_TAGS, Collections.singleton("service"));
|
||||
mockSink.write(LOG_PROTO);
|
||||
verifyNoInteractions(mockLogging);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue