req icon indicating copy to clipboard operation
req copied to clipboard

Is it safe to call client.SetLogger(logger) concurrently?

Open GingerMoon opened this issue 1 year ago • 5 comments

Dear @imroc

My server is using zap logger. The logger is set to log correlation id of every inbound http request. My handlers for handling these inbound http requests use req http client. I want the call client.SetLogger(logger) concurrently on the same client (the looger logs the correlation id of different requests) so that the req http client also logs the correlation id.

Or should I create a new req client for different inboud http requests? Or, is it possible to write trace info into the dump file?

GingerMoon avatar Dec 05 '23 02:12 GingerMoon

It's safe but may not work as expected due to the concurrency. Generally, client level setting should not call concurrently. you can enable dump at request level, get the dump string and write it with your correlation id anywhere you want.

ref: https://req.cool/docs/tutorial/debugging/#dump-the-content

You can also enable dump at request level, which will not override the client-level dump setting, it will dump to the internal buffer and do not print to stdout by default, you can call Response.Dump() to get the dump result and print only if you want to, typically used in production, only record the content of the request when the request is abnormal to help us troubleshoot problems

imroc avatar Dec 05 '23 05:12 imroc

Thanks imroc! By the way, is resp.Body.Close() below still needed?

resp, err := httpClient.R().Get(url) if err != nil { this.Logger.Error(fmt.Sprintf("failed to fetch the page: %v", err)) return "", errors.New("httpClient.GetError") } defer resp.Body.Close() // is this still needed?

GingerMoon avatar Dec 05 '23 09:12 GingerMoon

No, it's been closed automatically if you don't read resp.Body manually.

imroc avatar Dec 05 '23 09:12 imroc

@imroc should I close the resp.Body manually in the following code snippet?

func middlewareDumpReqAndResp(client *req.Client, resp *req.Response) error {
	ctx := resp.Request.Context()
	logger := logger.GetLoggerFromCtx(ctx)

	respBody, err := io.ReadAll(io.Reader(resp.Body))
	if err != nil {
		err = errors.New(fmt.Sprint("get response payload body failed: ", err.Error()))
		logger.Error(err.Error())
		panic(err.Error())
	}
	resp.Body = io.NopCloser(io.Reader(bytes.NewBuffer(respBody)))

	logger.Info(fmt.Sprintf("request url: %s \n request body: %s \n response body: %s", resp.Request.RawURL, string(resp.Request.Body), string(respBody)))
	return nil
}

GingerMoon avatar Mar 04 '24 05:03 GingerMoon

@imroc should I close the resp.Body manually in the following code snippet?

func middlewareDumpReqAndResp(client *req.Client, resp *req.Response) error {
	ctx := resp.Request.Context()
	logger := logger.GetLoggerFromCtx(ctx)

	respBody, err := io.ReadAll(io.Reader(resp.Body))
	if err != nil {
		err = errors.New(fmt.Sprint("get response payload body failed: ", err.Error()))
		logger.Error(err.Error())
		panic(err.Error())
	}
	resp.Body = io.NopCloser(io.Reader(bytes.NewBuffer(respBody)))

	logger.Info(fmt.Sprintf("request url: %s \n request body: %s \n response body: %s", resp.Request.RawURL, string(resp.Request.Body), string(respBody)))
	return nil
}

Unnecessary

imroc avatar Mar 04 '24 06:03 imroc