1

How to get responseBody string for logging purpose in HttpSupportFilter?

Common log solution is create wrapper and insert it to the standar filter

If we use standar filter we cannot access activejdbc db connection layer

I tried to apply wrapper but it does not work, the string is still empty

public class HTTPLogFilter extends HttpSupportFilter {

    private static ThreadLocal<Long> start = new ThreadLocal<>();
    
    @Override
    public void before() {
        start.set(System.currentTimeMillis());
    }

    @Override
    public void after() {

        if(Configuration.HTTPLOGS_ENABLE) {

            Registry.instance().getStatisticsQueue().enqueue(
                    new QueryExecutionEvent(getRoute().getController().getClass().getName() +
                            "#" + getRoute().getActionName() + ":" + method(), System.currentTimeMillis() - start.get()));

            HttpLog httpLog = new HttpLog();

            String username ="TEST";

            Map request = new HashMap<String, Object>();
            request.put("requestUrl", url());
            request.put("contextPath", context());
            request.put("uriFullPath", uri());
            request.put("uriPath", path());
            request.put("method", method());
            request.put("requestHeaders", headers());
            request.put("requestParams", params());
            request.put("queryString", queryString());
            request.put("requestBody", getRequestString());

            Map response = new HashMap<String, Object>();
            response.put("responseHeaders", getResponseHeaders());
            try {
                // BUG ! this responseBody still empty
                response.put("responseBody", getHttpServletResponse().getWriter().toString());
            } catch (IOException e) {
                e.printStackTrace();
            }

            httpLog.setCreatedby(username);
            httpLog.setCreateddt(new Date());
            httpLog.setUsername(username);
            String remoteAddr = ipForwardedFor() != null ? ipForwardedFor() : remoteAddress();
            httpLog.setIpaddress(remoteAddr );
            httpLog.setUseragent(userAgent());
            httpLog.setControllername(getRoute().getController().getClass().getName() + "." + getRoute().getActionName());
            httpLog.setHttpmethod(method());
            httpLog.setHttpexceptions("");
            httpLog.setExecutiondt(new Date(start.get()));
            httpLog.setExecutiondur(System.currentTimeMillis() - start.get());
            httpLog.setHttpurl(url());
            httpLog.setHttprequest(JsonHelper.toJson(request));
            httpLog.setHttpresponse(JsonHelper.toJson(response));
            httpLog.setHttpstatuscode(getHttpServletResponse().getStatus());
            httpLog.saveIt();
        }
    }

}
Gryu
  • 2,102
  • 2
  • 16
  • 29
xanana
  • 13
  • 2

1 Answers1

0

generally, you are on the right path. It is my understanding that HttpLog is a model, and you want to store the request values that to database, correct?

You write:

if we use standar filter we cannot access activejdbc db connection layer

So, the ActiveWeb filters have ordering, which is documented here: https://javalite.io/controller_filters#filter-ordering

This means that if you want a database connection available in the HTTPLogFilter, you have to register the DBConnectionFilter before the HTTPLogFilter, example:

public class AppControllerConfig extends AbstractControllerConfig {
    public void init(AppContext appContext) {
        add(new DBConnectionFilter(), new HTTPLogFilter());
    }
}

This way, the DBConnectionFilter.before() will be called before the HTTPLogFilter.before() and will open a DB connection accordingly.

On the side note: you will be filling your database pretty quickly, and a recommendation is to simply log all this data to a log file and use a log analyzer like Splunk or Graylog.

ipolevoy
  • 5,432
  • 2
  • 31
  • 46
  • Thank you for your answer and suggestion Yes correct HttpLog is a model Yes I have already use this add(new DBConnectionFilter(), new HTTPLogFilter()); Ok after trying this - on normal ( exception not occured ) this filter ordering works because DB connection is not yet closed by the DBConnectionFilter() after() method / onException() method - on exception occured , it seems the on onExceptions on DBConnectionFilter() will be triggered and database will be close which will lead to DB connection not exist error on HTTPLogFilter – xanana Aug 06 '20 at 01:43
  • so i added this on HTTPLogFilter after() and onException() if(isDBConnectionExists()) createHttpLog(); and problem on DB connection solved What about the issue on responseBody ? is it possible to get the responseBody string/ bytearray after the outputsteam is closed using activeweb filter ? – xanana Aug 06 '20 at 01:44
  • I do not think you can do that because the content already streamed to a client, this is just Servlet level – ipolevoy Aug 06 '20 at 14:04