com.netflix.zuul.context.Debug Maven / Gradle / Ivy
/*
* Copyright 2018 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.zuul.context;
import com.netflix.zuul.message.Header;
import com.netflix.zuul.message.ZuulMessage;
import com.netflix.zuul.message.http.HttpRequestInfo;
import com.netflix.zuul.message.http.HttpResponseInfo;
import io.netty.util.ReferenceCounted;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
/**
* Simple wrapper class around the RequestContext for setting and managing Request level Debug data.
* @author Mikey Cohen
* Date: 1/25/12
* Time: 2:26 PM
*/
public class Debug {
private static final Logger LOG = LoggerFactory.getLogger(Debug.class);
public static void setDebugRequest(SessionContext ctx, boolean bDebug) {
ctx.setDebugRequest(bDebug);
}
public static void setDebugRequestHeadersOnly(SessionContext ctx, boolean bHeadersOnly) {
ctx.setDebugRequestHeadersOnly(bHeadersOnly);
}
public static boolean debugRequestHeadersOnly(SessionContext ctx) {
return ctx.debugRequestHeadersOnly();
}
public static void setDebugRouting(SessionContext ctx, boolean bDebug) {
ctx.setDebugRouting(bDebug);
}
public static boolean debugRequest(SessionContext ctx) {
return ctx.debugRequest();
}
public static boolean debugRouting(SessionContext ctx) {
return ctx.debugRouting();
}
public static void addRoutingDebug(SessionContext ctx, String line) {
List rd = getRoutingDebug(ctx);
rd.add(line);
}
public static void addRequestDebugForMessage(SessionContext ctx, ZuulMessage message, String prefix) {
for (Header header : message.getHeaders().entries()) {
Debug.addRequestDebug(ctx, prefix + " " + header.getKey() + " " + header.getValue());
}
if (message.hasBody()) {
String bodyStr = message.getBodyAsText();
Debug.addRequestDebug(ctx, prefix + " " + bodyStr);
}
}
/**
*
* @return Returns the list of routiong debug messages
*/
public static List getRoutingDebug(SessionContext ctx) {
List rd = (List) ctx.get("routingDebug");
if (rd == null) {
rd = new ArrayList();
ctx.set("routingDebug", rd);
}
return rd;
}
/**
* Adds a line to the Request debug messages
* @param line
*/
public static void addRequestDebug(SessionContext ctx, String line) {
List rd = getRequestDebug(ctx);
rd.add(line);
}
/**
*
* @return returns the list of request debug messages
*/
public static List getRequestDebug(SessionContext ctx) {
List rd = (List) ctx.get("requestDebug");
if (rd == null) {
rd = new ArrayList();
ctx.set("requestDebug", rd);
}
return rd;
}
/**
* Adds debug details about changes that a given filter made to the request context.
* @param filterName
* @param copy
*/
public static void compareContextState(String filterName, SessionContext context, SessionContext copy) {
// TODO - only comparing Attributes. Need to compare the messages too.
// Ensure that the routingDebug property already exists, otherwise we'll have a ConcurrentModificationException
// below
getRoutingDebug(context);
Iterator it = context.keySet().iterator();
String key = it.next();
while (key != null) {
if ((!key.equals("routingDebug") && !key.equals("requestDebug"))) {
Object newValue = context.get(key);
Object oldValue = copy.get(key);
if (!(newValue instanceof ReferenceCounted) && !(oldValue instanceof ReferenceCounted)) {
if (oldValue == null && newValue != null) {
addRoutingDebug(context, "{" + filterName + "} added " + key + "=" + newValue.toString());
} else if (oldValue != null && newValue != null) {
if (!(oldValue.equals(newValue))) {
addRoutingDebug(context, "{" + filterName + "} changed " + key + "=" + newValue.toString());
}
}
}
}
if (it.hasNext()) {
key = it.next();
} else {
key = null;
}
}
}
public static Observable writeDebugRequest(
SessionContext context, HttpRequestInfo request, boolean isInbound) {
Observable obs = null;
if (Debug.debugRequest(context)) {
String prefix = isInbound ? "REQUEST_INBOUND" : "REQUEST_OUTBOUND";
String arrow = ">";
Debug.addRequestDebug(
context,
String.format(
"%s:: %s LINE: %s %s %s",
prefix,
arrow,
request.getMethod().toUpperCase(),
request.getPathAndQuery(),
request.getProtocol()));
obs = Debug.writeDebugMessage(context, request, prefix, arrow);
}
if (obs == null) {
obs = Observable.just(Boolean.FALSE);
}
return obs;
}
public static Observable writeDebugResponse(
SessionContext context, HttpResponseInfo response, boolean isInbound) {
Observable obs = null;
if (Debug.debugRequest(context)) {
String prefix = isInbound ? "RESPONSE_INBOUND" : "RESPONSE_OUTBOUND";
String arrow = "<";
Debug.addRequestDebug(context, String.format("%s:: %s STATUS: %s", prefix, arrow, response.getStatus()));
obs = Debug.writeDebugMessage(context, response, prefix, arrow);
}
if (obs == null) {
obs = Observable.just(Boolean.FALSE);
}
return obs;
}
public static Observable writeDebugMessage(
SessionContext context, ZuulMessage msg, String prefix, String arrow) {
Observable obs = null;
for (Header header : msg.getHeaders().entries()) {
Debug.addRequestDebug(
context, String.format("%s:: %s HDR: %s:%s", prefix, arrow, header.getKey(), header.getValue()));
}
// Capture the response body into a Byte array for later usage.
if (msg.hasBody()) {
if (!Debug.debugRequestHeadersOnly(context)) {
// Convert body to a String and add to debug log.
String body = msg.getBodyAsText();
Debug.addRequestDebug(context, String.format("%s:: %s BODY: %s", prefix, arrow, body));
}
}
if (obs == null) {
obs = Observable.just(Boolean.FALSE);
}
return obs;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy