
E2e
- 1 installs
- 2.2k repo stars
- Updated July 27, 2026
- alibaba/loongcollector
e2e is a Claude skill that guides designing, writing, running, and debugging LoongCollector end-to-end tests using the BDD Godog framework and docker-compose.
About
This skill is a guide for LoongCollector end-to-end testing built on the BDD Godog framework. A developer uses it to design a test matrix, write .feature scenarios using registered steps, run tests locally via docker-compose, and debug failures. It documents container inspection commands, cleanup steps, and known traps like ExcutionTimeout turning a config one-time.
- End-to-end testing guide for LoongCollector using BDD Godog
- Covers designing, writing, running, and debugging .feature scenarios
- Documents docker-compose local runs and known config pitfalls
E2e by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,750 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
e2e capabilities & compatibility
- Capabilities
- testing · debugging
- Works with
- docker
- Use cases
- testing · debugging
- Pricing
- Free
What e2e says it does
基于 **BDD Godog** 框架,通过 `.feature` 文件描述场景,引擎正则匹配步骤函数并传参。
**绝对不要**在 `input_forward`、`input_file` 等持续插件的配置中使用 `global.ExcutionTimeout`。
npx skills add https://github.com/alibaba/loongcollector --skill e2eAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 2.2k |
| Last updated | July 27, 2026 |
| Repository | alibaba/loongcollector ↗ |
What it does
Design, write, run, and debug LoongCollector end-to-end tests with BDD Godog and docker-compose.
Who is it for?
Engineers writing or debugging LoongCollector end-to-end tests with Godog .feature files
Skip if: Continuously running input plugins configured with global.ExcutionTimeout, which the skill warns turns the config one-time
When should I use this skill?
When writing a new E2E test, running existing tests, or troubleshooting an E2E failure in LoongCollector
What you get
Working E2E test scenarios that run under docker-compose and are debuggable via container inspection
- E2E .feature test cases
- docker-compose test setup
By the numbers
- 8-dimension scenario design checklist (basic, multi-type, hot reload, backpressure, etc.)
Files
LoongCollector E2E 测试指南
详细步骤模板见 reference.md | 可复用脚本见 scripts/
目录
1. 概览 2. 设计测试用例 3. 编写测试用例 4. 本地运行(docker-compose) 5. 调试 6. 已知陷阱
---
1 概览
基于 BDD Godog 框架,通过 .feature 文件描述场景,引擎正则匹配步骤函数并传参。
test/e2e/
test_cases/<case_name>/
case.feature # 场景描述
docker-compose.yaml # 可选,外部依赖服务
engine/
steps.go # 所有可用步骤(权威来源)
setup/ control/ trigger/ verify/ cleanup/环境 tag:@host、@k8s、@docker-compose(三选一,加 @e2e)
---
2 设计测试用例
编写 feature 文件前,先确定测试矩阵。按以下维度逐项评估是否需要覆盖:
2.1 场景维度清单
| 维度 | 典型场景 | 何时需要 |
|---|---|---|
| 基础功能 | 单配置、单数据类型端到端 | 必须 |
| 多数据类型 | logs / metrics / traces 分别验证 | 插件支持多类型时 |
| 多配置共存 | 同时加载多个 pipeline 配置 | 涉及端口/资源竞争时 |
| 配置热加载 | 运行中增/删/改配置 | 持续运行的 input 插件 |
| 配置类型变更 | 从 A 类型切换到 B 类型 | 插件支持多协议/格式时 |
| 反压与恢复 | 下游不可达 → 恢复后数据不丢 | flusher 插件 |
| 外部依赖失效 | 依赖服务重启/不可达 | 有外部依赖时 |
| 大数据量 | 高吞吐压力下不 OOM/不丢数据 | 性能敏感路径 |
2.2 设计产出
确定要覆盖的场景后,明确每个 Scenario 的:
- 输入:什么数据、什么格式、多少条
- 流经路径:input → processor → flusher 的具体插件
- 预期输出:在哪里验证、验证什么
- 外部依赖:需要什么辅助服务(OTel Collector、Kafka 等)
---
3 编写测试用例
3.1 目录结构
test/e2e/test_cases/my_feature/
├── case.feature
├── docker-compose.yaml # 外部依赖
└── otel-collector-config.yaml # 如果用 OTel Collector3.2 Feature 文件模板
@flusher
Feature: my feature name
Brief description
@e2e @docker-compose
Scenario: TestMyFeatureLogs
Given {docker-compose} environment
Given {my-config} local config as below
"""
enable: true
inputs:
- Type: input_forward
Protocol: OTLP
Endpoint: "0.0.0.0:4320"
flushers:
- Type: flusher_otlp_native
Endpoint: "otel-collector:4317"
"""
When start docker-compose {my_feature}
Then wait {10} seconds
When generate {1} OTLP {logs} via otelgen to endpoint {loongcollectorC:4320}, protocol {grpc}
Then wait {5} seconds
Then otlp collector received at least {1} logs from file {/tmp/otel-export/logs.json}3.3 强制规则
- 配置中必须含
enable: true - 只使用
test/engine/steps.go中已注册的步骤 wait {N} seconds是 Then 类型,不是 When- 命名格式:
Test${功能名}${场景描述} - 不要在持续运行插件的配置中使用
global.ExcutionTimeout(见 §6.1)
3.4 扩展步骤
如需新步骤,参考 reference.md §扩展步骤 中的开发和注册流程。
---
4 本地运行
4.1 前置条件
docker --version && docker compose version如修改了 C++ 代码,需重新编译并更新镜像。两种方式:
方式一:完整构建(慢,但保证一致)
make e2e_image # 从源码构建完整 Docker 镜像 aliyun/loongcollector:0.0.1方式二:增量更新(快,适合迭代调试)
cd build && make -sj$(nproc) && cd ..
# 替换镜像中的二进制
docker create --name tmp-lc aliyun/loongcollector:0.0.1
docker cp build/loongcollector tmp-lc:/usr/local/loongcollector/loongcollector
docker commit tmp-lc aliyun/loongcollector:0.0.1
docker rm tmp-lc4.2 运行
cd test/e2e
# 运行整个测试用例(所有 Scenario)
TEST_CASE=flusher_otlp_native go test -v -run "TestE2EOnDockerCompose$" \
-timeout 600s -count=1 ./...
# 只运行指定 Scenario
TEST_CASE=flusher_otlp_native go test -v \
-run "TestE2EOnDockerCompose/TestFlusherOTLPNativeLogs$" \
-timeout 600s -count=1 ./...4.3 清理(测试失败后必做)
可以直接运行脚本 bash .cursor/skills/e2e/scripts/e2e-cleanup.sh,或手动执行:
docker rm -f $(docker ps -aq) 2>/dev/null
docker network prune -f
rm -rf test/e2e/config test/e2e/onetime_pipeline_config
sudo rm -rf test/e2e/report
rm -f test/e2e/test_cases/<case>/testcase-compose.yaml---
5 调试
# 1. 查看容器日志
docker ps | grep loongcollectorC
docker exec <id> cat /usr/local/loongcollector/log/loongcollector.LOG
# 2. 检查配置是否加载
docker exec <id> ls /usr/local/loongcollector/conf/continuous_pipeline_config/local/
# 3. 检查端口是否监听
docker exec <id> ss -tlnp | grep <port>
# 4. 手动复现 compose 环境
cd test/e2e/test_cases/<case>
docker compose -f testcase-compose.yaml up -d
docker compose -f testcase-compose.yaml logs -f loongcollectorC---
6 已知陷阱
6.1 ExcutionTimeout 使配置变为一次性
绝对不要在 input_forward、input_file 等持续插件的配置中使用 global.ExcutionTimeout。
它会使 IsOnetime() 返回 true,导致 IsValidNativeInputPlugin(name, true) 在 onetime 注册表中查找,而大部分 input 只注册了 continuous,结果报 unsupported input plugin。
详见 .cursor/rules/project-knowledge/config-pitfalls.mdc。
6.2 FlusherFile 必须是文件
e2e 模板将 report/<case>default_flusher.json bind-mount 到容器。若宿主机路径不存在,Docker 会创建为目录。已在 BootController.Start() 中自动处理。
6.3 测试间残留
多 Scenario 共享进程,Clean() 会删除 config/report。异常退出后手动清理(§4.3)。
E2E 测试详细参考
可用步骤速查
权威来源:test/engine/steps.goGiven(环境准备)
| 步骤模板 | 说明 |
|---|---|
{docker-compose} environment | 初始化 docker-compose 环境 |
{host} environment | 初始化主机环境 |
{daemonset} environment | 初始化 K8s 环境 |
{name} local config as below | 写入持续采集配置 |
{name} onetime pipeline local config as below | 写入一次性采集配置 |
subcribe data from {sls} with config | 订阅 SLS 数据源 |
loongcollector depends on containers {name} | 设置容器依赖 |
loongcollector container mount {src} to {dst} | 挂载卷 |
loongcollector expose port {host} to {container} | 暴露端口 |
docker-compose boot type {type} | 设置 boot 类型 |
mkdir {path} | 创建目录 |
When(触发动作)
| 步骤模板 | 说明 |
|---|---|
start docker-compose {case_name} | 启动 docker-compose 环境 |
begin trigger | 标记触发开始时间(生成日志前必须调用) |
generate {N} regex logs to file {path}, with interval {M}ms | 生成正则日志 |
generate {N} json logs to file {path}, with interval {M}ms | 生成 JSON 日志 |
generate {N} apsara logs to file {path}, with interval {M}ms | 生成 Apsara 日志 |
| `generate {N} OTLP {logs\ | metrics\ |
generate {N} http logs, with interval {M}ms, url: {url}, method: {method}, body: | 生成 HTTP 日志 |
execute {N} commands {cmd} in sequence | 顺序执行命令 |
execute {N} commands {cmd} in parallel | 并行执行命令 |
create the shell script file {name} with the following content | 创建 shell 脚本 |
execute {N} the shell script file {name} in parallel | 并行执行 shell 脚本 |
restart agent | 重启 Agent |
force restart agent | 强制重启 Agent |
Then(结果验证)
| 步骤模板 | 说明 |
|---|---|
there is {N} logs | 精确验证日志数(上限 100) |
there is at least {N} logs | 最少日志数验证 |
there is less than {N} logs | 最多日志数验证 |
the log fields match kv | KV 字段匹配(文档内容跟 """...""") |
the log fields match as below | 日志字段模式匹配 |
the log tags match kv | Tag KV 匹配 |
the log is in order | 日志顺序验证 |
wait {N} seconds | 等待 N 秒 |
| `otlp collector received at least {N} (logs\ | metrics\ |
注意:日志数量验证上限 100。超过 100 用When query through+Then the log fields match kv方式。
---
扩展步骤
1. 编写函数
在 test/engine/ 对应子目录下:
func MyVerification(ctx context.Context, expected int) (context.Context, error) {
// 实现逻辑
return ctx, nil
}签名要求:第一个参数 context.Context,返回 (context.Context, error)。
2. 注册
在 test/engine/steps.go 中:
ctx.Then(`^my verification expects \{(\d+)\}$`, verify.MyVerification)3. 使用
Then my verification expects {42}---
docker-compose.yaml 示例
OTel Collector(OTLP 测试用)
services:
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
hostname: otel-collector
user: "0:0"
ports:
- "4317"
volumes:
- ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
- ./otel-export:/tmp/otel-export
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:13133/"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s---
eBPF 进程安全测试示例
@e2e @host @ebpf_input
Scenario: TestEBPFProcessSecurityByNormalStart
Given {host} environment
Given subcribe data from {sls} with config
"""
"""
Given {ebpf_process_security_default} local config as below
"""
enable: true
inputs:
- Type: input_process_security
"""
When begin trigger
When execute {1} commands {/bin/echo 1} in sequence
When query through {* | select * from e2e where call_name = 'execve' and binary = '/bin/echo' and arguments = '1'}
Then there is {1} logs#!/usr/bin/env bash
# E2E 测试环境清理脚本
# 用法: bash .claude/skills/e2e/scripts/e2e-cleanup.sh [case_name]
set -euo pipefail
REPO_ROOT="$(git rev-parse --show-toplevel)"
E2E_DIR="$REPO_ROOT/test/e2e"
CASE_NAME="${1:-}"
echo "==> 停止并删除所有 Docker 容器..."
docker rm -f $(docker ps -aq) 2>/dev/null || true
echo "==> 清理 Docker 网络..."
docker network prune -f 2>/dev/null || true
echo "==> 清理运行时目录..."
rm -rf "$E2E_DIR/config" "$E2E_DIR/onetime_pipeline_config"
sudo rm -rf "$E2E_DIR/report" 2>/dev/null || rm -rf "$E2E_DIR/report" 2>/dev/null || true
if [[ -n "$CASE_NAME" ]]; then
CASE_DIR="$E2E_DIR/test_cases/$CASE_NAME"
if [[ -d "$CASE_DIR" ]]; then
echo "==> 清理测试用例 $CASE_NAME..."
rm -f "$CASE_DIR/testcase-compose.yaml"
rm -f "$CASE_DIR/otel-export/"*.json 2>/dev/null || true
fi
else
echo "==> 清理所有测试用例的 testcase-compose.yaml..."
find "$E2E_DIR/test_cases" -name "testcase-compose.yaml" -delete 2>/dev/null || true
fi
echo "==> 清理完成"
Related skills
FAQ
What framework do the E2E tests use?
BDD Godog, with .feature files whose steps are matched by regex to step functions in engine/steps.go.
Why should I avoid global.ExcutionTimeout in continuous input configs?
It makes IsOnetime() return true, causing the input plugin to be looked up in the onetime registry and reported as an unsupported input plugin.