mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-02 04:20:50 +08:00
refactor(gemini-web): Standardize logging with logrus
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,5 +11,4 @@ auths/*
|
|||||||
AGENTS.md
|
AGENTS.md
|
||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
*.exe
|
*.exe
|
||||||
temp/*
|
temp/*
|
||||||
.serena/
|
|
||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpOptions struct {
|
type httpOptions struct {
|
||||||
@@ -103,7 +105,7 @@ func getAccessToken(baseCookies map[string]string, proxy string, verbose bool, i
|
|||||||
}
|
}
|
||||||
trySets = append(trySets, merged)
|
trySets = append(trySets, merged)
|
||||||
} else if verbose {
|
} else if verbose {
|
||||||
Debug("Skipping base cookies: __Secure-1PSIDTS missing")
|
log.Debug("Skipping base cookies: __Secure-1PSIDTS missing")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +132,7 @@ func getAccessToken(baseCookies map[string]string, proxy string, verbose bool, i
|
|||||||
resp, mergedCookies, err := sendInitRequest(cookies, proxy, insecure)
|
resp, mergedCookies, err := sendInitRequest(cookies, proxy, insecure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if verbose {
|
if verbose {
|
||||||
Warning("Failed init request: %v", err)
|
log.Warnf("Failed init request: %v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -143,7 +145,7 @@ func getAccessToken(baseCookies map[string]string, proxy string, verbose bool, i
|
|||||||
if len(matches) >= 2 {
|
if len(matches) >= 2 {
|
||||||
token := matches[1]
|
token := matches[1]
|
||||||
if verbose {
|
if verbose {
|
||||||
Success("Gemini access token acquired.")
|
log.Infof("Gemini access token acquired.")
|
||||||
}
|
}
|
||||||
return token, mergedCookies, nil
|
return token, mergedCookies, nil
|
||||||
}
|
}
|
||||||
@@ -212,3 +214,27 @@ func (r *constReader) Read(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func stringsReader(s string) io.Reader { return &constReader{s: s} }
|
func stringsReader(s string) io.Reader { return &constReader{s: s} }
|
||||||
|
|
||||||
|
func MaskToken28(s string) string {
|
||||||
|
n := len(s)
|
||||||
|
if n == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if n < 20 {
|
||||||
|
return strings.Repeat("*", n)
|
||||||
|
}
|
||||||
|
midStart := n/2 - 2
|
||||||
|
if midStart < 8 {
|
||||||
|
midStart = 8
|
||||||
|
}
|
||||||
|
if midStart+4 > n-8 {
|
||||||
|
midStart = n - 8 - 4
|
||||||
|
if midStart < 8 {
|
||||||
|
midStart = 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prefixByte := s[:8]
|
||||||
|
middle := s[midStart : midStart+4]
|
||||||
|
suffix := s[n-8:]
|
||||||
|
return prefixByte + strings.Repeat("*", 4) + middle + strings.Repeat("*", 4) + suffix
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GeminiClient is the async http client interface (Go port)
|
// GeminiClient is the async http client interface (Go port)
|
||||||
@@ -79,7 +81,7 @@ func (c *GeminiClient) Init(timeoutSec float64, verbose bool) error {
|
|||||||
|
|
||||||
c.Timeout = time.Duration(timeoutSec * float64(time.Second))
|
c.Timeout = time.Duration(timeoutSec * float64(time.Second))
|
||||||
if verbose {
|
if verbose {
|
||||||
Success("Gemini client initialized successfully.")
|
log.Infof("Gemini client initialized successfully.")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,131 +0,0 @@
|
|||||||
package geminiwebapi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// init honors GEMINI_WEBAPI_LOG to keep parity with the Python client.
|
|
||||||
func init() {
|
|
||||||
if lvl := os.Getenv("GEMINI_WEBAPI_LOG"); lvl != "" {
|
|
||||||
SetLogLevel(lvl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLogLevel adjusts logging verbosity using CLI-style strings.
|
|
||||||
func SetLogLevel(level string) {
|
|
||||||
switch strings.ToUpper(level) {
|
|
||||||
case "TRACE":
|
|
||||||
log.SetLevel(log.TraceLevel)
|
|
||||||
case "DEBUG":
|
|
||||||
log.SetLevel(log.DebugLevel)
|
|
||||||
case "INFO":
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
case "WARNING", "WARN":
|
|
||||||
log.SetLevel(log.WarnLevel)
|
|
||||||
case "ERROR":
|
|
||||||
log.SetLevel(log.ErrorLevel)
|
|
||||||
case "CRITICAL", "FATAL":
|
|
||||||
log.SetLevel(log.FatalLevel)
|
|
||||||
default:
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func prefix(format string) string { return "[gemini_webapi] " + format }
|
|
||||||
|
|
||||||
func Debug(format string, v ...any) { log.Debugf(prefix(format), v...) }
|
|
||||||
|
|
||||||
// DebugRaw logs without the module prefix; use sparingly for messages
|
|
||||||
// that should integrate with global formatting without extra tags.
|
|
||||||
func DebugRaw(format string, v ...any) { log.Debugf(format, v...) }
|
|
||||||
func Info(format string, v ...any) { log.Infof(prefix(format), v...) }
|
|
||||||
func Warning(format string, v ...any) { log.Warnf(prefix(format), v...) }
|
|
||||||
func Error(format string, v ...any) { log.Errorf(prefix(format), v...) }
|
|
||||||
func Success(format string, v ...any) { log.Infof(prefix("SUCCESS "+format), v...) }
|
|
||||||
|
|
||||||
// MaskToken28 returns a fixed-length (28) masked representation showing:
|
|
||||||
// first 8 chars + 8 asterisks + 4 middle chars + last 8 chars.
|
|
||||||
// If the input is shorter than 20 characters, it returns a fully masked string
|
|
||||||
// of length min(len(s), 28).
|
|
||||||
func MaskToken28(s string) string {
|
|
||||||
n := len(s)
|
|
||||||
if n == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if n < 20 {
|
|
||||||
return strings.Repeat("*", n)
|
|
||||||
}
|
|
||||||
// Pick 4 middle characters around the center
|
|
||||||
midStart := n/2 - 2
|
|
||||||
if midStart < 8 {
|
|
||||||
midStart = 8
|
|
||||||
}
|
|
||||||
if midStart+4 > n-8 {
|
|
||||||
midStart = n - 8 - 4
|
|
||||||
if midStart < 8 {
|
|
||||||
midStart = 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prefixByte := s[:8]
|
|
||||||
middle := s[midStart : midStart+4]
|
|
||||||
suffix := s[n-8:]
|
|
||||||
return prefixByte + strings.Repeat("*", 4) + middle + strings.Repeat("*", 4) + suffix
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildUpstreamRequestLog builds a compact preview string for upstream request logging.
|
|
||||||
func BuildUpstreamRequestLog(account string, contextOn bool, useTags, explicitContext bool, prompt string, filesCount int, reuse bool, metaLen int, gem *Gem) string {
|
|
||||||
var sb strings.Builder
|
|
||||||
sb.WriteString("\n\n=== GEMINI WEB UPSTREAM ===\n")
|
|
||||||
sb.WriteString(fmt.Sprintf("account: %s\n", account))
|
|
||||||
if contextOn {
|
|
||||||
sb.WriteString("context_mode: on\n")
|
|
||||||
} else {
|
|
||||||
sb.WriteString("context_mode: off\n")
|
|
||||||
}
|
|
||||||
if reuse {
|
|
||||||
sb.WriteString("reuseIdx: 1\n")
|
|
||||||
} else {
|
|
||||||
sb.WriteString("reuseIdx: 0\n")
|
|
||||||
}
|
|
||||||
sb.WriteString(fmt.Sprintf("useTags: %t\n", useTags))
|
|
||||||
sb.WriteString(fmt.Sprintf("metadata_len: %d\n", metaLen))
|
|
||||||
if explicitContext {
|
|
||||||
sb.WriteString("explicit_context: true\n")
|
|
||||||
} else {
|
|
||||||
sb.WriteString("explicit_context: false\n")
|
|
||||||
}
|
|
||||||
if filesCount > 0 {
|
|
||||||
sb.WriteString(fmt.Sprintf("files: %d\n", filesCount))
|
|
||||||
}
|
|
||||||
|
|
||||||
if gem != nil {
|
|
||||||
sb.WriteString("gem:\n")
|
|
||||||
if gem.ID != "" {
|
|
||||||
sb.WriteString(fmt.Sprintf(" id: %s\n", gem.ID))
|
|
||||||
}
|
|
||||||
if gem.Name != "" {
|
|
||||||
sb.WriteString(fmt.Sprintf(" name: %s\n", gem.Name))
|
|
||||||
}
|
|
||||||
sb.WriteString(fmt.Sprintf(" predefined: %t\n", gem.Predefined))
|
|
||||||
} else {
|
|
||||||
sb.WriteString("gem: none\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
chunks := ChunkByRunes(prompt, 4096)
|
|
||||||
preview := prompt
|
|
||||||
truncated := false
|
|
||||||
if len(chunks) > 1 {
|
|
||||||
preview = chunks[0]
|
|
||||||
truncated = true
|
|
||||||
}
|
|
||||||
sb.WriteString("prompt_preview:\n")
|
|
||||||
sb.WriteString(preview)
|
|
||||||
if truncated {
|
|
||||||
sb.WriteString("\n... [truncated]\n")
|
|
||||||
}
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/interfaces"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/interfaces"
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/misc"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/misc"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ func (i Image) Save(path string, filename string, cookies map[string]string, ver
|
|||||||
filename = m[1]
|
filename = m[1]
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if verbose {
|
||||||
Warning("Invalid filename: %s", filename)
|
log.Warnf("Invalid filename: %s", filename)
|
||||||
}
|
}
|
||||||
if skipInvalidFilename {
|
if skipInvalidFilename {
|
||||||
return "", nil
|
return "", nil
|
||||||
@@ -125,7 +126,7 @@ func (i Image) Save(path string, filename string, cookies map[string]string, ver
|
|||||||
return "", fmt.Errorf("error downloading image: %d %s", resp.StatusCode, resp.Status)
|
return "", fmt.Errorf("error downloading image: %d %s", resp.StatusCode, resp.Status)
|
||||||
}
|
}
|
||||||
if ct := resp.Header.Get("Content-Type"); ct != "" && !strings.Contains(strings.ToLower(ct), "image") {
|
if ct := resp.Header.Get("Content-Type"); ct != "" && !strings.Contains(strings.ToLower(ct), "image") {
|
||||||
Warning("Content type of %s is not image, but %s.", filename, ct)
|
log.Warnf("Content type of %s is not image, but %s.", filename, ct)
|
||||||
}
|
}
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = "temp"
|
path = "temp"
|
||||||
@@ -144,7 +145,7 @@ func (i Image) Save(path string, filename string, cookies map[string]string, ver
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if verbose {
|
if verbose {
|
||||||
Info("Image saved as %s", dest)
|
log.Infof("Image saved as %s", dest)
|
||||||
}
|
}
|
||||||
abspath, _ := filepath.Abs(dest)
|
abspath, _ := filepath.Abs(dest)
|
||||||
return abspath, nil
|
return abspath, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user