From 89fb8a099e4aee7bbd60cf4ebb1f35657a8c83e8 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Thu, 15 Jan 2026 23:29:48 +0800 Subject: [PATCH] add a unified logging handler to the http client --- pkg/api/map_image_proxies.go | 4 +- pkg/auth/oauth2/oauth2_authentication.go | 4 +- .../provider/common/common_oauth2_provider.go | 8 +++- .../provider/github/github_oauth2_provider.go | 14 +++++-- .../oauth2/provider/oidc/oidc_provider.go | 5 ++- ...ommon_http_exchange_rates_data_provider.go | 10 +++-- .../http.go => httpclient/http_client.go} | 37 +++++++++++++++---- pkg/httpclient/http_request_context.go | 35 ++++++++++++++++++ ...large_language_model_provider_container.go | 14 +++---- ...mmon_http_large_language_model_provider.go | 12 +++--- .../google_ai_large_language_model_adapter.go | 4 +- .../ollama_large_language_model_adapter.go | 4 +- .../openai_chat_completions_api_provider.go | 4 +- ...compatible_large_language_model_adapter.go | 4 +- ...ompatible_chat_completions_api_provider.go | 4 +- ...penrouter_chat_completions_api_provider.go | 4 +- pkg/settings/setting.go | 7 ++++ pkg/storage/webdav_storage.go | 4 +- 18 files changed, 130 insertions(+), 48 deletions(-) rename pkg/{utils/http.go => httpclient/http_client.go} (61%) create mode 100644 pkg/httpclient/http_request_context.go diff --git a/pkg/api/map_image_proxies.go b/pkg/api/map_image_proxies.go index c28340dc..a7055f5d 100644 --- a/pkg/api/map_image_proxies.go +++ b/pkg/api/map_image_proxies.go @@ -8,8 +8,8 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/settings" - "github.com/mayswind/ezbookkeeping/pkg/utils" ) const openStreetMapTileImageUrlFormat = "https://tile.openstreetmap.org/{z}/{x}/{y}.png" // https://tile.openstreetmap.org/{z}/{x}/{y}.png @@ -110,7 +110,7 @@ func (p *MapImageProxy) mapImageProxyHandler(c *core.WebContext, fn func(c *core } transport := http.DefaultTransport.(*http.Transport).Clone() - utils.SetProxyUrl(transport, p.CurrentConfig().MapProxy) + httpclient.SetProxyUrl(transport, p.CurrentConfig().MapProxy) director := func(req *http.Request) { imageRawUrl := targetUrl diff --git a/pkg/auth/oauth2/oauth2_authentication.go b/pkg/auth/oauth2/oauth2_authentication.go index b6408c98..d18c45e7 100644 --- a/pkg/auth/oauth2/oauth2_authentication.go +++ b/pkg/auth/oauth2/oauth2_authentication.go @@ -13,8 +13,8 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/provider/oidc" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/settings" - "github.com/mayswind/ezbookkeeping/pkg/utils" ) // OAuth2Container contains the current OAuth 2.0 authentication provider @@ -67,7 +67,7 @@ func InitializeOAuth2Provider(config *settings.Config) error { Container.current = oauth2Provider Container.usePKCE = config.OAuth2UsePKCE - Container.oauth2HttpClient = utils.NewHttpClient(config.OAuth2RequestTimeout, config.OAuth2Proxy, config.OAuth2SkipTLSVerify, settings.GetUserAgent()) + Container.oauth2HttpClient = httpclient.NewHttpClient(config.OAuth2RequestTimeout, config.OAuth2Proxy, config.OAuth2SkipTLSVerify, settings.GetUserAgent(), config.EnableDebugLog) Container.externalUserAuthType = externalUserAuthType return nil diff --git a/pkg/auth/oauth2/provider/common/common_oauth2_provider.go b/pkg/auth/oauth2/provider/common/common_oauth2_provider.go index e0844111..673cffa6 100644 --- a/pkg/auth/oauth2/provider/common/common_oauth2_provider.go +++ b/pkg/auth/oauth2/provider/common/common_oauth2_provider.go @@ -10,6 +10,7 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/provider" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/settings" ) @@ -59,6 +60,11 @@ func (p *CommonOAuth2Provider) GetUserInfo(c core.Context, oauth2Token *oauth2.T } oauth2Client := oauth2.NewClient(c, oauth2.StaticTokenSource(oauth2Token)) + + req = req.WithContext(httpclient.CustomHttpResponseLog(c, func(data []byte) { + log.Debugf(c, "[common_oauth2_provider.GetUserInfo] response is %s", data) + })) + resp, err := oauth2Client.Do(req) if err != nil { @@ -69,8 +75,6 @@ func (p *CommonOAuth2Provider) GetUserInfo(c core.Context, oauth2Token *oauth2.T defer resp.Body.Close() body, err := io.ReadAll(resp.Body) - log.Debugf(c, "[common_oauth2_provider.GetUserInfo] response is %s", body) - if resp.StatusCode != 200 { log.Errorf(c, "[common_oauth2_provider.GetUserInfo] failed to get user info response, because response code is %d", resp.StatusCode) return nil, errs.ErrFailedToRequestRemoteApi diff --git a/pkg/auth/oauth2/provider/github/github_oauth2_provider.go b/pkg/auth/oauth2/provider/github/github_oauth2_provider.go index 2fc28e94..41e42e15 100644 --- a/pkg/auth/oauth2/provider/github/github_oauth2_provider.go +++ b/pkg/auth/oauth2/provider/github/github_oauth2_provider.go @@ -11,6 +11,7 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/provider" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/settings" ) @@ -61,6 +62,11 @@ func (p *GithubOAuth2Provider) GetUserInfo(c core.Context, oauth2Token *oauth2.T } oauth2Client := oauth2.NewClient(c, oauth2.StaticTokenSource(oauth2Token)) + + req = req.WithContext(httpclient.CustomHttpResponseLog(c, func(data []byte) { + log.Debugf(c, "[github_oauth2_provider.GetUserInfo] user profile response is %s", data) + })) + resp, err := oauth2Client.Do(req) if err != nil { @@ -71,8 +77,6 @@ func (p *GithubOAuth2Provider) GetUserInfo(c core.Context, oauth2Token *oauth2.T defer resp.Body.Close() body, err := io.ReadAll(resp.Body) - log.Debugf(c, "[github_oauth2_provider.GetUserInfo] user profile response is %s", body) - if resp.StatusCode != 200 { log.Errorf(c, "[github_oauth2_provider.GetUserInfo] failed to get user info response, because response code is %d", resp.StatusCode) return nil, errs.ErrFailedToRequestRemoteApi @@ -92,6 +96,10 @@ func (p *GithubOAuth2Provider) GetUserInfo(c core.Context, oauth2Token *oauth2.T return nil, errs.ErrFailedToRequestRemoteApi } + req = req.WithContext(httpclient.CustomHttpResponseLog(c, func(data []byte) { + log.Debugf(c, "[github_oauth2_provider.GetUserInfo] user emails response is %s", data) + })) + resp, err = oauth2Client.Do(req) if err != nil { @@ -102,8 +110,6 @@ func (p *GithubOAuth2Provider) GetUserInfo(c core.Context, oauth2Token *oauth2.T defer resp.Body.Close() body, err = io.ReadAll(resp.Body) - log.Debugf(c, "[github_oauth2_provider.GetUserInfo] user emails response is %s", body) - if resp.StatusCode != 200 { log.Errorf(c, "[github_oauth2_provider.GetUserInfo] failed to get user emails response, because response code is %d", resp.StatusCode) return nil, errs.ErrFailedToRequestRemoteApi diff --git a/pkg/auth/oauth2/provider/oidc/oidc_provider.go b/pkg/auth/oauth2/provider/oidc/oidc_provider.go index 67f21555..ba47e8bc 100644 --- a/pkg/auth/oauth2/provider/oidc/oidc_provider.go +++ b/pkg/auth/oauth2/provider/oidc/oidc_provider.go @@ -11,6 +11,7 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/provider" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/settings" ) @@ -92,7 +93,9 @@ func (p *OIDCProvider) GetUserInfo(c core.Context, oauth2Token *oauth2.Token) (* nickName := claims.Name if userName == "" || email == "" || nickName == "" { - userInfo, err := p.oidcProvider.UserInfo(c, oauth2.StaticTokenSource(oauth2Token)) + userInfo, err := p.oidcProvider.UserInfo(httpclient.CustomHttpResponseLog(c, func(data []byte) { + log.Debugf(c, "[oidc_provider.GetUserInfo] response is %s", data) + }), oauth2.StaticTokenSource(oauth2Token)) if err != nil { log.Errorf(c, "[oidc_provider.GetUserInfo] failed to get user info, because %s", err.Error()) diff --git a/pkg/exchangerates/common_http_exchange_rates_data_provider.go b/pkg/exchangerates/common_http_exchange_rates_data_provider.go index 04e5c1e5..846db5bf 100644 --- a/pkg/exchangerates/common_http_exchange_rates_data_provider.go +++ b/pkg/exchangerates/common_http_exchange_rates_data_provider.go @@ -7,10 +7,10 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/settings" - "github.com/mayswind/ezbookkeeping/pkg/utils" ) // HttpExchangeRatesDataSource defines the structure of http exchange rates data source @@ -41,6 +41,10 @@ func (e *CommonHttpExchangeRatesDataProvider) GetLatestExchangeRates(c core.Cont for i := 0; i < len(requests); i++ { req := requests[i] + req = req.WithContext(httpclient.CustomHttpResponseLog(c, func(data []byte) { + log.Debugf(c, "[common_http_exchange_rates_data_provider.GetLatestExchangeRates] response#%d is %s", i, data) + })) + resp, err := e.httpClient.Do(req) if err != nil { @@ -51,8 +55,6 @@ func (e *CommonHttpExchangeRatesDataProvider) GetLatestExchangeRates(c core.Cont defer resp.Body.Close() body, err := io.ReadAll(resp.Body) - log.Debugf(c, "[common_http_exchange_rates_data_provider.GetLatestExchangeRates] response#%d is %s", i, body) - if resp.StatusCode != 200 { log.Errorf(c, "[common_http_exchange_rates_data_provider.GetLatestExchangeRates] failed to get latest exchange rate data response for user \"uid:%d\", because response code is %d", uid, resp.StatusCode) return nil, errs.ErrFailedToRequestRemoteApi @@ -106,6 +108,6 @@ func (e *CommonHttpExchangeRatesDataProvider) GetLatestExchangeRates(c core.Cont func newCommonHttpExchangeRatesDataProvider(config *settings.Config, dataSource HttpExchangeRatesDataSource) *CommonHttpExchangeRatesDataProvider { return &CommonHttpExchangeRatesDataProvider{ dataSource: dataSource, - httpClient: utils.NewHttpClient(config.ExchangeRatesRequestTimeout, config.ExchangeRatesProxy, config.ExchangeRatesSkipTLSVerify, settings.GetUserAgent()), + httpClient: httpclient.NewHttpClient(config.ExchangeRatesRequestTimeout, config.ExchangeRatesProxy, config.ExchangeRatesSkipTLSVerify, settings.GetUserAgent(), config.EnableDebugLog), } } diff --git a/pkg/utils/http.go b/pkg/httpclient/http_client.go similarity index 61% rename from pkg/utils/http.go rename to pkg/httpclient/http_client.go index d10b036d..ce3c3a37 100644 --- a/pkg/utils/http.go +++ b/pkg/httpclient/http_client.go @@ -1,15 +1,18 @@ -package utils +package httpclient import ( + "bytes" "crypto/tls" + "io" "net/http" "net/url" "time" ) type defaultTransport struct { - defaultUserAgent string - baseTransport http.RoundTripper + defaultUserAgent string + enableHttpResponseLog bool + baseTransport http.RoundTripper } func (t *defaultTransport) RoundTrip(req *http.Request) (*http.Response, error) { @@ -19,11 +22,30 @@ func (t *defaultTransport) RoundTrip(req *http.Request) (*http.Response, error) req.Header.Del("User-Agent") } - return t.baseTransport.RoundTrip(req) + resp, err := t.baseTransport.RoundTrip(req) + + if t.enableHttpResponseLog && err == nil { + ctx := req.Context() + + if handler, ok := ctx.Value(logHandleKey).(HttpResponseLogHandlerFunc); ok { + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + + if err != nil { + return nil, err + } + + handler(body) + + resp.Body = io.NopCloser(bytes.NewReader(body)) + } + } + + return resp, err } // NewHttpClient creates and returns a new http client with specified settings -func NewHttpClient(requestTimeout uint32, proxy string, skipTLSVerify bool, defaultUserAgent string) *http.Client { +func NewHttpClient(requestTimeout uint32, proxy string, skipTLSVerify bool, defaultUserAgent string, enableHttpResponseLog bool) *http.Client { baseTransport := http.DefaultTransport.(*http.Transport).Clone() SetProxyUrl(baseTransport, proxy) @@ -35,8 +57,9 @@ func NewHttpClient(requestTimeout uint32, proxy string, skipTLSVerify bool, defa return &http.Client{ Transport: &defaultTransport{ - defaultUserAgent: defaultUserAgent, - baseTransport: baseTransport, + defaultUserAgent: defaultUserAgent, + enableHttpResponseLog: enableHttpResponseLog, + baseTransport: baseTransport, }, Timeout: time.Duration(requestTimeout) * time.Millisecond, } diff --git a/pkg/httpclient/http_request_context.go b/pkg/httpclient/http_request_context.go new file mode 100644 index 00000000..b545fc22 --- /dev/null +++ b/pkg/httpclient/http_request_context.go @@ -0,0 +1,35 @@ +package httpclient + +import ( + "github.com/mayswind/ezbookkeeping/pkg/core" +) + +const ( + logHandleKey = "log_handler" +) + +// HttpResponseLogHandlerFunc represents the http response log handler function +type HttpResponseLogHandlerFunc func([]byte) + +// httpRequestContext represents the context for http request +type httpRequestContext struct { + core.Context + logHandler HttpResponseLogHandlerFunc +} + +// Value returns the value associated with key +func (c *httpRequestContext) Value(key any) any { + if key == logHandleKey { + return c.logHandler + } + + return c.Context.Value(key) +} + +// CustomHttpResponseLog returns a context with http response log handler +func CustomHttpResponseLog(c core.Context, responseLogHandler HttpResponseLogHandlerFunc) core.Context { + return &httpRequestContext{ + Context: c, + logHandler: responseLogHandler, + } +} diff --git a/pkg/llm/large_language_model_provider_container.go b/pkg/llm/large_language_model_provider_container.go index 6652b290..89d7ac0d 100644 --- a/pkg/llm/large_language_model_provider_container.go +++ b/pkg/llm/large_language_model_provider_container.go @@ -26,7 +26,7 @@ func InitializeLargeLanguageModelProvider(config *settings.Config) error { var err error = nil if config.ReceiptImageRecognitionLLMConfig != nil { - Container.receiptImageRecognitionCurrentProvider, err = initializeLargeLanguageModelProvider(config.ReceiptImageRecognitionLLMConfig) + Container.receiptImageRecognitionCurrentProvider, err = initializeLargeLanguageModelProvider(config.ReceiptImageRecognitionLLMConfig, config.EnableDebugLog) if err != nil { return err @@ -36,17 +36,17 @@ func InitializeLargeLanguageModelProvider(config *settings.Config) error { return nil } -func initializeLargeLanguageModelProvider(llmConfig *settings.LLMConfig) (provider.LargeLanguageModelProvider, error) { +func initializeLargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool) (provider.LargeLanguageModelProvider, error) { if llmConfig.LLMProvider == settings.OpenAILLMProvider { - return openai.NewOpenAILargeLanguageModelProvider(llmConfig), nil + return openai.NewOpenAILargeLanguageModelProvider(llmConfig, enableResponseLog), nil } else if llmConfig.LLMProvider == settings.OpenAICompatibleLLMProvider { - return openai.NewOpenAICompatibleLargeLanguageModelProvider(llmConfig), nil + return openai.NewOpenAICompatibleLargeLanguageModelProvider(llmConfig, enableResponseLog), nil } else if llmConfig.LLMProvider == settings.OpenRouterLLMProvider { - return openai.NewOpenRouterLargeLanguageModelProvider(llmConfig), nil + return openai.NewOpenRouterLargeLanguageModelProvider(llmConfig, enableResponseLog), nil } else if llmConfig.LLMProvider == settings.OllamaLLMProvider { - return ollama.NewOllamaLargeLanguageModelProvider(llmConfig), nil + return ollama.NewOllamaLargeLanguageModelProvider(llmConfig, enableResponseLog), nil } else if llmConfig.LLMProvider == settings.GoogleAILLMProvider { - return googleai.NewGoogleAILargeLanguageModelProvider(llmConfig), nil + return googleai.NewGoogleAILargeLanguageModelProvider(llmConfig, enableResponseLog), nil } else if llmConfig.LLMProvider == "" { return nil, nil } diff --git a/pkg/llm/provider/common/common_http_large_language_model_provider.go b/pkg/llm/provider/common/common_http_large_language_model_provider.go index 89a0b588..a791f957 100644 --- a/pkg/llm/provider/common/common_http_large_language_model_provider.go +++ b/pkg/llm/provider/common/common_http_large_language_model_provider.go @@ -7,11 +7,11 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/llm/data" "github.com/mayswind/ezbookkeeping/pkg/llm/provider" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/settings" - "github.com/mayswind/ezbookkeeping/pkg/utils" ) // HttpLargeLanguageModelAdapter defines the structure of http large language model adapter @@ -57,6 +57,10 @@ func (p *CommonHttpLargeLanguageModelProvider) getTextualResponse(c core.Context return nil, errs.ErrFailedToRequestRemoteApi } + httpRequest = httpRequest.WithContext(httpclient.CustomHttpResponseLog(c, func(data []byte) { + log.Debugf(c, "[common_http_large_language_model_provider.getTextualResponse] response is %s", data) + })) + resp, err := p.httpClient.Do(httpRequest) if err != nil { @@ -67,8 +71,6 @@ func (p *CommonHttpLargeLanguageModelProvider) getTextualResponse(c core.Context defer resp.Body.Close() body, err := io.ReadAll(resp.Body) - log.Debugf(c, "[common_http_large_language_model_provider.getTextualResponse] response is %s", body) - if resp.StatusCode != 200 { log.Errorf(c, "[common_http_large_language_model_provider.getTextualResponse] failed to get large language model api response for user \"uid:%d\", because response code is %d", uid, resp.StatusCode) return nil, errs.ErrFailedToRequestRemoteApi @@ -78,9 +80,9 @@ func (p *CommonHttpLargeLanguageModelProvider) getTextualResponse(c core.Context } // NewCommonHttpLargeLanguageModelProvider creates a http adapter based large language model provider instance -func NewCommonHttpLargeLanguageModelProvider(llmConfig *settings.LLMConfig, adapter HttpLargeLanguageModelAdapter) *CommonHttpLargeLanguageModelProvider { +func NewCommonHttpLargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool, adapter HttpLargeLanguageModelAdapter) *CommonHttpLargeLanguageModelProvider { return &CommonHttpLargeLanguageModelProvider{ adapter: adapter, - httpClient: utils.NewHttpClient(llmConfig.LargeLanguageModelAPIRequestTimeout, llmConfig.LargeLanguageModelAPIProxy, llmConfig.LargeLanguageModelAPISkipTLSVerify, settings.GetUserAgent()), + httpClient: httpclient.NewHttpClient(llmConfig.LargeLanguageModelAPIRequestTimeout, llmConfig.LargeLanguageModelAPIProxy, llmConfig.LargeLanguageModelAPISkipTLSVerify, settings.GetUserAgent(), enableResponseLog), } } diff --git a/pkg/llm/provider/googleai/google_ai_large_language_model_adapter.go b/pkg/llm/provider/googleai/google_ai_large_language_model_adapter.go index 4bf06a45..774f4e49 100644 --- a/pkg/llm/provider/googleai/google_ai_large_language_model_adapter.go +++ b/pkg/llm/provider/googleai/google_ai_large_language_model_adapter.go @@ -159,8 +159,8 @@ func (p *GoogleAILargeLanguageModelAdapter) buildJsonRequestBody(c core.Context, } // NewGoogleAILargeLanguageModelProvider creates a new Google AI large language model provider instance -func NewGoogleAILargeLanguageModelProvider(llmConfig *settings.LLMConfig) provider.LargeLanguageModelProvider { - return common.NewCommonHttpLargeLanguageModelProvider(llmConfig, &GoogleAILargeLanguageModelAdapter{ +func NewGoogleAILargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool) provider.LargeLanguageModelProvider { + return common.NewCommonHttpLargeLanguageModelProvider(llmConfig, enableResponseLog, &GoogleAILargeLanguageModelAdapter{ GoogleAIAPIKey: llmConfig.GoogleAIAPIKey, GoogleAIModelID: llmConfig.GoogleAIModelID, }) diff --git a/pkg/llm/provider/ollama/ollama_large_language_model_adapter.go b/pkg/llm/provider/ollama/ollama_large_language_model_adapter.go index ee8e8042..99e9fb17 100644 --- a/pkg/llm/provider/ollama/ollama_large_language_model_adapter.go +++ b/pkg/llm/provider/ollama/ollama_large_language_model_adapter.go @@ -158,8 +158,8 @@ func (p *OllamaLargeLanguageModelAdapter) getOllamaRequestUrl() string { } // NewOllamaLargeLanguageModelProvider creates a new Ollama large language model provider instance -func NewOllamaLargeLanguageModelProvider(llmConfig *settings.LLMConfig) provider.LargeLanguageModelProvider { - return common.NewCommonHttpLargeLanguageModelProvider(llmConfig, &OllamaLargeLanguageModelAdapter{ +func NewOllamaLargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool) provider.LargeLanguageModelProvider { + return common.NewCommonHttpLargeLanguageModelProvider(llmConfig, enableResponseLog, &OllamaLargeLanguageModelAdapter{ OllamaServerURL: llmConfig.OllamaServerURL, OllamaModelID: llmConfig.OllamaModelID, }) diff --git a/pkg/llm/provider/openai/openai_chat_completions_api_provider.go b/pkg/llm/provider/openai/openai_chat_completions_api_provider.go index 6a7be388..d20437a1 100644 --- a/pkg/llm/provider/openai/openai_chat_completions_api_provider.go +++ b/pkg/llm/provider/openai/openai_chat_completions_api_provider.go @@ -36,8 +36,8 @@ func (p *OpenAIOfficialChatCompletionsAPIProvider) GetModelID() string { } // NewOpenAILargeLanguageModelProvider creates a new OpenAI large language model provider instance -func NewOpenAILargeLanguageModelProvider(llmConfig *settings.LLMConfig) provider.LargeLanguageModelProvider { - return newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig, &OpenAIOfficialChatCompletionsAPIProvider{ +func NewOpenAILargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool) provider.LargeLanguageModelProvider { + return newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig, enableResponseLog, &OpenAIOfficialChatCompletionsAPIProvider{ OpenAIAPIKey: llmConfig.OpenAIAPIKey, OpenAIModelID: llmConfig.OpenAIModelID, }) diff --git a/pkg/llm/provider/openai/openai_common_compatible_large_language_model_adapter.go b/pkg/llm/provider/openai/openai_common_compatible_large_language_model_adapter.go index a8d144a3..53492cc3 100644 --- a/pkg/llm/provider/openai/openai_common_compatible_large_language_model_adapter.go +++ b/pkg/llm/provider/openai/openai_common_compatible_large_language_model_adapter.go @@ -213,8 +213,8 @@ func (p *CommonOpenAIChatCompletionsAPILargeLanguageModelAdapter) buildJsonReque return requestBodyBytes, nil } -func newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig *settings.LLMConfig, apiProvider OpenAIChatCompletionsAPIProvider) provider.LargeLanguageModelProvider { - return common.NewCommonHttpLargeLanguageModelProvider(llmConfig, &CommonOpenAIChatCompletionsAPILargeLanguageModelAdapter{ +func newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig *settings.LLMConfig, enableResponseLog bool, apiProvider OpenAIChatCompletionsAPIProvider) provider.LargeLanguageModelProvider { + return common.NewCommonHttpLargeLanguageModelProvider(llmConfig, enableResponseLog, &CommonOpenAIChatCompletionsAPILargeLanguageModelAdapter{ apiProvider: apiProvider, }) } diff --git a/pkg/llm/provider/openai/openai_compatible_chat_completions_api_provider.go b/pkg/llm/provider/openai/openai_compatible_chat_completions_api_provider.go index 066502ee..b9b7b619 100644 --- a/pkg/llm/provider/openai/openai_compatible_chat_completions_api_provider.go +++ b/pkg/llm/provider/openai/openai_compatible_chat_completions_api_provider.go @@ -50,8 +50,8 @@ func (p *OpenAICompatibleChatCompletionsAPIProvider) getFinalChatCompletionsRequ } // NewOpenAICompatibleLargeLanguageModelProvider creates a new OpenAI compatible large language model provider instance -func NewOpenAICompatibleLargeLanguageModelProvider(llmConfig *settings.LLMConfig) provider.LargeLanguageModelProvider { - return newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig, &OpenAICompatibleChatCompletionsAPIProvider{ +func NewOpenAICompatibleLargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool) provider.LargeLanguageModelProvider { + return newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig, enableResponseLog, &OpenAICompatibleChatCompletionsAPIProvider{ OpenAICompatibleBaseURL: llmConfig.OpenAICompatibleBaseURL, OpenAICompatibleAPIKey: llmConfig.OpenAICompatibleAPIKey, OpenAICompatibleModelID: llmConfig.OpenAICompatibleModelID, diff --git a/pkg/llm/provider/openai/openrouter_chat_completions_api_provider.go b/pkg/llm/provider/openai/openrouter_chat_completions_api_provider.go index 90951310..5c8d4c41 100644 --- a/pkg/llm/provider/openai/openrouter_chat_completions_api_provider.go +++ b/pkg/llm/provider/openai/openrouter_chat_completions_api_provider.go @@ -38,8 +38,8 @@ func (p *OpenRouterChatCompletionsAPIProvider) GetModelID() string { } // NewOpenRouterLargeLanguageModelProvider creates a new OpenRouter large language model provider instance -func NewOpenRouterLargeLanguageModelProvider(llmConfig *settings.LLMConfig) provider.LargeLanguageModelProvider { - return newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig, &OpenRouterChatCompletionsAPIProvider{ +func NewOpenRouterLargeLanguageModelProvider(llmConfig *settings.LLMConfig, enableResponseLog bool) provider.LargeLanguageModelProvider { + return newCommonOpenAIChatCompletionsAPILargeLanguageModelAdapter(llmConfig, enableResponseLog, &OpenRouterChatCompletionsAPIProvider{ OpenRouterAPIKey: llmConfig.OpenRouterAPIKey, OpenRouterModelID: llmConfig.OpenRouterModelID, }) diff --git a/pkg/settings/setting.go b/pkg/settings/setting.go index 9832b813..d8884d47 100644 --- a/pkg/settings/setting.go +++ b/pkg/settings/setting.go @@ -305,6 +305,7 @@ type Config struct { EnableConsoleLog bool EnableFileLog bool + EnableDebugLog bool LogLevel Level FileLogPath string RequestFileLogPath string @@ -759,6 +760,12 @@ func loadLogConfiguration(config *Config, configFile *ini.File, sectionName stri return errs.ErrInvalidLogLevel } + if config.LogLevel == LOGLEVEL_DEBUG { + config.EnableDebugLog = true + } else { + config.EnableDebugLog = false + } + if config.EnableFileLog { fileLogPath := getConfigItemStringValue(configFile, sectionName, "log_path") finalFileLogPath, _ := getFinalPath(config.WorkingPath, fileLogPath) diff --git a/pkg/storage/webdav_storage.go b/pkg/storage/webdav_storage.go index 1b3db6a3..f4144124 100644 --- a/pkg/storage/webdav_storage.go +++ b/pkg/storage/webdav_storage.go @@ -9,9 +9,9 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" + "github.com/mayswind/ezbookkeeping/pkg/httpclient" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/settings" - "github.com/mayswind/ezbookkeeping/pkg/utils" ) // WebDAVObjectStorage represents WebDAV object storage @@ -26,7 +26,7 @@ func NewWebDAVObjectStorage(config *settings.Config, pathPrefix string) (*WebDAV webDavConfig := config.WebDAVConfig storage := &WebDAVObjectStorage{ - httpClient: utils.NewHttpClient(webDavConfig.RequestTimeout, webDavConfig.Proxy, webDavConfig.SkipTLSVerify, settings.GetUserAgent()), + httpClient: httpclient.NewHttpClient(webDavConfig.RequestTimeout, webDavConfig.Proxy, webDavConfig.SkipTLSVerify, settings.GetUserAgent(), false), webDavConfig: webDavConfig, rootPath: webDavConfig.RootPath, }