refactor(tracing): remove Jaeger integration and related components
This commit removes Jaeger tracing support from the project, including the associated Docker configurations, Go modules, and middleware. The changes simplify the codebase by eliminating unused tracing functionality, which was previously integrated for observability. Documentation and scripts have also been updated to reflect the removal of Jaeger references.
This commit is contained in:
@@ -29,7 +29,6 @@ import (
|
||||
"github.com/Tencent/WeKnora/internal/container"
|
||||
"github.com/Tencent/WeKnora/internal/logger"
|
||||
"github.com/Tencent/WeKnora/internal/runtime"
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
"github.com/joho/godotenv"
|
||||
wailsruntime "github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
@@ -191,7 +190,6 @@ func main() {
|
||||
err := c.Invoke(func(
|
||||
cfg *config.Config,
|
||||
router *gin.Engine,
|
||||
tracer *tracing.Tracer,
|
||||
resourceCleaner interfaces.ResourceCleaner,
|
||||
) error {
|
||||
server := &http.Server{Handler: router}
|
||||
|
||||
@@ -36,7 +36,6 @@ import (
|
||||
"github.com/Tencent/WeKnora/internal/container"
|
||||
"github.com/Tencent/WeKnora/internal/logger"
|
||||
"github.com/Tencent/WeKnora/internal/runtime"
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
)
|
||||
|
||||
@@ -66,7 +65,6 @@ func main() {
|
||||
err := c.Invoke(func(
|
||||
cfg *config.Config,
|
||||
router *gin.Engine,
|
||||
tracer *tracing.Tracer,
|
||||
resourceCleaner interfaces.ResourceCleaner,
|
||||
systemSettingSvc interfaces.SystemSettingService,
|
||||
) error {
|
||||
|
||||
@@ -298,31 +298,6 @@ services:
|
||||
- WeKnora-network-dev
|
||||
restart: unless-stopped
|
||||
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:latest
|
||||
container_name: WeKnora-jaeger-dev
|
||||
ports:
|
||||
- "6831:6831/udp"
|
||||
- "6832:6832/udp"
|
||||
- "5778:5778"
|
||||
- "16686:16686"
|
||||
- "4317:4317"
|
||||
- "4318:4318"
|
||||
- "14250:14250"
|
||||
- "14268:14268"
|
||||
- "9411:9411"
|
||||
environment:
|
||||
- COLLECTOR_OTLP_ENABLED=true
|
||||
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
|
||||
volumes:
|
||||
- jaeger_data_dev:/var/lib/jaeger
|
||||
networks:
|
||||
- WeKnora-network-dev
|
||||
restart: unless-stopped
|
||||
profiles:
|
||||
- jaeger
|
||||
- full
|
||||
|
||||
dex:
|
||||
image: dexidp/dex:latest
|
||||
container_name: WeKnora-dex-dev
|
||||
@@ -547,7 +522,6 @@ volumes:
|
||||
redis_data_dev:
|
||||
minio_data_dev:
|
||||
neo4j-data-dev:
|
||||
jaeger_data_dev:
|
||||
qdrant_data_dev:
|
||||
opensearch_data_dev:
|
||||
milvus_data_dev:
|
||||
|
||||
@@ -82,12 +82,6 @@ services:
|
||||
- DB_NAME=${DB_NAME:-}
|
||||
- TZ=${TZ:-Asia/Shanghai}
|
||||
- WEKNORA_LANGUAGE=${WEKNORA_LANGUAGE:-zh-CN}
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=jaeger:4317
|
||||
- OTEL_SERVICE_NAME=WeKnora
|
||||
- OTEL_TRACES_EXPORTER=otlp
|
||||
- OTEL_METRICS_EXPORTER=none
|
||||
- OTEL_LOGS_EXPORTER=none
|
||||
- OTEL_PROPAGATORS=tracecontext,baggage
|
||||
# ========== Langfuse (optional observability) ==========
|
||||
# Enabled automatically when LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY are set.
|
||||
# See docs/Langfuse集成.md for the full list of tuning knobs.
|
||||
@@ -398,31 +392,6 @@ services:
|
||||
- minio
|
||||
- full
|
||||
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:1.76.0
|
||||
container_name: WeKnora-jaeger
|
||||
ports:
|
||||
- "6831:6831/udp" # Jaeger Thrift接收器
|
||||
- "6832:6832/udp" # Jaeger Thrift接收器(Compact)
|
||||
- "5778:5778" # 配置端口
|
||||
- "16686:16686" # Web UI
|
||||
- "4317:4317" # OTLP gRPC接收器
|
||||
- "4318:4318" # OTLP HTTP接收器
|
||||
- "14250:14250" # 接收模型端口
|
||||
- "14268:14268" # Jaeger HTTP接收器
|
||||
- "9411:9411" # Zipkin兼容性端口
|
||||
environment:
|
||||
- COLLECTOR_OTLP_ENABLED=true
|
||||
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
|
||||
volumes:
|
||||
- jaeger_data:/var/lib/jaeger # 持久化 Jaeger 数据
|
||||
networks:
|
||||
- WeKnora-network
|
||||
restart: unless-stopped
|
||||
profiles:
|
||||
- jaeger
|
||||
- full
|
||||
|
||||
neo4j:
|
||||
image: neo4j:2025.10.1
|
||||
container_name: WeKnora-neo4j
|
||||
@@ -822,7 +791,6 @@ volumes:
|
||||
postgres-data:
|
||||
data-files:
|
||||
docreader-tmp:
|
||||
jaeger_data:
|
||||
minio_data:
|
||||
neo4j-data:
|
||||
qdrant_data:
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ INIT_RERANK_MODEL_API_KEY=your_rerank_model_api_key
|
||||
# 启动 MinIO 服务
|
||||
docker-compose --profile minio up -d
|
||||
|
||||
# 或者启动完整服务(包括 MinIO、Jaeger、Neo4j、Qdrant)
|
||||
# 或者启动完整服务(包括 MinIO、Neo4j、Qdrant)
|
||||
docker-compose --profile full up -d
|
||||
```
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ make dev-frontend
|
||||
| Redis | localhost:6379 |
|
||||
| MinIO Console | http://localhost:9001 |
|
||||
| Neo4j Browser | http://localhost:7474 |
|
||||
| Jaeger UI | http://localhost:16686 |
|
||||
|
||||
> Neo4j 的使用参见 [知识图谱](../核心功能/知识图谱.md) 和 [开启知识图谱功能](../核心功能/开启知识图谱功能.md)
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ make dev-start
|
||||
- MinIO(对象存储)
|
||||
- Neo4j(图数据库)
|
||||
- DocReader(文档读取服务)
|
||||
- Jaeger(链路追踪)
|
||||
|
||||
#### 2. 启动后端应用(新终端)
|
||||
|
||||
@@ -79,7 +78,6 @@ make dev-stop
|
||||
- **Redis**: localhost:6379
|
||||
- **MinIO Console**: http://localhost:9001
|
||||
- **Neo4j Browser**: http://localhost:7474
|
||||
- **Jaeger UI**: http://localhost:16686
|
||||
|
||||
## 开发工作流对比
|
||||
|
||||
@@ -227,7 +225,6 @@ VS Code 配置示例(`.vscode/launch.json`):
|
||||
"DOCREADER_ADDR": "localhost:50051",
|
||||
"MINIO_ENDPOINT": "localhost:9000",
|
||||
"REDIS_ADDR": "localhost:6379",
|
||||
"OTEL_EXPORTER_OTLP_ENDPOINT": "localhost:4317",
|
||||
"NEO4J_URI": "bolt://localhost:7687"
|
||||
},
|
||||
"args": []
|
||||
|
||||
@@ -65,12 +65,6 @@ require (
|
||||
github.com/weaviate/weaviate-go-client/v5 v5.7.3
|
||||
github.com/xuri/excelize/v2 v2.10.1
|
||||
github.com/yanyiwu/gojieba v1.4.7
|
||||
go.opentelemetry.io/otel v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0
|
||||
go.opentelemetry.io/otel/sdk v1.43.0
|
||||
go.opentelemetry.io/otel/trace v1.43.0
|
||||
go.uber.org/dig v1.19.0
|
||||
golang.org/x/crypto v0.51.0
|
||||
golang.org/x/mod v0.36.0
|
||||
@@ -310,7 +304,12 @@ require (
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
|
||||
go.opentelemetry.io/otel v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/automaxprocs v1.5.3 // indirect
|
||||
|
||||
@@ -2669,8 +2669,6 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRl
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU=
|
||||
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
|
||||
|
||||
@@ -230,7 +230,6 @@ These map to docker-compose profiles:
|
||||
| `minio.enabled` | Enable MinIO storage | `false` |
|
||||
| `neo4j.enabled` | Enable Neo4j (GraphRAG) | `false` |
|
||||
| `qdrant.enabled` | Enable Qdrant vector DB | `false` |
|
||||
| `jaeger.enabled` | Enable Jaeger tracing | `false` |
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ Components deployed:
|
||||
- Redis ({{ include "weknora.redis.image" . }})
|
||||
{{- end }}
|
||||
|
||||
{{- if or .Values.minio.enabled .Values.neo4j.enabled .Values.qdrant.enabled .Values.jaeger.enabled }}
|
||||
{{- if or .Values.minio.enabled .Values.neo4j.enabled .Values.qdrant.enabled }}
|
||||
|
||||
Optional components enabled:
|
||||
{{- if .Values.minio.enabled }}
|
||||
@@ -77,9 +77,6 @@ Optional components enabled:
|
||||
{{- if .Values.qdrant.enabled }}
|
||||
- Qdrant (Vector Database)
|
||||
{{- end }}
|
||||
{{- if .Values.jaeger.enabled }}
|
||||
- Jaeger (Distributed Tracing)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -492,12 +492,3 @@ qdrant:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
|
||||
# -- Jaeger configuration (Distributed Tracing)
|
||||
# Equivalent to: docker compose --profile jaeger
|
||||
jaeger:
|
||||
# -- Enable Jaeger tracing
|
||||
enabled: false
|
||||
image:
|
||||
repository: jaegertracing/all-in-one
|
||||
tag: latest
|
||||
|
||||
@@ -19,14 +19,12 @@ import (
|
||||
"github.com/Tencent/WeKnora/internal/models/chat"
|
||||
"github.com/Tencent/WeKnora/internal/models/embedding"
|
||||
"github.com/Tencent/WeKnora/internal/searchutil"
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
"github.com/Tencent/WeKnora/internal/tracing/langfuse"
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
secutils "github.com/Tencent/WeKnora/internal/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/hibiken/asynq"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
func (s *knowledgeService) cloneKnowledge(
|
||||
@@ -258,22 +256,11 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
options = opts[0]
|
||||
}
|
||||
|
||||
ctx, span := tracing.ContextWithSpan(ctx, "knowledgeService.processChunks")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.Int("tenant_id", int(knowledge.TenantID)),
|
||||
attribute.String("knowledge_base_id", knowledge.KnowledgeBaseID),
|
||||
attribute.String("knowledge_id", knowledge.ID),
|
||||
attribute.String("embedding_model_id", kb.EmbeddingModelID),
|
||||
attribute.Int("chunk_count", len(chunks)),
|
||||
)
|
||||
|
||||
// Check if knowledge is being deleted/cancelled before processing.
|
||||
// Both statuses short-circuit identically here — there's nothing to clean
|
||||
// up yet so the branch is purely "stop early".
|
||||
if aborted, status := s.isKnowledgeAborted(ctx, knowledge.TenantID, knowledge.ID); aborted {
|
||||
logger.Infof(ctx, "Knowledge aborted (%s), skipping chunk processing: %s", status, knowledge.ID)
|
||||
span.AddEvent("aborted: knowledge " + status)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -284,7 +271,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
embeddingModel, err = s.modelService.GetEmbeddingModel(ctx, kb.EmbeddingModelID)
|
||||
if err != nil {
|
||||
logger.GetLogger(ctx).WithField("error", err).Errorf("processChunks get embedding model failed")
|
||||
span.RecordError(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -489,14 +475,12 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
// Nothing has been persisted yet, so both branches just bail.
|
||||
if aborted, status := s.isKnowledgeAborted(ctx, knowledge.TenantID, knowledge.ID); aborted {
|
||||
logger.Infof(ctx, "Knowledge aborted (%s), skipping chunk write: %s", status, knowledge.ID)
|
||||
span.AddEvent("aborted: knowledge " + status + " before saving")
|
||||
return
|
||||
}
|
||||
|
||||
// Save chunks to database — ALWAYS, regardless of indexing strategy.
|
||||
// Chunks are needed for wiki generation, graph extraction, and summary generation
|
||||
// even when vector/keyword indexing is disabled.
|
||||
span.AddEvent("create chunks")
|
||||
s.beginStage(ctx, knowledge.ID, types.StageChunking, types.JSONMap{
|
||||
"chunks_planned": len(insertChunks),
|
||||
})
|
||||
@@ -505,7 +489,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
knowledge.ErrorMessage = err.Error()
|
||||
knowledge.UpdatedAt = time.Now()
|
||||
s.repo.UpdateKnowledge(ctx, knowledge)
|
||||
span.RecordError(err)
|
||||
s.failStage(ctx, knowledge.ID, types.StageChunking,
|
||||
werrors.ErrCodeChunkingFailed, "create chunks failed", err)
|
||||
return
|
||||
@@ -557,7 +540,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
}
|
||||
|
||||
// Calculate storage size required for embeddings
|
||||
span.AddEvent("estimate storage size")
|
||||
totalStorageSize = retrieveEngine.EstimateStorageSize(ctx, embeddingModel, indexInfoList)
|
||||
if tenantInfo.StorageQuota > 0 {
|
||||
// Re-fetch tenant storage information
|
||||
@@ -567,7 +549,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
knowledge.ErrorMessage = err.Error()
|
||||
knowledge.UpdatedAt = time.Now()
|
||||
s.repo.UpdateKnowledge(ctx, knowledge)
|
||||
span.RecordError(err)
|
||||
return
|
||||
}
|
||||
// Check if there's enough storage quota available
|
||||
@@ -576,7 +557,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
knowledge.ErrorMessage = "存储空间不足"
|
||||
knowledge.UpdatedAt = time.Now()
|
||||
s.repo.UpdateKnowledge(ctx, knowledge)
|
||||
span.RecordError(errors.New("storage quota exceeded"))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -591,11 +571,9 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
logger.Warnf(ctx, "Failed to cleanup chunks after deletion detected: %v", err)
|
||||
}
|
||||
}
|
||||
span.AddEvent("aborted: knowledge " + status + " before indexing")
|
||||
return
|
||||
}
|
||||
|
||||
span.AddEvent("batch index")
|
||||
err = retrieveEngine.BatchIndex(ctx, embeddingModel, indexInfoList)
|
||||
if err != nil {
|
||||
knowledge.ParseStatus = types.ParseStatusFailed
|
||||
@@ -614,7 +592,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
); err != nil {
|
||||
logger.Errorf(ctx, "Delete index failed: %v", err)
|
||||
}
|
||||
span.RecordError(err)
|
||||
// Map vector store / embedding rate-limit errors to a
|
||||
// stable code so the UI can offer "retry later" hints.
|
||||
code := werrors.ErrCodeVectorStoreWriteFailed
|
||||
@@ -645,7 +622,6 @@ func (s *knowledgeService) processChunks(ctx context.Context,
|
||||
logger.Warnf(ctx, "Failed to cleanup index after deletion detected: %v", err)
|
||||
}
|
||||
}
|
||||
span.AddEvent("aborted: knowledge " + status + " during processing")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -11,10 +11,8 @@ import (
|
||||
"github.com/Tencent/WeKnora/internal/common"
|
||||
"github.com/Tencent/WeKnora/internal/logger"
|
||||
"github.com/Tencent/WeKnora/internal/models/embedding"
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// engineInfo holds information about a retrieve engine and its supported retriever types
|
||||
@@ -200,8 +198,6 @@ func (c *CompositeRetrieveEngine) concurrentExecWithError(
|
||||
func (c *CompositeRetrieveEngine) Index(ctx context.Context,
|
||||
embedder embedding.Embedder, indexInfo *types.IndexInfo,
|
||||
) error {
|
||||
ctx, span := tracing.ContextWithSpan(ctx, "CompositeRetrieveEngine.Index")
|
||||
defer span.End()
|
||||
err := c.concurrentExecWithError(ctx, func(ctx context.Context, engineInfo *engineInfo) error {
|
||||
if err := engineInfo.retrieveEngine.Index(ctx, embedder, indexInfo, engineInfo.retrieverType); err != nil {
|
||||
logger.Errorf(ctx, "Repository %s failed to save: %v", engineInfo.retrieveEngine.EngineType(), err)
|
||||
@@ -209,11 +205,6 @@ func (c *CompositeRetrieveEngine) Index(ctx context.Context,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
span.RecordError(err)
|
||||
span.SetAttributes(
|
||||
attribute.String("embedder", embedder.GetModelName()),
|
||||
attribute.String("source_id", indexInfo.SourceID),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -221,8 +212,6 @@ func (c *CompositeRetrieveEngine) Index(ctx context.Context,
|
||||
func (c *CompositeRetrieveEngine) BatchIndex(ctx context.Context,
|
||||
embedder embedding.Embedder, indexInfoList []*types.IndexInfo,
|
||||
) error {
|
||||
ctx, span := tracing.ContextWithSpan(ctx, "CompositeRetrieveEngine.BatchIndex")
|
||||
defer span.End()
|
||||
// Deduplicate sourceIDs
|
||||
indexInfoList = common.Deduplicate(func(info *types.IndexInfo) string { return info.SourceID }, indexInfoList...)
|
||||
err := c.concurrentExecWithError(ctx, func(ctx context.Context, engineInfo *engineInfo) error {
|
||||
@@ -237,11 +226,6 @@ func (c *CompositeRetrieveEngine) BatchIndex(ctx context.Context,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
span.RecordError(err)
|
||||
span.SetAttributes(
|
||||
attribute.String("embedder", embedder.GetModelName()),
|
||||
attribute.Int("index_info_count", len(indexInfoList)),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -318,18 +302,13 @@ func (c *CompositeRetrieveEngine) DeleteByKnowledgeIDList(ctx context.Context,
|
||||
func (c *CompositeRetrieveEngine) EstimateStorageSize(ctx context.Context,
|
||||
embedder embedding.Embedder, indexInfoList []*types.IndexInfo,
|
||||
) int64 {
|
||||
ctx, span := tracing.ContextWithSpan(ctx, "CompositeRetrieveEngine.EstimateStorageSize")
|
||||
defer span.End()
|
||||
sum := atomic.Int64{}
|
||||
err := c.concurrentExecWithError(ctx, func(ctx context.Context, engineInfo *engineInfo) error {
|
||||
sum.Add(engineInfo.retrieveEngine.EstimateStorageSize(ctx, embedder, indexInfoList, engineInfo.retrieverType))
|
||||
return nil
|
||||
})
|
||||
span.RecordError(err)
|
||||
span.SetAttributes(
|
||||
attribute.String("embedder", embedder.GetModelName()),
|
||||
attribute.Int("index_info_count", len(indexInfoList)),
|
||||
attribute.Int64("storage_size", sum.Load()),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Errorf(ctx, "EstimateStorageSize failed: %v", err)
|
||||
}
|
||||
return sum.Load()
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ import (
|
||||
"github.com/Tencent/WeKnora/internal/models/utils/ollama"
|
||||
"github.com/Tencent/WeKnora/internal/router"
|
||||
"github.com/Tencent/WeKnora/internal/stream"
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
"github.com/Tencent/WeKnora/internal/tracing/langfuse"
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
@@ -107,15 +106,12 @@ func BuildContainer(container *dig.Container) *dig.Container {
|
||||
// Core infrastructure configuration
|
||||
logger.Debugf(ctx, "[Container] Registering core infrastructure...")
|
||||
must(container.Provide(config.LoadConfig))
|
||||
must(container.Provide(initTracer))
|
||||
must(container.Provide(initLangfuse))
|
||||
must(container.Provide(initDatabase))
|
||||
must(container.Provide(initFileService))
|
||||
must(container.Provide(initRedisClient))
|
||||
must(container.Provide(initAntsPool))
|
||||
|
||||
// Register tracer cleanup handler (tracer needs to be available for cleanup registration)
|
||||
must(container.Invoke(registerTracerCleanup))
|
||||
must(container.Invoke(registerLangfuseCleanup))
|
||||
|
||||
// Register goroutine pool cleanup handler
|
||||
@@ -414,18 +410,6 @@ func must(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// initTracer initializes OpenTelemetry tracer
|
||||
// Sets up distributed tracing for observability across the application
|
||||
// Parameters:
|
||||
// - None
|
||||
//
|
||||
// Returns:
|
||||
// - Configured tracer instance
|
||||
// - Error if initialization fails
|
||||
func initTracer() (*tracing.Tracer, error) {
|
||||
return tracing.InitTracer()
|
||||
}
|
||||
|
||||
// initLangfuse initializes the Langfuse ingestion client.
|
||||
// Configuration is read from LANGFUSE_* environment variables (see
|
||||
// docs/langfuse.md). Returns a disabled manager if credentials are absent —
|
||||
@@ -1205,19 +1189,6 @@ func registerPoolCleanup(pool *ants.Pool, cleaner interfaces.ResourceCleaner) {
|
||||
})
|
||||
}
|
||||
|
||||
// registerTracerCleanup registers the tracer for cleanup
|
||||
// Ensures proper cleanup of the tracer when application shuts down
|
||||
// Parameters:
|
||||
// - tracer: Tracer instance
|
||||
// - cleaner: Resource cleaner
|
||||
func registerTracerCleanup(tracer *tracing.Tracer, cleaner interfaces.ResourceCleaner) {
|
||||
// Register the cleanup function - actual context will be provided during cleanup
|
||||
cleaner.RegisterWithName("Tracer", func() error {
|
||||
// Create context for cleanup with longer timeout for tracer shutdown
|
||||
return tracer.Cleanup(context.Background())
|
||||
})
|
||||
}
|
||||
|
||||
// registerLangfuseCleanup ensures buffered Langfuse events are flushed on
|
||||
// shutdown. A 5-second timeout matches other external-service cleanups and
|
||||
// balances data durability against a slow remote endpoint holding up exit.
|
||||
|
||||
+1
-45
@@ -20,14 +20,10 @@ import (
|
||||
"github.com/Tencent/WeKnora/internal/event"
|
||||
"github.com/Tencent/WeKnora/internal/logger"
|
||||
"github.com/Tencent/WeKnora/internal/models/chat"
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
"github.com/google/uuid"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -667,14 +663,6 @@ func (s *Service) LoadAndStartChannels() error {
|
||||
// the leader lock and opens the connection; other instances periodically
|
||||
// retry so they can take over if the leader dies.
|
||||
func (s *Service) StartChannel(channel *IMChannel) error {
|
||||
_, span := tracing.ContextWithSpan(context.Background(), "im.StartChannel")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.String("im.channel_id", channel.ID),
|
||||
attribute.String("im.platform", channel.Platform),
|
||||
attribute.String("im.mode", channel.Mode),
|
||||
)
|
||||
|
||||
s.mu.Lock()
|
||||
factory, ok := s.adapterFactories[channel.Platform]
|
||||
if !ok {
|
||||
@@ -1036,18 +1024,6 @@ func (s *Service) isDuplicate(ctx context.Context, messageID string) bool {
|
||||
|
||||
// HandleMessage processes an incoming IM message end-to-end using channel config.
|
||||
func (s *Service) HandleMessage(ctx context.Context, msg *IncomingMessage, channelID string) error {
|
||||
ctx, span := tracing.ContextWithSpan(ctx, "im.HandleMessage")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.String("im.channel_id", channelID),
|
||||
attribute.String("im.platform", string(msg.Platform)),
|
||||
attribute.String("im.user_id", msg.UserID),
|
||||
attribute.String("im.chat_id", msg.ChatID),
|
||||
attribute.String("im.thread_id", msg.ThreadID),
|
||||
attribute.String("im.message_type", string(msg.MessageType)),
|
||||
attribute.Bool("im.has_quote", msg.Quote != nil),
|
||||
)
|
||||
|
||||
// Dedup: skip if this message was already processed (IM platforms may retry)
|
||||
if msg.MessageID != "" {
|
||||
if s.isDuplicate(ctx, msg.MessageID) {
|
||||
@@ -1081,8 +1057,6 @@ func (s *Service) HandleMessage(ctx context.Context, msg *IncomingMessage, chann
|
||||
}
|
||||
}
|
||||
|
||||
span.SetAttributes(attribute.String("im.session_mode", channel.SessionMode))
|
||||
|
||||
// Resolve threadID for key building — only include in thread mode to avoid
|
||||
// leaking thread scope into user-mode rate limit / inflight keys.
|
||||
threadID := ""
|
||||
@@ -1223,7 +1197,6 @@ func (s *Service) HandleMessage(ctx context.Context, msg *IncomingMessage, chann
|
||||
pos, enqueueErr := s.qaQueue.Enqueue(req)
|
||||
if enqueueErr != nil {
|
||||
qaCancel()
|
||||
span.AddEvent("queue rejected", trace.WithAttributes(attribute.String("reason", enqueueErr.Error())))
|
||||
logger.Warnf(ctx, "[IM] Queue rejected: user=%s reason=%v", msg.UserID, enqueueErr)
|
||||
_ = adapter.SendReply(ctx, msg, &ReplyMessage{
|
||||
Content: "当前排队人数较多,请稍后再试。",
|
||||
@@ -1254,13 +1227,7 @@ func (s *Service) HandleMessage(ctx context.Context, msg *IncomingMessage, chann
|
||||
// executeQARequest is the worker handler that runs the QA pipeline for a queued request.
|
||||
// It is called by qaQueue workers and must not block indefinitely.
|
||||
func (s *Service) executeQARequest(req *qaRequest) {
|
||||
ctx, span := tracing.ContextWithSpan(req.ctx, "im.ExecuteQA")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.String("im.channel_id", req.channelID),
|
||||
attribute.String("im.user_key", req.userKey),
|
||||
attribute.String("im.user_id", req.msg.UserID),
|
||||
)
|
||||
ctx := req.ctx
|
||||
defer req.cancel()
|
||||
|
||||
// Track in-flight request so /stop can cancel it.
|
||||
@@ -1270,7 +1237,6 @@ func (s *Service) executeQARequest(req *qaRequest) {
|
||||
|
||||
// Check if a pre-execution /stop was issued while this request was queued.
|
||||
if s.checkAndClearStopMarker(ctx, req.userKey) {
|
||||
span.AddEvent("cancelled by remote /stop before execution")
|
||||
logger.Infof(ctx, "[IM] Request cancelled by remote /stop before execution: %s", req.userKey)
|
||||
return
|
||||
}
|
||||
@@ -1289,7 +1255,6 @@ func (s *Service) executeQARequest(req *qaRequest) {
|
||||
if !streamDisabled {
|
||||
if streamer, ok := req.adapter.(StreamSender); ok {
|
||||
if err := s.handleMessageStream(ctx, req.msg, req.session, req.agent, kbIDs, streamer, req.adapter, req.userKey, req.tenant); err != nil {
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
logger.Errorf(ctx, "[IM] Stream QA failed: %v", err)
|
||||
}
|
||||
return
|
||||
@@ -1299,7 +1264,6 @@ func (s *Service) executeQARequest(req *qaRequest) {
|
||||
// Non-streaming fallback: collect full answer then send.
|
||||
answer, err := s.runQA(ctx, req.session, req.msg.Content, req.agent, kbIDs, req.userKey, req.msg.Quote)
|
||||
if err != nil {
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
logger.Errorf(ctx, "[IM] QA failed: %v, sending fallback reply", err)
|
||||
answer = "抱歉,处理您的问题时出现了异常,请稍后再试。"
|
||||
}
|
||||
@@ -1329,14 +1293,6 @@ func (s *Service) handleCommand(
|
||||
channelSession *ChannelSession,
|
||||
customAgent *types.CustomAgent,
|
||||
) error {
|
||||
ctx, span := tracing.ContextWithSpan(ctx, "im.HandleCommand")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.String("im.command", cmd.Name()),
|
||||
attribute.String("im.channel_id", channel.ID),
|
||||
attribute.String("im.user_id", msg.UserID),
|
||||
)
|
||||
|
||||
agentName := ""
|
||||
if customAgent != nil {
|
||||
agentName = customAgent.Name
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/tracing"
|
||||
)
|
||||
|
||||
// Custom ResponseWriter to capture response content
|
||||
type responseBodyWriter struct {
|
||||
gin.ResponseWriter
|
||||
body *bytes.Buffer
|
||||
}
|
||||
|
||||
// Override Write method to write response content to buffer and original writer
|
||||
func (r responseBodyWriter) Write(b []byte) (int, error) {
|
||||
r.body.Write(b)
|
||||
return r.ResponseWriter.Write(b)
|
||||
}
|
||||
|
||||
// TracingMiddleware provides a Gin middleware that creates a trace span for each request
|
||||
func TracingMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Extract trace context from request headers
|
||||
propagator := tracing.GetTracer()
|
||||
if propagator == nil {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
// Create new span
|
||||
spanName := fmt.Sprintf("%s %s", c.Request.Method, c.FullPath())
|
||||
ctx, span := tracing.ContextWithSpan(c.Request.Context(), spanName)
|
||||
defer span.End()
|
||||
|
||||
// Set basic span attributes
|
||||
span.SetAttributes(
|
||||
attribute.String("http.method", c.Request.Method),
|
||||
attribute.String("http.url", c.Request.URL.String()),
|
||||
attribute.String("http.path", c.FullPath()),
|
||||
)
|
||||
|
||||
// Record request headers (optional, or selectively record important headers)
|
||||
for key, values := range c.Request.Header {
|
||||
// Skip sensitive or unnecessary headers
|
||||
if strings.ToLower(key) == "authorization" || strings.ToLower(key) == "cookie" {
|
||||
continue
|
||||
}
|
||||
span.SetAttributes(attribute.String("http.request.header."+key, strings.Join(values, ";")))
|
||||
}
|
||||
|
||||
// Record request body (for POST/PUT/PATCH requests)
|
||||
if c.Request.Method == "POST" || c.Request.Method == "PUT" || c.Request.Method == "PATCH" {
|
||||
if c.Request.Body != nil {
|
||||
bodyBytes, _ := io.ReadAll(c.Request.Body)
|
||||
span.SetAttributes(attribute.String("http.request.body", string(bodyBytes)))
|
||||
// Reset request body because ReadAll consumes the Reader content
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
}
|
||||
}
|
||||
|
||||
// Record query parameters
|
||||
if len(c.Request.URL.RawQuery) > 0 {
|
||||
span.SetAttributes(attribute.String("http.request.query", c.Request.URL.RawQuery))
|
||||
}
|
||||
|
||||
// Set request context with span context
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
|
||||
// Store tracing context in Gin context
|
||||
c.Set("trace.span", span)
|
||||
c.Set("trace.ctx", ctx)
|
||||
|
||||
// Create response body capturer
|
||||
responseBody := &bytes.Buffer{}
|
||||
responseWriter := &responseBodyWriter{
|
||||
ResponseWriter: c.Writer,
|
||||
body: responseBody,
|
||||
}
|
||||
c.Writer = responseWriter
|
||||
|
||||
// Process request
|
||||
c.Next()
|
||||
|
||||
// Set response status code
|
||||
statusCode := c.Writer.Status()
|
||||
span.SetAttributes(attribute.Int("http.status_code", statusCode))
|
||||
|
||||
// Record response body
|
||||
responseContent := responseBody.String()
|
||||
if len(responseContent) > 0 {
|
||||
span.SetAttributes(attribute.String("http.response.body", responseContent))
|
||||
}
|
||||
|
||||
// Record response headers (optional, or selectively record important headers)
|
||||
for key, values := range c.Writer.Header() {
|
||||
span.SetAttributes(attribute.String("http.response.header."+key, strings.Join(values, ";")))
|
||||
}
|
||||
|
||||
// Mark as error if status code >= 400
|
||||
if statusCode >= 400 {
|
||||
span.SetStatus(codes.Error, fmt.Sprintf("HTTP %d", statusCode))
|
||||
if err := c.Errors.Last(); err != nil {
|
||||
span.RecordError(err.Err)
|
||||
}
|
||||
} else {
|
||||
span.SetStatus(codes.Ok, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,9 +141,6 @@ func NewRouter(params RouterParams) *gin.Engine {
|
||||
// Diagnostic preview of presigned URLs (Admin only, behind auth middleware).
|
||||
servePresignedPreview(r, params.Config)
|
||||
|
||||
// 添加OpenTelemetry追踪中间件
|
||||
// r.Use(middleware.TracingMiddleware())
|
||||
|
||||
// Langfuse observability — only active when LANGFUSE_* env vars are set.
|
||||
// The middleware is registered unconditionally; when disabled it's a no-op.
|
||||
r.Use(langfuse.GinMiddleware())
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
AppName = "WeKnoraApp"
|
||||
)
|
||||
|
||||
type Tracer struct {
|
||||
Cleanup func(context.Context) error
|
||||
}
|
||||
|
||||
var tracer trace.Tracer
|
||||
|
||||
// InitTracer initializes OpenTelemetry tracer
|
||||
func InitTracer() (*Tracer, error) {
|
||||
// Create resource description
|
||||
labels := []attribute.KeyValue{
|
||||
semconv.TelemetrySDKLanguageGo,
|
||||
semconv.ServiceNameKey.String(AppName),
|
||||
}
|
||||
res := resource.NewWithAttributes(semconv.SchemaURL, labels...)
|
||||
var err error
|
||||
|
||||
// First try to create OTLP exporter (can connect to Jaeger, Zipkin, etc.)
|
||||
var traceExporter sdktrace.SpanExporter
|
||||
if endpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"); endpoint != "" {
|
||||
// Use gRPC exporter
|
||||
client := otlptracegrpc.NewClient(
|
||||
otlptracegrpc.WithEndpoint(endpoint),
|
||||
otlptracegrpc.WithInsecure(),
|
||||
)
|
||||
traceExporter, err = otlptrace.New(context.Background(), client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// If no OTLP endpoint is set, default to standard output
|
||||
traceExporter, err = stdouttrace.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create batch SpanProcessor
|
||||
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
|
||||
|
||||
sampler := sdktrace.AlwaysSample()
|
||||
|
||||
// Create and register TracerProvider
|
||||
tp := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sampler),
|
||||
sdktrace.WithResource(res),
|
||||
sdktrace.WithSpanProcessor(bsp),
|
||||
)
|
||||
otel.SetTracerProvider(tp)
|
||||
|
||||
// Set global propagator
|
||||
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
|
||||
propagation.TraceContext{},
|
||||
propagation.Baggage{},
|
||||
))
|
||||
|
||||
// Create Tracer for project use
|
||||
tracer = tp.Tracer(AppName)
|
||||
|
||||
// Return cleanup function
|
||||
return &Tracer{
|
||||
Cleanup: func(ctx context.Context) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
if err := tp.Shutdown(ctx); err != nil {
|
||||
log.Printf("Error shutting down tracer provider: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetTracer gets global Tracer
|
||||
func GetTracer() trace.Tracer {
|
||||
return tracer
|
||||
}
|
||||
|
||||
// Create context with span
|
||||
func ContextWithSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
return GetTracer().Start(ctx, name, opts...)
|
||||
}
|
||||
@@ -88,7 +88,6 @@ WeKnora `docker-compose.yml` 大量服务是 **profile 限定**,本镜像只
|
||||
| `minio` | 对象存储替代本地文件 |
|
||||
| `qdrant` / `milvus` / `weaviate` / `doris` | 替代 pgvector |
|
||||
| `neo4j` | GraphRAG 知识图谱 |
|
||||
| `jaeger` | OpenTelemetry trace UI |
|
||||
| `langfuse` | 自建 Langfuse 可观测平台 |
|
||||
| `dex` | OIDC 登录 |
|
||||
| `odl-hybrid` | OpenDataLoader Docling hybrid(体积大,无预发布镜像,需 `--build`) |
|
||||
|
||||
@@ -182,7 +182,7 @@ docker compose up -d
|
||||
echo "[prepare] 4.5/6 预拉 sandbox 镜像 (Agent Skills 用, 非常驻)"
|
||||
docker compose --profile full pull sandbox || true
|
||||
|
||||
# 其他向量库 / 可观测组件 (qdrant, milvus, weaviate, doris, neo4j, langfuse-*, minio, jaeger, dex)
|
||||
# 其他向量库 / 可观测组件 (qdrant, milvus, weaviate, doris, neo4j, langfuse-*, minio, dex)
|
||||
# 不预拉, 体积可省 5-15GB. 用户如需启用:
|
||||
# cd /opt/WeKnora && docker compose --profile <name> up -d
|
||||
|
||||
|
||||
+2
-12
@@ -68,7 +68,6 @@ show_help() {
|
||||
echo " --minio 启动 MinIO 对象存储"
|
||||
echo " --qdrant 启动 Qdrant 向量数据库"
|
||||
echo " --neo4j 启动 Neo4j 图数据库"
|
||||
echo " --jaeger 启动 Jaeger 链路追踪"
|
||||
echo " --dex 启动 Dex(OIDC 身份认证)"
|
||||
echo " --langfuse 启动 Langfuse(默认已开启)"
|
||||
echo " --no-langfuse 不启动 Langfuse"
|
||||
@@ -78,7 +77,6 @@ show_help() {
|
||||
echo "示例:"
|
||||
echo " $0 start # 启动基础服务"
|
||||
echo " $0 start --qdrant # 启动基础服务 + Qdrant"
|
||||
echo " $0 start --qdrant --jaeger # 启动基础服务 + Qdrant + Jaeger"
|
||||
echo " $0 start --dex # 启动基础服务 + Dex"
|
||||
echo " $0 start --odl-hybrid # 启动基础服务 + OpenDataLoader hybrid"
|
||||
echo " $0 start --full # 启动所有服务"
|
||||
@@ -172,7 +170,7 @@ start_services() {
|
||||
# 解析 profile 参数
|
||||
shift # 移除 "start" 命令本身
|
||||
# 默认启动基础设施(postgres / redis / docreader)+ langfuse,
|
||||
# 其余可选服务通过 --minio / --qdrant / --neo4j / --jaeger / --dex / --full 按需开启。
|
||||
# 其余可选服务通过 --minio / --qdrant / --neo4j / --dex / --full 按需开启。
|
||||
PROFILES="--profile langfuse"
|
||||
ENABLED_SERVICES="langfuse"
|
||||
while [ $# -gt 0 ]; do
|
||||
@@ -189,10 +187,6 @@ start_services() {
|
||||
PROFILES="$PROFILES --profile neo4j"
|
||||
ENABLED_SERVICES="$ENABLED_SERVICES neo4j"
|
||||
;;
|
||||
--jaeger)
|
||||
PROFILES="$PROFILES --profile jaeger"
|
||||
ENABLED_SERVICES="$ENABLED_SERVICES jaeger"
|
||||
;;
|
||||
--dex)
|
||||
PROFILES="$PROFILES --profile dex"
|
||||
ENABLED_SERVICES="$ENABLED_SERVICES dex"
|
||||
@@ -212,7 +206,7 @@ start_services() {
|
||||
;;
|
||||
--full)
|
||||
PROFILES="--profile full"
|
||||
ENABLED_SERVICES="minio qdrant neo4j jaeger dex"
|
||||
ENABLED_SERVICES="minio qdrant neo4j dex"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
@@ -254,9 +248,6 @@ start_services() {
|
||||
if [[ "$ENABLED_SERVICES" == *"neo4j"* ]]; then
|
||||
echo " - Neo4j: localhost:7474 (Bolt: localhost:7687)"
|
||||
fi
|
||||
if [[ "$ENABLED_SERVICES" == *"jaeger"* ]]; then
|
||||
echo " - Jaeger: localhost:16686"
|
||||
fi
|
||||
if [[ "$ENABLED_SERVICES" == *"dex"* ]]; then
|
||||
echo " - Dex: localhost:5556"
|
||||
fi
|
||||
@@ -349,7 +340,6 @@ start_app() {
|
||||
export MINIO_ENDPOINT=localhost:9000
|
||||
export REDIS_ADDR=localhost:6379
|
||||
export MILVUS_ADDRESS=localhost:19530
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317
|
||||
export NEO4J_URI=bolt://localhost:7687
|
||||
export QDRANT_HOST=localhost
|
||||
|
||||
|
||||
@@ -99,7 +99,6 @@ log_info "访问地址:"
|
||||
echo " - 前端: http://localhost:5173"
|
||||
echo " - 后端 API: http://localhost:8080"
|
||||
echo " - MinIO Console: http://localhost:9001"
|
||||
echo " - Jaeger UI: http://localhost:16686"
|
||||
echo ""
|
||||
|
||||
log_info "管理命令:"
|
||||
|
||||
@@ -749,7 +749,6 @@ else
|
||||
log_success "所有服务启动完成,可通过以下地址访问:"
|
||||
printf "%b\n" "${GREEN} - 前端界面: http://localhost:${FRONTEND_PORT:-80}${NC}"
|
||||
printf "%b\n" "${GREEN} - API接口: http://localhost:${APP_PORT:-8080}${NC}"
|
||||
printf "%b\n" "${GREEN} - Jaeger链路追踪: http://localhost:16686${NC}"
|
||||
echo ""
|
||||
log_info "正在持续输出容器日志(按 Ctrl+C 退出日志,容器不会停止)..."
|
||||
"$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD logs app docreader postgres --since=10s -f
|
||||
@@ -763,7 +762,6 @@ else
|
||||
log_success "Docker容器启动完成,可通过以下地址访问:"
|
||||
printf "%b\n" "${GREEN} - 前端界面: http://localhost:${FRONTEND_PORT:-80}${NC}"
|
||||
printf "%b\n" "${GREEN} - API接口: http://localhost:${APP_PORT:-8080}${NC}"
|
||||
printf "%b\n" "${GREEN} - Jaeger链路追踪: http://localhost:16686${NC}"
|
||||
echo ""
|
||||
log_info "正在持续输出容器日志(按 Ctrl+C 退出日志,容器不会停止)..."
|
||||
"$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD logs app docreader postgres --since=10s -f
|
||||
|
||||
Reference in New Issue
Block a user