Le SDK Go (sdk/go/ledgersdk) couvre l'API manuelle Record. Les applications Go instrumentées avec OTel devraient plutôt faire pointer leur exportateur existant vers le récepteur OTLP du registre (/v1/otlp/v1/traces) — il n'existe pas de processeur de spans propre à Go.
go get github.com/bf95/AI_Comp_Ledger/sdk/go/ledgersdk
package main
import (
"time"
"github.com/bf95/AI_Comp_Ledger/sdk/go/ledgersdk"
)
func main() {
l := ledgersdk.New("http://127.0.0.1:4010", ingestKey, "urn:agent:research-assistant")
l.SetTrigger(ledgersdk.Trigger{Type: "human", Subject: "person@example.com"})
provider, model := "anthropic", "claude-fable-5"
tokensIn, tokensOut := 420, 180
response := "The policy provides that…"
span := l.Record(ledgersdk.RecordInput{
ActionType: "llm_call",
Provider: &provider,
Model: &model,
StartedAt: time.Now().Add(-time.Second),
EndedAt: time.Now(),
Status: "success",
Usage: &ledgersdk.Usage{TokensIn: &tokensIn, TokensOut: &tokensOut},
Payloads: []ledgersdk.Payload{{Kind: "response", Content: &response}},
})
l.Flush()
_ = span // l'identifiant de span — à passer comme ParentRef d'un autre événement pour la lignée décisionnelle
}
Record ne provoque jamais de panique dans l'application hôte — les échecs sont dirigés vers Ledger.OnError à la place. La plupart des champs sont des pointeurs car une valeur nil signifie « non renseigné », ce qui est distinct d'une valeur zéro (par exemple, Usage.TokensIn == nil signifie inconnu, pas zéro jeton).
Définissez ParentRef (et HasParentRef: true) sur un RecordInput pour citer le span à l'origine de cet événement :
parent := searchSpan
l.Record(ledgersdk.RecordInput{
ActionType: "llm_call",
ParentRef: &parent,
HasParentRef: true,
// ...
})
Flush() livre les événements en tampon et peut être appelé sans risque sur une minuterie ou avant la fin du processus. La livraison se fait au moins une fois (at-least-once) — le serveur déduplique par identifiant de span, donc un lot renvoyé après un flush échoué n'entraîne jamais de double enregistrement.