Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions daemon/ccotel_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package daemon

import (
"context"
"encoding/json"
"log/slog"
"os"
"time"
Expand Down Expand Up @@ -187,6 +188,8 @@ func extractSessionFromResource(resource *resourcev1.Resource) *model.CCOtelSess
session.OSVersion = value.GetStringValue()
case "host.arch":
session.HostArch = value.GetStringValue()
case "wsl.version":
session.WSLVersion = value.GetStringValue()
}
}

Expand Down Expand Up @@ -305,6 +308,18 @@ func (p *CCOtelProcessor) parseLogRecord(lr *logsv1.LogRecord) *model.CCOtelEven
event.Error = value.GetStringValue()
case "prompt_length":
event.PromptLength = int(value.GetIntValue())
case "prompt":
event.Prompt = value.GetStringValue()
case "tool_parameters":
// tool_parameters comes as a JSON string, parse it into map
if jsonStr := value.GetStringValue(); jsonStr != "" {
var params map[string]interface{}
if err := json.Unmarshal([]byte(jsonStr), &params); err == nil {
event.ToolParameters = params
} else {
slog.Debug("CCOtel: Failed to parse tool_parameters", "error", err)
}
}
case "status_code":
event.StatusCode = int(value.GetIntValue())
case "attempt":
Expand Down
20 changes: 0 additions & 20 deletions model/api_ccotel.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,3 @@ func SendCCOtelData(ctx context.Context, req *CCOtelRequest, endpoint Endpoint)

return &resp, nil
}

// SendCCSessionEnd notifies the backend that a session has ended
// POST /api/v1/cc/session/end
func SendCCSessionEnd(ctx context.Context, req *CCSessionEndRequest, endpoint Endpoint) error {
ctx, span := modelTracer.Start(ctx, "ccotel.session.end")
defer span.End()

var resp CCSessionEndResponse
err := SendHTTPRequestJSON(HTTPRequestOptions[*CCSessionEndRequest, CCSessionEndResponse]{
Context: ctx,
Endpoint: endpoint,
Method: http.MethodPost,
Path: "/api/v1/cc/session/end",
Payload: req,
Response: &resp,
Timeout: 30 * time.Second,
})

return err
}
53 changes: 14 additions & 39 deletions model/ccotel_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package model

// CCOtelRequest is the main request to POST /api/v1/cc/otel
type CCOtelRequest struct {
Host string `json:"host"`
Project string `json:"project"`
Session *CCOtelSession `json:"session"`
Events []CCOtelEvent `json:"events,omitempty"`
Metrics []CCOtelMetric `json:"metrics,omitempty"`
Host string `json:"host"`
Project string `json:"project"`
Session *CCOtelSession `json:"session"`
Events []CCOtelEvent `json:"events,omitempty"`
Metrics []CCOtelMetric `json:"metrics,omitempty"`
}

// CCOtelSession represents session data for Claude Code OTEL tracking
Expand All @@ -20,6 +20,7 @@ type CCOtelSession struct {
OSType string `json:"osType"`
OSVersion string `json:"osVersion"`
HostArch string `json:"hostArch"`
WSLVersion string `json:"wslVersion,omitempty"`
StartedAt int64 `json:"startedAt"`
EndedAt int64 `json:"endedAt,omitempty"`
ActiveTimeSeconds int `json:"activeTimeSeconds,omitempty"`
Expand Down Expand Up @@ -55,6 +56,7 @@ type CCOtelEvent struct {
Source string `json:"source,omitempty"`
Error string `json:"error,omitempty"`
PromptLength int `json:"promptLength,omitempty"`
Prompt string `json:"prompt,omitempty"`
ToolParameters map[string]interface{} `json:"toolParameters,omitempty"`
StatusCode int `json:"statusCode,omitempty"`
Attempt int `json:"attempt,omitempty"`
Expand Down Expand Up @@ -84,43 +86,16 @@ type CCOtelResponse struct {
Message string `json:"message,omitempty"`
}

// CCSessionEndRequest is the request to POST /api/v1/cc/session/end
type CCSessionEndRequest struct {
Host string `json:"host"`
SessionID string `json:"sessionId"`
EndedAt int64 `json:"endedAt"`
ActiveTimeSeconds int `json:"activeTimeSeconds,omitempty"`
TotalPrompts int `json:"totalPrompts,omitempty"`
TotalToolCalls int `json:"totalToolCalls,omitempty"`
TotalApiRequests int `json:"totalApiRequests,omitempty"`
TotalCostUSD float64 `json:"totalCostUsd,omitempty"`
LinesAdded int `json:"linesAdded,omitempty"`
LinesRemoved int `json:"linesRemoved,omitempty"`
CommitsCreated int `json:"commitsCreated,omitempty"`
PRsCreated int `json:"prsCreated,omitempty"`
TotalInputTokens int64 `json:"totalInputTokens,omitempty"`
TotalOutputTokens int64 `json:"totalOutputTokens,omitempty"`
TotalCacheReadTokens int64 `json:"totalCacheReadTokens,omitempty"`
TotalCacheCreationTokens int64 `json:"totalCacheCreationTokens,omitempty"`
}

// CCSessionEndResponse is the response from POST /api/v1/cc/session/end
type CCSessionEndResponse struct {
Code int `json:"code"`
Data interface{} `json:"data"`
Message string `json:"message"`
}

// Claude Code OTEL metric types
const (
CCMetricSessionCount = "session_count"
CCMetricLinesOfCodeCount = "lines_of_code_count"
CCMetricPullRequestCount = "pull_request_count"
CCMetricCommitCount = "commit_count"
CCMetricCostUsage = "cost_usage"
CCMetricTokenUsage = "token_usage"
CCMetricSessionCount = "session_count"
CCMetricLinesOfCodeCount = "lines_of_code_count"
CCMetricPullRequestCount = "pull_request_count"
CCMetricCommitCount = "commit_count"
CCMetricCostUsage = "cost_usage"
CCMetricTokenUsage = "token_usage"
CCMetricCodeEditToolDecision = "code_edit_tool_decision"
CCMetricActiveTimeTotal = "active_time_total"
CCMetricActiveTimeTotal = "active_time_total"
)

// Claude Code OTEL event types
Expand Down
Loading