2 Commits
Author SHA1 Message Date
sun 7e2d050d51 feat(volcano): add upstream TTS request diagnostic log
移除了README中旧的环境配置日志说明部分,新增火山TTS上游请求的诊断日志,打印关键请求参数和请求体用于排查问题
2026-07-01 14:31:40 +08:00
sun f39c72acbe refactor(setting): 优化配置启动日志与错误提示
1. 移除main.go中重复的TTS配置错误警告
2. 统一日志中文全角逗号格式
3. 新增TTS配置项脱敏掩码函数
4. 完善启动日志的必填项检查和状态展示
5. 调整TTS配置错误的提示文案,明确500路由情况
2026-07-01 00:13:15 +08:00
4 changed files with 56 additions and 27 deletions
-15
View File
@@ -285,21 +285,6 @@ curl.exe -v -X POST "http://localhost:8080/v1/audio/speech" -H "Content-Type: ap
### 7. 查看日志
****启动期环境配置汇总**(每次启动打印一次,便于核对环境变量是否生效):
```
[TTS-Server] main.go:31: === 环境配置汇总 ===
[TTS-Server] main.go:32: 服务端口: 8080
[TTS-Server] main.go:35: OPENAI_TTS_API_KEY: 已设置 1 个有效密钥
[TTS-Server] main.go:41: ALLOWED_ORIGINS: 已配置 1 个允许的跨域来源白名单
[TTS-Server] main.go:46: 火山 TTS 配置: 初始化成功 (model=seed-tts-2.0-standard, format=mp3, sample_rate=24000, timeout=30s)
```
TTS 必填项缺失时会改为打印 `火山 TTS 配置: 初始化失败 - 缺少必需的环境变量: [BYTEDANCE_TTS_API_KEY] (TTS 功能不可用)`,服务继续运行但 `/v1/audio/speech` 路由会返回 500。
所有环境变量由 `setting` 包集中读取(其它包不允许直接 `os.Getenv`),`/health` 端点的 `ConfigStatus` 字段直接读全局 Config 状态,不存在重复读取。
服务启动后输出到 stdout/stderr。常见日志关键字:
**中间件层拒绝**(有专门日志):
+3
View File
@@ -219,6 +219,9 @@ func Synthesis(config *dto.ByteDanceTTSConfig, httpClient *HTTPClient, text stri
if err != nil {
return nil, fmt.Errorf("marshal TTS request: %w", err)
}
// 诊断日志:记录实际发到上游的请求体(去 model/speaker/resource 关键字段)
log.Printf("TTS upstream request: X-Api-Resource-Id=%s speaker=%s model=%s namespace=UnidirectionalTTS body=%s",
config.ResourceId, speaker, model, string(body))
// 鉴权 header 按 v3 新版控制台方式(Connection 由 Go http 默认 keep-alive)
headers := map[string]string{
+2 -4
View File
@@ -23,17 +23,15 @@ func main() {
// 所有环境变量读取在 setting 包内集中完成,业务模块只读全局 Config。
setting.InitAllConfigs()
// 兼容旧调用顺序:rate limiter / 静态文件 / stats / controller 的初始化保持独立。
// 兼容旧调用顺序:rate limiter / 静态文件 / stats / controller 的初始化保持独立。
middleware.InitRateLimiter()
setting.CheckStaticFiles()
service.InitStats()
controller.InitController()
// 启动期一次性打印所有 Config 状态,便于运维核对。
// (必填项缺失的明确警告由 LogStartupSummary 自身负责,避免重复打印。)
setting.LogStartupSummary()
if setting.TTSConfigErr != nil {
log.Printf("警告: 服务将继续运行,但 TTS 功能不可用,请检查环境变量配置")
}
controller.SetStartTime(time.Now())
+51 -8
View File
@@ -140,7 +140,7 @@ func InitTTSConfig() error {
if parsedTimeout, err := time.ParseDuration(timeoutStr); err == nil {
timeout = parsedTimeout
} else {
log.Printf("无效的超时设置 '%s',使用默认值: %v", timeoutStr, timeout)
log.Printf("无效的超时设置 '%s',使用默认值: %v", timeoutStr, timeout)
}
}
@@ -154,12 +154,12 @@ func InitTTSConfig() error {
sampleRate := 24000
if srStr := os.Getenv("BYTEDANCE_TTS_SAMPLE_RATE"); srStr != "" {
if sr, err := fmt.Sscanf(srStr, "%d", &sampleRate); err != nil || sr != 1 {
log.Printf("无效的采样率设置 '%s',使用默认值: 24000", srStr)
log.Printf("无效的采样率设置 '%s',使用默认值: 24000", srStr)
sampleRate = 24000
}
validRates := map[int]bool{8000: true, 16000: true, 22050: true, 24000: true, 32000: true, 44100: true, 48000: true}
if !validRates[sampleRate] {
log.Printf("不支持的采样率 %d,使用默认值: 24000", sampleRate)
log.Printf("不支持的采样率 %d,使用默认值: 24000", sampleRate)
sampleRate = 24000
}
}
@@ -179,14 +179,17 @@ func InitTTSConfig() error {
// LogStartupSummary 在启动期打印所有 Config 的最终状态。
// 调用时机:InitAllConfigs 之后,ListenAndServe 之前。
// 必填项逐项输出,失败分支明确告知"v1/audio/speech 路由将 500"。
func LogStartupSummary() {
log.Printf("=== 环境配置汇总 ===")
log.Printf("服务端口: %s", Server.Port)
if len(Auth.APIKeys) == 0 {
log.Printf("OPENAI_TTS_API_KEY: 未设置(所有请求无需鉴权)")
} else {
log.Printf("OPENAI_TTS_API_KEY: 已设置 %d 个有效密钥", len(Auth.APIKeys))
}
if CORS.AllowAll {
log.Printf("ALLOWED_ORIGINS: *(允许所有跨域,不可与凭据共用)")
} else if len(CORS.Origins) == 0 {
@@ -194,12 +197,52 @@ func LogStartupSummary() {
} else {
log.Printf("ALLOWED_ORIGINS: 已配置 %d 个允许的跨域来源白名单", len(CORS.Origins))
}
if TTSConfigErr != nil {
log.Printf("火山 TTS 配置: 初始化失败 - %v (TTS 功能不可用)", TTSConfigErr)
} else {
log.Printf("火山 TTS 配置: 初始化成功 (model=%s, format=%s, sample_rate=%d, timeout=%v)",
TTSConfig.Model, TTSConfig.Format, TTSConfig.SampleRate, TTSConfig.Timeout)
// 火山 TTS 必填项逐项状态:缺则 ❌,有则 ✓(API Key 脱敏,仅显示头尾各 4 字符)
log.Printf("火山 TTS 必填项状态:")
type ttsCheck struct {
name string
value string
ok bool
}
checks := []ttsCheck{
{"BYTEDANCE_TTS_API_KEY", maskAPIKey(TTSConfig.ApiKey), TTSConfig.ApiKey != ""},
{"BYTEDANCE_TTS_RESOURCE_ID", TTSConfig.ResourceId, TTSConfig.ResourceId != ""},
{"BYTEDANCE_TTS_SPEAKER", TTSConfig.Speaker, TTSConfig.Speaker != ""},
}
missingCount := 0
for _, c := range checks {
mark := "✓"
if !c.ok {
mark = "❌"
missingCount++
}
val := c.value
if val == "" {
val = "(未设置)"
}
log.Printf(" %s %s: %s", mark, c.name, val)
}
if TTSConfigErr != nil {
log.Printf("火山 TTS 整体: 初始化失败,%d 个必填项缺失,/v1/audio/speech 路由将全部返回 500", missingCount)
} else {
log.Printf("火山 TTS 可选项: model=%s, format=%s, sample_rate=%d, timeout=%v",
TTSConfig.Model, TTSConfig.Format, TTSConfig.SampleRate, TTSConfig.Timeout)
log.Printf("火山 TTS 整体: 初始化成功")
}
}
// maskAPIKey 对 API Key 脱敏,显示头 4 / 尾 4 字符,中间 * 号代替。
// 短于等于 8 字符整体掩为 ****,空串原样返回。
func maskAPIKey(key string) string {
if key == "" {
return ""
}
if len(key) <= 8 {
return "****"
}
return key[:4] + "****" + key[len(key)-4:]
}
// CheckEnvironmentVariables 返回环境变量状态,供 /health 端点使用。