Skip to content

Commit 81355e7

Browse files
authored
fix: inject version via ldflags and set model on tool spans (#54)
1 parent db40aba commit 81355e7

6 files changed

Lines changed: 63 additions & 2 deletions

File tree

.goreleaser.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ builds:
77
- id: on-event
88
env:
99
- CGO_ENABLED=0
10+
ldflags:
11+
- -s -w -X github.com/dash0hq/dash0-agent-plugin/internal/version.Version={{.Version}}
1012
goos:
1113
- linux
1214
- darwin

cmd/on-event/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ func sendToolTrace(event map[string]any, cfg otlp.Config, ts time.Time, dataDir
3838
event["model"] = ctx.Model
3939
}
4040

41+
// Fall back to reading model from transcript if still missing.
42+
if _, hasModel := event["model"]; !hasModel {
43+
if tp, _ := event["transcript_path"].(string); tp != "" {
44+
if m := transcript.ReadModel(tp); m != "" {
45+
event["model"] = m
46+
}
47+
}
48+
}
49+
4150
// Compute start time from duration_ms (always present on PostToolUse).
4251
startTime := ts
4352
if durationMs, ok := event["duration_ms"].(float64); ok && durationMs > 0 {

cmd/on-event/main_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,3 +692,47 @@ func TestConversationIDOnAllSpans(t *testing.T) {
692692
assert.True(t, found, "span %q should have gen_ai.conversation.id", span.Name)
693693
}
694694
}
695+
696+
func TestModelOnToolSpanFromTranscriptWhenSessionStartOmitsModel(t *testing.T) {
697+
dataDir := t.TempDir()
698+
t.Setenv("CLAUDE_PLUGIN_DATA", dataDir)
699+
srv, spans, _ := collectingServer(t)
700+
t.Setenv("DASH0_OTLP_URL", srv.URL)
701+
702+
// Create transcript with model info.
703+
transcriptPath := filepath.Join(dataDir, "transcript.jsonl")
704+
writeTranscript(t, transcriptPath, []string{
705+
`{"type":"user","message":{"role":"user","content":[{"type":"text","text":"hello"}]}}`,
706+
`{"type":"assistant","requestId":"req_001","message":{"role":"assistant","model":"claude-opus-4-7","content":[{"type":"text","text":"hi"}],"usage":{"input_tokens":10,"output_tokens":5}}}`,
707+
})
708+
709+
// SessionStart WITHOUT model — simulates the real-world bug.
710+
feed(t, `{"hook_event_name":"SessionStart","session_id":"sess-no-model"}`)
711+
feed(t, `{"hook_event_name":"UserPromptSubmit","session_id":"sess-no-model","prompt":"hello"}`)
712+
feed(t, fmt.Sprintf(`{"hook_event_name":"PostToolUse","session_id":"sess-no-model","tool_name":"Bash","tool_use_id":"tu1","tool_response":"ok","transcript_path":"%s"}`, transcriptPath))
713+
feed(t, fmt.Sprintf(`{"hook_event_name":"Stop","session_id":"sess-no-model","transcript_path":"%s"}`, transcriptPath))
714+
715+
require.Len(t, *spans, 2, "expected tool span + chat span")
716+
717+
// Tool span should have model from transcript fallback.
718+
toolSpan := findSpan(*spans, "execute_tool")
719+
require.NotNil(t, toolSpan, "tool span should exist")
720+
assertStringAttr(t, toolSpan.Attributes, "gen_ai.request.model", "claude-opus-4-7")
721+
722+
// Chat span should also have model from transcript.
723+
chatSpan := findSpan(*spans, "chat")
724+
require.NotNil(t, chatSpan, "chat span should exist")
725+
assertStringAttr(t, chatSpan.Attributes, "gen_ai.request.model", "claude-opus-4-7")
726+
}
727+
728+
func assertStringAttr(t *testing.T, attrs []otlp.Attribute, key, want string) {
729+
t.Helper()
730+
for _, a := range attrs {
731+
if a.Key == key {
732+
require.NotNil(t, a.Value.StringValue, "attribute %q should have string value", key)
733+
assert.Equal(t, want, *a.Value.StringValue)
734+
return
735+
}
736+
}
737+
t.Errorf("attribute %q not found", key)
738+
}

internal/otlp/trace.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"fmt"
99
"strconv"
1010
"time"
11+
12+
"github.com/dash0hq/dash0-agent-plugin/internal/version"
1113
)
1214

1315
// OTLP JSON wire format types for traces.
@@ -132,7 +134,7 @@ func SendTrace(span Span, event map[string]any, cfg Config) error {
132134
ScopeSpans: []ScopeSpans{{
133135
Scope: Scope{
134136
Name: "dash0-agent-plugin",
135-
Version: "0.1.0",
137+
Version: version.Version,
136138
},
137139
Spans: []Span{span},
138140
}},

internal/otlp/trace_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func TestSendTrace(t *testing.T) {
228228
require.Len(t, rs.ScopeSpans, 1)
229229
ss := rs.ScopeSpans[0]
230230
assert.Equal(t, "dash0-agent-plugin", ss.Scope.Name)
231-
assert.Equal(t, "0.1.0", ss.Scope.Version)
231+
assert.Equal(t, "dev", ss.Scope.Version)
232232

233233
require.Len(t, ss.Spans, 1)
234234
s := ss.Spans[0]

internal/version/version.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package version
2+
3+
// Version is set at build time by GoReleaser via ldflags.
4+
var Version = "dev"

0 commit comments

Comments
 (0)