// internal/tools/metrics.go
package tools
import (
"context"
"encoding/json"
"fmt"
"log"
"strings"
"github.com/chussenot/datadog-mcp/internal/client"
"github.com/chussenot/datadog-mcp/internal/types"
v1 "github.com/chussenot/datadog-mcp/internal/api/v1"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// SubmitMetrics submits metrics to DataDog
func SubmitMetrics(ctx context.Context, client *client.DataDogClient, args types.SubmitMetricsArgs) (*mcp.CallToolResult, any, error) {
log.Printf("🔍 Calling DataDog API: SubmitMetrics with %d series", len(args.Series))
// Convert our types to DataDog API types
series := make([]v1.Series, len(args.Series))
for i, s := range args.Series {
series[i] = v1.Series{
Metric: s.Metric,
Points: s.Points,
Type: s.Type,
Host: s.Host,
Tags: &s.Tags,
}
}
// Marshal the series to JSON
seriesJSON, err := json.Marshal(series)
if err != nil {
log.Printf("❌ Failed to marshal series: %v", err)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("Failed to marshal series: %v", err)}},
}, nil, nil
}
payload := fmt.Sprintf(`{"series":%s}`, string(seriesJSON))
resp, err := client.Client.SubmitMetricsWithBodyWithResponse(ctx, &v1.SubmitMetricsParams{}, "application/json", strings.NewReader(payload))
if err != nil {
log.Printf("❌ API call error: %v", err)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("API call failed: %v", err)}},
}, nil, nil
}
log.Printf("📊 API Response Status: %d", resp.StatusCode())
log.Printf("📊 API Response Headers: %+v", resp.HTTPResponse.Header)
// Check response status
if resp.StatusCode() < 200 || resp.StatusCode() >= 300 {
body := "No response body"
if resp.Body != nil {
body = string(resp.Body)
}
log.Printf("❌ API error response: status %d, body: %s", resp.StatusCode(), body)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("API returned status %d: %s", resp.StatusCode(), body)}},
}, nil, nil
}
// Check if we have JSON response data
if resp.JSON200 == nil {
log.Printf("❌ No JSON200 data in response")
log.Printf("❌ Response body: %s", string(resp.Body))
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: "No JSON response data available"}},
}, nil, nil
}
// Convert the response to JSON string
jsonBytes, err := json.Marshal(resp.JSON200)
if err != nil {
log.Printf("❌ Failed to marshal JSON response: %v", err)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("Failed to marshal response: %v", err)}},
}, nil, nil
}
log.Printf("✅ Successfully submitted %d metric series", len(args.Series))
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: string(jsonBytes)},
},
}, nil, nil
}
// QueryMetrics queries metrics from DataDog
func QueryMetrics(ctx context.Context, client *client.DataDogClient, args types.QueryMetricsArgs) (*mcp.CallToolResult, any, error) {
log.Printf("🔍 Calling DataDog API: QueryMetrics with query: %s", args.Query)
params := &v1.QueryMetricsParams{
Query: args.Query,
From: args.From,
To: args.To,
}
resp, err := client.Client.QueryMetricsWithResponse(ctx, params)
if err != nil {
log.Printf("❌ API call error: %v", err)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("API call failed: %v", err)}},
}, nil, nil
}
log.Printf("📊 API Response Status: %d", resp.StatusCode())
log.Printf("📊 API Response Headers: %+v", resp.HTTPResponse.Header)
// Check response status
if resp.StatusCode() < 200 || resp.StatusCode() >= 300 {
body := "No response body"
if resp.Body != nil {
body = string(resp.Body)
}
log.Printf("❌ API error response: status %d, body: %s", resp.StatusCode(), body)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("API returned status %d: %s", resp.StatusCode(), body)}},
}, nil, nil
}
// Check if we have JSON response data
if resp.JSON200 == nil {
log.Printf("❌ No JSON200 data in response")
log.Printf("❌ Response body: %s", string(resp.Body))
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: "No JSON response data available"}},
}, nil, nil
}
// Convert the response to JSON string
jsonBytes, err := json.Marshal(resp.JSON200)
if err != nil {
log.Printf("❌ Failed to marshal JSON response: %v", err)
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("Failed to marshal response: %v", err)}},
}, nil, nil
}
log.Printf("✅ Successfully queried metrics")
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: string(jsonBytes)},
},
}, nil, nil
}