gobuffalo/buffalo

support to log the result of response

dengqinghua opened this issue · 4 comments

Description

Hi.

We use the buffalo as a micro service in the k8s. And I found some problems when I try to do the log.

In the source code, I've found nice designs to get the log, like

// RequestLogger can be be overridden to a user specified
// function that can be used to log the request.
var RequestLogger = RequestLoggerFunc

Instead of just log the params, request URI, request body or header, we also want to log the response.

We've tried many ways, like using the middleware, use custom renderer etc... but we think it is too tricky to do the thing, maybe the best way is to support internally?

Thanks a lot!

sio4 commented

Hi @dengqinghua,

Instead of just log the params, request URI, request body or header, we also want to log the response.

What do you mean by "the response"? I don't think you want to log all the page contents that responded to the client. Which information do you want to log? The current default logger already logs status code (HTTP response code), responded content size, and some additional information like processing time and time spent by the database part of the request handling.

If you specifically let us know which information could be useful for many common users, we would consider adding that by default. However, if the information is site/application specific, I think you can implement it with middleware or just for a specific handler if the log information is just for a specific handler.

We've tried many ways, like using the middleware, use custom renderer etc... but we think it is too tricky to do the thing, maybe the best way is to support internally?

What was your implementation with middleware and what was the expected result and actual result? (I don't think custom renderer is not a common approach for this kind of thing)

Maybe more specific and detailed information/description on a question will help you to get a better answer. :-)

Hi, @sio4

Thanks for your reply!

I mean the response body of the HTTP request.

Example: the common log like this

{"content_type":"application/json","duration":295710324,"form":"{\"per_page\":[\"2\"]}","level":"info","method":"POST","msg":"/server/setting/page/?per_page=2","params":"{\"per_page\":[\"2\"]}","path":"/server/setting/page/?per_page=2","render":202464,"request_id":"cae00cc2010fc06bdc27-7157af8f72273e16f6ec","status":200,"time":"2022-08-27T16:08:03+08:00"}

But I want to record HTTP response body to the log.

{"content_type":"application/json", ...... "body": "{"message": "hello world"}"

The {"message": "hello world"} is the response of the HTTP request.

sio4 commented

Oh, I see @dengqinghua.

I think that is not a common use case and could be somewhat tricky :-)

If you use the Buffalo's default context and generated handler code, then you may are familiar with the usual form of the handler code:

func (v BooksResource) List(c buffalo.Context) error {
    <...>
    return c.Render(http.StatusOK, r.JSON(books))
}

In the c.Render() function, the function writes the rendered contents to http.ResponseWriter (via Context.Response()) which is writable only. So if you really want to log all those responses from the all handlers, you may need to override the function by creating your own Context and Render function and need to intercept the content when it is called. (If you really want to do that, I think this post in the stackoverflow could be helpful: https://stackoverflow.com/questions/43801849/how-to-get-data-from-http-responsewriter-for-logging)

However, if you are OK with adding the log just for a few handlers and/or it could not be the exactly the same, you can just add some code before sending the response by adding a few lines of code:

func (v BooksResource) List(c buffalo.Context) error {
    <...>

    c.LogField("books", books)

    return c.Render(http.StatusOK, r.JSON(books))
}

I hope it could be the answer for your question.

Thanks!I solved the same like you said