Go SDK

Go SDK

适用版本:cnb.cool/mliev/entmesh/sdk-go@v0.6.0。Go SDK 用于可信服务端事件,Track 只写入内存队列,不等待网络;队列按批次 gzip 发送到 Collector。

安装

go get cnb.cool/mliev/entmesh/sdk-go@v0.6.0

生产项目应提交 go.modgo.sum,不要跟随未固定的分支。

初始化并发送事件

package main

import (
    "context"
    "log"
    "time"

    entmesh "cnb.cool/mliev/entmesh/sdk-go"
)

func main() {
    client, err := entmesh.New(entmesh.Config{
        Endpoint:  "https://collector.entmesh.mliev.com",
        ServerKey: "sk_替换为当前环境的ServerKey",
    })
    if err != nil {
        log.Fatal(err)
    }

    if err := client.Track(entmesh.Event{
        EventName: "invoice_paid",
        UserID:    "user-42",
        Properties: map[string]any{
            "invoice_id": "invoice-1001",
            "amount":     299,
        },
    }); err != nil {
        log.Printf("track invoice_paid: %v", err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    if err := client.Close(ctx); err != nil {
        log.Printf("close entmesh: %v", err)
    }
}

同一个 Client 可以被多个 goroutine 安全调用。应用进程退出前必须在有截止时间的 Context 中调用 Close;需要在进程继续运行时等待既有事件送达,可调用 Flush(ctx)

队列与错误

默认队列容量 10,000、批量 100、每秒刷新,失败最多重试 5 次。可通过 ConfigQueueSizeBatchSizeFlushIntervalHTTPClient 和重试参数调整。

if err := client.Track(event); err != nil {
    switch {
    case errors.Is(err, entmesh.ErrQueueFull):
        // 记录指标或按业务策略丢弃;不要阻塞主请求。
    case errors.Is(err, entmesh.ErrClosed):
        // Client 已关闭,检查应用生命周期。
    default:
        // 参数错误。
    }
}

Track 至少需要 UserIDAnonymousIDIdentityContext 之一。业务事件名不能以 $ 开头。

透传浏览器身份

type CreateOrderRequest struct {
    IdentityContext string `json:"identity_context"`
}

err := client.Track(entmesh.Event{
    EventName:       "order_created",
    UserID:          authenticatedUser.ID,
    IdentityContext: request.IdentityContext,
    Properties:      map[string]any{"order_id": order.ID},
})

业务入口应把字段长度限制为 4 KiB。IdentityContext 是可伪造的统计关联证据,不得用于鉴权,不得覆盖从可信登录态得到的 UserID,也不要写入日志。

客户 IP

err := client.Track(entmesh.Event{
    EventName: "order_created",
    UserID:    authenticatedUser.ID,
    ClientIP:  trustedClientIP,
})

只传业务 Web 框架按可信代理规则解析出的 IPv4/IPv6。不要直接使用未经清洗的 X-Forwarded-ForX-Real-IP 或代理连接地址。地址不能包含端口或 IPv6 zone;后台任务没有真实客户 IP 时留空。

Feature Flag

decisions, err := client.DecideAndExpose(
    ctx,
    entmesh.ExperimentSubject{UserID: "user-42"},
    []entmesh.FlagRequest{{
        Key:      "checkout_copy",
        Fallback: json.RawMessage(`"继续"`),
    }},
)
if err != nil {
    log.Printf("flag fallback used: %v", err)
}

event := entmesh.WithExperimentContext(entmesh.Event{
    EventName: "checkout_completed",
    UserID:    "user-42",
}, decisions)
_ = client.Track(event)

只有曝光状态为 recordedduplicate 的实验决策才会被 WithExperimentContext 附加到后续事件。共享 Client 不会跨用户保存 assignment。