跳到主要内容

Langfuse · 模型、采集与存储

约 13 分钟3,412 字更新于 2026/10/22

本页覆盖:Trace 模型、采集入口、鉴权限流、存储与保留。每条事实链到固定提交(f75c661d)。回到 Langfuse 总览。

1. Trace / Observation 模型、类型、层级、Token 与成本​

1.1 Trace 与 Observation 的领域对象​

  • TraceDomain 是前后端共用的 Zod 对象(packages/shared/src/domain/traces.ts L12-L30,permalink)。
  • Trace 字段包括 id、name、timestamp、environment、tags、bookmarked、public、release、version、input、output、metadata、sessionId、userId、projectId(同上范围)。
  • ObservationType 有 SPAN、EVENT、GENERATION、AGENT、TOOL、CHAIN、RETRIEVER、EVALUATOR、EMBEDDING、GUARDRAIL 共 10 种(packages/shared/src/domain/observations.ts L5-L17,permalink)。
  • ObservationSchema 用可空 traceId 指向 Trace,用可空 parentObservationId 指向父 Observation(packages/shared/src/domain/observations.ts L55-L65,permalink)。
  • Observation 还带 level、statusMessage、模型、用量、成本、promptId、promptName、promptVersion、工具定义与工具调用(packages/shared/src/domain/observations.ts L66-L100,permalink)。
  • EventsObservationSchema 在 Observation 上附加 userId、sessionId、traceName、release、tags、bookmarked、public、isRootObservation(packages/shared/src/domain/observations.ts L116-L125,permalink)。
  • 根 Observation 的判定是没有 parentObservationId,或 isAppRoot === true(packages/shared/src/eventsTable.ts L44-L50,permalink)。
  • 在 SQL 里,根行条件是 parent_span_id = '' OR is_app_root = true(packages/shared/src/eventsTable.ts L4-L7,permalink)。

1.2 层级​

  • ClickHouse events_full 用 trace_id、span_id、parent_span_id 表示同一条 Trace 里的 span 树(packages/shared/clickhouse/migrations/canonical/0039_create_events_full.up.sql L4-L6,permalink)。
  • 同一行带 trace_name、is_app_root、session_id、user_id、tags(packages/shared/clickhouse/migrations/canonical/0039_create_events_full.up.sql L16-L24,permalink)。
  • 从 events 聚合 Trace 时,id 取 trace_id,timestamp 取 min(start_time)(packages/shared/src/server/queries/clickhouse-sql/event-query-builder.ts L528-L535,permalink)。
  • Trace 的 input、output、metadata、bookmarked 取 parent_span_id = '' 的最新 event_ts 行(packages/shared/src/server/queries/clickhouse-sql/event-query-builder.ts L541-L558,permalink)。
  • Trace 级聚合 level 按 ERROR、WARNING、DEFAULT、DEBUG 的优先级取最高(packages/shared/src/server/queries/clickhouse-sql/event-query-builder.ts L566-L567,permalink)。
  • eventsTracesAggregation 的注释写明:按 trace_id 把 events 重新聚成 Trace,并称这是迁到只用 events 表之前的临时做法(packages/shared/src/server/queries/clickhouse-sql/query-fragments.ts L103-L128,permalink)。
  • 旧 traces 表独立存在,初始建表使用 ReplacingMergeTree(event_ts, is_deleted),按 toYYYYMM(timestamp) 分区(packages/shared/clickhouse/migrations/canonical/0001_traces.up.sql L1-L23,permalink)。

1.3 采集事件类型​

  • 采集事件类型包含 trace-create、span-create/update、generation-create/update、event-create、score-create、sdk-log、dataset-run-item-create,以及 agent、tool、chain、retriever、evaluator、embedding、guardrail 的 create(packages/shared/src/server/ingestion/types.ts L319-L339,permalink)。
  • observation-create 与 observation-update 被标成仅为兼容保留的旧类型(packages/shared/src/server/ingestion/types.ts L336-L338,permalink)。
  • Generation 在 Span 字段上增加 model、usage、costDetails、promptName、promptVersion(packages/shared/src/server/ingestion/types.ts L513-L540,permalink)。
  • promptName 与 promptVersion 必须同时出现或同时为空(packages/shared/src/server/ingestion/types.ts L535-L539,permalink)。

1.4 模型匹配、Token 计数、成本​

  • 模型定义存在 Postgres Model 表,含 matchPattern、单价、tokenizerId、tokenizerConfig,可按项目覆盖(packages/shared/prisma/schema.prisma L912-L932,permalink)。
  • 价格拆成 Price(按 usageType)和 PricingTier(含 priority、isDefault、conditions)(packages/shared/prisma/schema.prisma L955-L969,permalink)。
  • findModel 先查本地缓存,再查 Redis 缓存,最后查库(packages/shared/src/server/ingestion/modelMatch.ts L44,permalink)。
  • Worker 对有 provided_model_name 的观测调用 findModel,否则不匹配模型(worker/src/services/IngestionService/index.ts L1363,permalink)。
  • 价格档按条件匹配:条件可对 usageDetails 的键做正则求和比较,也可比较 modelParameters 或 metadata 的值(packages/shared/src/server/pricing-tiers/matcher.ts L18-L30,permalink)。
  • Worker 调 matchPricingTier 选出价格档,再算成本(worker/src/services/IngestionService/index.ts L1411,permalink)。
  • 只有在「用户没给 usage、没给 cost、模型已匹配、level 不是 ERROR、不是 AI Gateway 生成」时才做本地 tokenize(worker/src/services/IngestionService/index.ts L1491-L1497,permalink)。
  • 用户给了任一成本点后,不再计算其他成本点,直接用用户提供的值(worker/src/services/IngestionService/index.ts L1713-L1716,permalink)。
  • 未提供成本时,按 usageUnits 的键逐项匹配价格并相乘(worker/src/services/IngestionService/index.ts L1740-L1743,permalink)。
  • 本地 tokenizer 有 openai(tiktoken)和 claude 两种(worker/src/features/tokenisation/usage.ts L51-L57,permalink)。
  • events 路径的成本与用量按 span 做 sum / sumMap 聚合成 Trace 总量(packages/shared/src/server/queries/clickhouse-sql/event-query-builder.ts L549-L565,permalink)。
  • 价格档与模型管理有独立 tRPC 路由 models(web/src/server/api/root.ts L99,permalink)和页面 /project/[projectId]/models(web/src/pages/project/[projectId]/models.tsx L1,permalink)。
  • 公共 API 有 /api/public/models 目录下的路由(web/src/pages/api/public/models/index.ts L1,permalink)。

2. 采集:legacy ingestion、公共 API、OTLP、SDK、队列、批处理、限流、鉴权​

2.1 入口​

  • 入口 POST /api/public/ingestion 接收 { batch, metadata },先做权限、限流和格式校验,再异步处理(web/src/pages/api/public/ingestion.ts L56-L70,permalink)。
  • 请求体上限是 4.5mb(web/src/pages/api/public/ingestion.ts L48-L54,permalink)。
  • 用量超阈值时 ingestion 被拒绝(web/src/pages/api/public/ingestion.ts L127,permalink)。
  • 在 events_only 下,该端点只接受 score-create(web/src/pages/api/public/ingestion.ts L295-L297,permalink)。
  • 被拒绝的非 score 事件返回 400,并提示改用 v4 SDK 或 OTLP,或临时把写入模式设成 dual(web/src/pages/api/public/ingestion.ts L311-L345,permalink)。
  • Legacy REST 还有 POST /api/public/traces、spans、events、generations;它们把 body 包成 ingestion 事件再走同一管线(web/src/pages/api/public/traces/index.ts L39-L64,permalink、web/src/pages/api/public/spans.ts L18-L38,permalink、web/src/pages/api/public/events.ts L16-L33,permalink、web/src/pages/api/public/generations.ts L19-L35,permalink)。
  • 这些 legacy 写接口在 events_only 下被拒绝(web/src/pages/api/public/traces/index.ts L45-L47,permalink)。
  • OTLP 入口是 POST /api/public/otel/v1/traces,权限 traces:create,限流资源 ingestion(web/src/pages/api/public/otel/v1/traces/index.ts L26-L33,permalink)。
  • OTLP 路由关闭 bodyParser,自行读 body,并支持 gzip(web/src/pages/api/public/otel/v1/traces/index.ts L20-L24,permalink)。
  • OTLP 路由读取 x-langfuse-ingestion-version 头,并和 SDK 名称、版本一起交给 processOtelIngestion(web/src/pages/api/public/otel/v1/traces/index.ts L96,permalink)。
  • OTLP metrics 端点 POST /api/public/otel/v1/metrics 的处理函数是空函数 fn: async () => {}(web/src/pages/api/public/otel/v1/metrics/index.ts L18,permalink)。
  • SDK 自身代码不在本仓库;仓库只读取 SDK 头(x-langfuse-sdk-name、x-langfuse-sdk-version、x-langfuse-ingestion-version)来决定写入路径(worker/src/queues/otelIngestionQueue.ts L60-L100,permalink)。
  • 另有媒体上传入口 POST /api/public/media,限流资源 media-upload(web/src/pages/api/public/media/index.ts L19,permalink)。

2.2 鉴权与限流​

  • 公共 API 支持 Basic 认证(公钥加私钥,完整 scope)和 Bearer 认证(只有公钥,受限 scope)(web/src/features/public-api/server/apiAuth.ts L92,permalink、web/src/features/public-api/server/apiAuth.ts L215,permalink)。
  • API Key 有 PROJECT 与 ORGANIZATION 两种 scope(web/src/features/public-api/server/apiAuth.ts L183,permalink)。
  • 限流用 rate-limiter-flexible 的 RateLimiterRedis,按「组织、套餐、资源」分桶(web/src/features/public-api/server/RateLimitService.ts L47-L50,permalink)。
  • 自托管和没有 Redis 时不限流(web/src/features/public-api/server/RateLimitService.ts L48,permalink)。
  • 限流资源有 ingestion、media-upload、public-api、public-api-metrics、public-api-v2-metrics、prompts、datasets、annotation-queues、trace-delete、score-delete 等(packages/shared/src/interfaces/rate-limits.ts L4,permalink)。
  • 限流出错时 ingestion 选择放行(fail open)(web/src/pages/api/public/ingestion.ts L158,permalink)。
  • score 事件要求 scores:create,其余事件要求 traces:create(web/src/pages/api/public/ingestion.ts L384-L390,permalink)。

2.3 队列与 Worker​

  • processEventBatch 先按 ingestion schema 校验,再把 sdk-log 记日志后丢出后续处理(packages/shared/src/server/ingestion/processEventBatch.ts L168-L200,permalink)。
  • 校验通过的事件按实体 id 分组上传到 S3,S3 失败则中止,不再入队(packages/shared/src/server/ingestion/processEventBatch.ts L276-L332,permalink)。
  • S3 成功后,每组事件按 projectId-eventBodyId 分片写入 IngestionQueue(packages/shared/src/server/ingestion/processEventBatch.ts L328-L346,permalink)。
  • 队列名包括 ingestion-queue、otel-ingestion-queue、trace-upsert、batch-export-queue、event-propagation-queue、monitor-queue、webhook-queue、data-retention-queue 等(packages/shared/src/server/queues.ts L406-L446,permalink)。
  • 入队延迟默认 15 秒,分片数默认 1(packages/shared/src/env.ts L217-L223,permalink)。
  • Worker 消费 IngestionQueue:先查 Redis 去重键,再读 S3 事件文件(worker/src/queues/ingestionQueue.ts L85,permalink)。
  • IngestionService.mergeAndWrite 按事件类型分流到 trace、observation、score 三条处理函数(worker/src/services/IngestionService/index.ts L238-L268,permalink)。
  • 处理结果写入 ClickhouseWriter 的内存队列,批量写 ClickHouse(worker/src/services/ClickhouseWriter/index.ts L61-L63,permalink)。
  • 批大小默认 1000,写间隔默认 1000 ms,最大重试次数默认 3(worker/src/env.ts L181-L192,permalink)。
  • OTLP 数据先上传 S3,再进 OtelIngestionQueue,分片键是 projectId-fileKey(packages/shared/src/server/otel/OtelIngestionProcessor.ts L330-L342,permalink)。
  • Worker 的 OTLP 处理器 processOtelEvents 对每个 span 调 createEventRecord,再 writeEventRecord(worker/src/features/otel-ingestion/processOtelEvents.ts L110,permalink、worker/src/features/otel-ingestion/processOtelEvents.ts L154,permalink)。
  • writeEventRecord 直接把记录加入 events_full 的写队列,events_core 由物化视图填充(worker/src/services/IngestionService/index.ts L509-L512,permalink)。
  • 是否直写 events 表由下面四条规则按序决定:请求头、环境变量、SDK 版本 scope、组织创建日期截止线(worker/src/queues/otelIngestionQueue.ts L310-L322,permalink)。
  • SDK scope 规则:Python SDK ≥ 4.0.0,或 JS SDK ≥ 5.0.0(worker/src/queues/otelIngestionQueue.ts L65-L66,permalink)。
  • 一条 OTLP span 可能同时生成 trace-create 事件,body 含 public、tags、environment、input、output(packages/shared/src/server/otel/OtelIngestionProcessor.ts L1140-L1161,permalink)。
  • is_app_root 来自 OTel 属性,值为 true 或 "true" 时为真(packages/shared/src/server/otel/OtelIngestionProcessor.ts L1175-L1178,permalink)。
  • 旧路径里,观测处理会在缺 Trace 时生成包装 Trace 记录(worker/src/services/IngestionService/index.ts L1121,permalink)。

2.4 事件批处理与暂存表​

  • observations_batch_staging 表有 TTL toDateTime(s3_first_seen_timestamp) + INTERVAL 48 HOUR(packages/shared/clickhouse/migrations/canonical/0038_create_observations_batch_staging.up.sql L50,permalink)。
  • Worker 有独立的 EventPropagationQueue(worker/src/app.ts L715,permalink)。
  • 传播任务把 observations_batch_staging 与 traces 连接后插入 events_full(worker/src/features/eventPropagation/handleEventPropagationJob.ts L159,permalink)。

2.5 其他采集路径​

  • 采集管线按 trace-create 事件在 Worker 里写 Trace,同时对带 session_id 的 Trace 往 Postgres trace_sessions 插入稀疏行(worker/src/services/IngestionService/index.ts L882-L894,permalink)。
  • 采集侧环境名会被规范化,空值或非法字符落到默认环境(packages/shared/src/server/ingestion/types.ts L304-L317,permalink)。

3. 存储:ClickHouse、Postgres、对象存储、保留策略​

3.1 ClickHouse 表​

  • 旧 traces 表按 project_id、toDate(timestamp)、id 排序(packages/shared/clickhouse/migrations/canonical/0001_traces.up.sql L28-L32,permalink)。
  • 旧 traces 表的 input 与 output 使用 ZSTD(3)(packages/shared/clickhouse/migrations/canonical/0001_traces.up.sql L13-L14,permalink)。
  • 旧 observations 表以 trace_id 关联 Trace,并有 parent_observation_id、type、start_time、end_time(packages/shared/clickhouse/migrations/canonical/0002_observations.up.sql L3-L10,permalink)。
  • 旧 scores 表同样是 ReplacingMergeTree(event_ts, is_deleted),按 toYYYYMM(timestamp) 分区(packages/shared/clickhouse/migrations/canonical/0003_scores.up.sql L22-L23,permalink)。
  • scores 后续增加了 session_id(packages/shared/clickhouse/migrations/canonical/0012_add_session_id_column_scores.up.sql L1,permalink)、dataset_run_id(packages/shared/clickhouse/migrations/canonical/0017_add_run_id_column_scores.up.sql L1,permalink),并把 trace_id 改成可空(packages/shared/clickhouse/migrations/canonical/0014_scores_modify_nullable_trace_id_column.up.sql L1,permalink)。
  • events_full 使用 ReplacingMergeTree(event_ts, is_deleted),按 toYYYYMM(start_time) 分区,主键是 project_id、分钟级 start_time、xxHash32(trace_id)(packages/shared/clickhouse/migrations/canonical/0039_create_events_full.up.sql L112-L115,permalink)。
  • events_full 带全文索引,覆盖 input、output 的小写形式以及 metadata_values、metadata_names(packages/shared/clickhouse/migrations/canonical/0039_create_events_full.up.sql L108-L110,permalink)。
  • events_core 引擎与排序键同 events_full(packages/shared/clickhouse/migrations/canonical/0040_create_events_core.up.sql L113-L116,permalink)。
  • 物化视图 events_core_mv 从 events_full 写入 events_core,并把 input、output、metadata value 截到 200 个字符(packages/shared/clickhouse/migrations/canonical/0041_create_events_core_mv.up.sql L39-L42,permalink)。
  • 读取时 truncated 为 true 读 events_core,否则读 events_full(packages/shared/src/server/queries/clickhouse-sql/query-fragments.ts L97,permalink)。
  • observations_batch_staging 是 48 小时 TTL 的暂存表(packages/shared/clickhouse/migrations/canonical/0038_create_observations_batch_staging.up.sql L50,permalink)。
  • dataset_run_items_rmt 存数据集运行项,排序键 project_id, dataset_id, dataset_run_id, id(packages/shared/clickhouse/migrations/canonical/0024_dataset_run_items.up.sql L1,permalink、packages/shared/clickhouse/migrations/canonical/0024_dataset_run_items.up.sql L36,permalink)。
  • blob_storage_file_log 记录 S3 事件文件,取代了旧的 event_log 表(packages/shared/clickhouse/migrations/canonical/0011_add_blob_storage_file_log.up.sql L1,permalink、packages/shared/clickhouse/migrations/canonical/0044_drop_event_log.up.sql L1,permalink)。
  • 迁移 0028、0029 删除了 traces_null 以及按 7 天、30 天、全量划分的聚合表(packages/shared/clickhouse/migrations/canonical/0029_drop_traces_null_and_amt_tables.up.sql L1,permalink)。
  • events_full 加了 name、trace_name 等列的 ngram 索引(packages/shared/clickhouse/migrations/canonical/0049_add_events_name_ngram_indexes.up.sql L3,permalink)。
  • 迁移 0049 的注释写明 events_full 按月分区且没有表级 TTL(packages/shared/clickhouse/migrations/canonical/0049_add_events_name_ngram_indexes.up.sql L1,permalink)。
  • 迁移文件分 canonical 模板,按集群与非集群两种方式渲染(模板里有 {CLICKHOUSE_CLUSTER_CLAUSE} 占位,见 packages/shared/clickhouse/migrations/canonical/0039_create_events_full.up.sql L1,permalink)。
  • OTLP 直写路径下,Worker 通过 writeEventRecord 把 span 写进 events_full(worker/src/services/IngestionService/index.ts L509-L512,permalink);score 仍写 scores 表(worker/src/services/IngestionService/index.ts L799,permalink)。
  • 登录时 session 的 v4BetaEnabled 在 events_only 下恒为 true;在 dual 下还要求「Cloud 或开启 LANGFUSE_MIGRATION_V4_ALLOW_PREVIEW_OPT_IN」且用户库里的 flag 为 true(web/src/server/auth.ts L844-L847,permalink)。

3.2 Postgres 表​

  • Postgres 里没有 Trace 与 Observation 表;只有 TraceSession(packages/shared/prisma/schema.prisma L501-L513,permalink)。
  • Project 带 retentionDays 与 hasTraces(packages/shared/prisma/schema.prisma L139,permalink)。
  • 观测相关的 Postgres 模型有:Model/Price/PricingTier、Dashboard/DashboardWidget、TableViewPreset/DefaultView、Monitor、Action/Trigger/Automation、AnnotationQueue*、ScoreConfig、Evaluator/JobConfiguration/EvaluationRule/JobExecution、BatchExport/BatchAction、Media、BlobStorageIntegration、AuditLog、PendingDeletion、Comment(各 model 声明见 packages/shared/prisma/schema.prisma L1630,permalink、packages/shared/prisma/schema.prisma L1892,permalink、packages/shared/prisma/schema.prisma L1488,permalink、packages/shared/prisma/schema.prisma L1964,permalink)。
  • Comment.objectType 可以是 TRACE、OBSERVATION、SESSION、PROMPT(packages/shared/prisma/schema.prisma L751-L756,permalink)。
  • AuditLog 无外键约束,保证审计记录保留(packages/shared/prisma/schema.prisma L980,permalink)。

3.3 对象存储​

  • 采集的原始事件先写 S3 再入队(packages/shared/src/server/ingestion/processEventBatch.ts L276-L332,permalink;桶由 LANGFUSE_S3_EVENT_UPLOAD_BUCKET 配置,见 packages/shared/src/env.ts L312,permalink)。
  • OTLP 的 resourceSpans 以 JSON 文件写入 S3 的 otel/<projectId>/... 路径(packages/shared/src/server/otel/OtelIngestionProcessor.ts L331,permalink)。
  • 媒体桶由 LANGFUSE_S3_MEDIA_UPLOAD_BUCKET 配置(packages/shared/src/env.ts L325,permalink)。
  • Postgres Media 表按 sha256Hash 去重,记录 bucketPath、contentType、contentLength、上传状态(packages/shared/prisma/schema.prisma L1488-L1507,permalink)。
  • TraceMedia 把媒体关联到 projectId、traceId、field;ObservationMedia 再关联 observationId(packages/shared/prisma/schema.prisma L1516-L1528,permalink、packages/shared/prisma/schema.prisma L1531-L1543,permalink)。
  • 媒体关联来源有 CLIENT_UPLOAD、INGESTION_MEDIA_EXTRACTION、INGESTION_FIELD_OVERFLOW 等(packages/shared/prisma/schema.prisma L1509-L1514,permalink)。
  • OTLP 处理器里有 processOtelMedia,把 span 里的媒体抽取后上传(worker/src/features/otel-ingestion/processOtelEvents.ts L19,permalink)。
  • 客户可配置 BlobStorageIntegration,把数据按频率导出到自己的 S3/Azure/GCS 桶(packages/shared/prisma/schema.prisma L1335-L1365,permalink)。
  • 导出文件格式、导出模式、数据源是可选项:fileType、exportMode、exportSource、compressed(packages/shared/prisma/schema.prisma L1353,permalink)。
  • Worker 目录 worker/src/features/blobstorage 实现导出,并有 BlobStorageIntegrationQueue 与处理队列(worker/src/app.ts L630,permalink)。
  • 批量导出(用户在表格里点导出)的文件落在 S3 批量导出桶,由 BatchExport 队列处理(worker/src/app.ts L352,permalink)。

3.4 保留策略与删除​

  • 项目级保留天数是 Project.retentionDays(packages/shared/prisma/schema.prisma L139,permalink)。
  • 保留任务由 DataRetentionQueue 调度、DataRetentionProcessingQueue 执行(packages/shared/src/server/queues.ts L433,permalink)。
  • 处理任务先读项目当前 retentionDays,已关闭则不删(worker/src/ee/dataRetention/handleDataRetentionProcessingJob.ts L31,permalink)。
  • 处理任务按截止日期删除 traces、observations、scores,并删媒体(worker/src/ee/dataRetention/handleDataRetentionProcessingJob.ts L154,permalink)。
  • 另有批量保留清理器,覆盖 traces、observations、scores、events_full、events_core 五张表(worker/src/features/batch-data-retention-cleaner/index.ts L23-L30,permalink)。
  • deleteEventsOlderThanDays 提供按天数删除 events 的仓储函数(packages/shared/src/server/repositories/events.ts L2568,permalink)。
  • 另有媒体保留清理器(worker/src/features/media-retention-cleaner/index.ts L26,permalink)。
  • Trace 删除先写 Postgres PendingDeletion,延迟 LANGFUSE_TRACE_DELETE_DELAY_MS 后再删 ClickHouse(packages/shared/src/server/traceDeletionProcessor.ts L55,permalink、packages/shared/src/server/traceDeletionProcessor.ts L31,permalink)。
  • 数据保留属于企业能力,处理代码放在 worker/src/ee/dataRetention(worker/src/ee/dataRetention/handleDataRetentionSchedule.ts L1,permalink);项目设置接口要求 data-retention 权益(web/src/features/projects/server/projectsRouter.ts L158,permalink)。