22

I am new to spring cloud gateway, what I want is to log incoming request to corresponding route url, For e.g. if I have following route config:

      - id: route1
        uri: http://localhost:8585/
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/foo/(?<segment>.*), /$\{segment}

Then for a incoming request of 'http://localhost:8080/foo/route1' following log message should be printed.

"Incoming request url 'http://localhost:8080/foo/route1' is routed to 'http://localhost:8585/route1'"

Is there any easy way of achieving this or can I achieve this just by setting log level.

Can you please help

JavaCodeNet
  • 1,115
  • 1
  • 15
  • 21

4 Answers4

24

You could do it with a simple GlobalFilter.

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.Collections;
import java.util.Set;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

public class LoggingFilter implements GlobalFilter {
    Log log = LogFactory.getLog(getClass());

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Set<URI> uris = exchange.getAttributeOrDefault(GATEWAY_ORIGINAL_REQUEST_URL_ATTR, Collections.emptySet());
        String originalUri = (uris.isEmpty()) ? "Unknown" : uris.iterator().next().toString();
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        URI routeUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
        log.info("Incoming request " + originalUri + " is routed to id: " + route.getId()
                + ", uri:" + routeUri);
        return chain.filter(exchange);
    }
}

produces the following in the logs.

2019-01-09 15:36:32.422  INFO 6870 --- [or-http-epoll-2] LoggingFilter                      : Incoming request http://localhost:8080/api/configserver/foo/default is routed to id: CompositeDiscoveryClient_CONFIGSERVER, uri:http://192.168.0.112:8888/foo/default
spencergibb
  • 24,471
  • 6
  • 69
  • 75
  • 2
    The filter logs two times, I don't know why, some idea about this issue? – Diego Oct 03 '19 at 21:32
  • I configured some routes, but it always prints "Unknown", for instance: Incoming request Unknown is routed to id: 98bad84c-6b31-46f4-84ec-915e02f921a5, uri:http://localhost:8080/bootstrap.css.map – bzhu Oct 15 '19 at 14:02
  • 2
    @user792883 use this code to retrieve URI: `String originalUri = uris.isEmpty()) ? exchange.getRequest().getURI().toString() : uris.iterator().next().toString();` – bvn13 Nov 27 '19 at 20:17
  • 6
    I had to add @Component to the class for it to work – John Mercier Jul 28 '21 at 18:08
  • This `GlobalFilter` will not log requests that were not matched by any route. @spencergibb? – Krzysztof Tomaszewski Nov 08 '22 at 07:48
23

From spring cloud gateway 2.2, please try following switches:

logging:
  level:
    reactor:
      netty: INFO
    org:
      springframework:
        cloud:
          gateway: TRACE
spring:
  cloud:
    gateway:
      httpclient:
        wiretap: true
      httpserver:
        wiretap: true

more info please refer here, spring cloud gateway log levels

bzhu
  • 908
  • 2
  • 9
  • 16
  • 4
    Just done, useless, destination path is never explicitly logged, and basically a lot of default toString() classes shown in a infinite long line, what is interesting is information about how matching is done, what I expect is something pretty simple: INPUT_METHOD INPUT_URL OUTPUT_METHOD OUTPUT URL HTTP_STATUS RESPONSE, continue searching. – tonio Jan 21 '21 at 17:17
  • Does SCG support AdvancedByteBufFormat.TEXTUAL https://projectreactor.io/docs/netty/release/reference/index.html#server-tcp-level-configurations-event-wire-logger? – Rajesh Vyas Feb 27 '21 at 17:40
  • @RajeshVyas : Check below answer – Akshay Shinde Jul 02 '21 at 15:32
3

I have found below solution, give it a try:

application.yml

logging:
    level:
        reactor:
            netty: INFO
        org:
            springframework:
                cloud:
                    gateway: INFO

Bean Config:

@Bean
HttpClient httpClient() {
    return HttpClient.create().wiretap("LoggingFilter", LogLevel.INFO, AdvancedByteBufFormat.TEXTUAL);
}

Akshay

Dharman
  • 30,962
  • 25
  • 85
  • 135
2

You can just add this log level. The log messages will be more verbose than the filter, but at least you don't need to create a class

application.yml:

logging:
  level:
    org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping: DEBUG

An advantage to the filter solution is you can also log when routes are not found by changing to TRACE:

logging:
  level:
    org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping: TRACE
Theo
  • 479
  • 5
  • 6