package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetAttributeValuesHandlerArgs struct {
Type model.MetricType `json:"type" jsonschema:"required,description=The type of telemetry data to get the attribute keys and values for. Either 'logs' or 'trace' or 'metric' or 'kubernetes_resource'"`
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to use while getting the possible values of log attributes. e.g. if you want to get values for the last 5 minutes you would set time_period=5 and time_window=Minutes. You can also set an absoulute time range by setting start_time and end_time"`
Attribute string `json:"attribute" jsonschema:"required,description=The attribute key to get the possible values for. Possible values for attribute should be obtained from get_attribute_keys tool call for the same type"`
MetricName string `json:"metricName" jsonschema:"description=REQUIRED IF THE TYPE IS 'metric'. The name of the metric to get the possible attribute keys and values."`
Filters map[string][]string `json:"filters" jsonschema:"description=The filters to apply before getting the possible values. For example if you want to get the possible values for an attribute key where the environment is X you would set the Filters as {environment: [X]}"`
}
func GetAttributeValuesHandler(ctx context.Context, arguments GetAttributeValuesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
err = CheckAttributes(ctx, arguments.Type, arguments.Filters, map[string][]string{}, []string{}, nil)
if err != nil {
return nil, err
}
request := model.GetAttributeValuesRequest{
Type: arguments.Type,
Attribute: arguments.Attribute,
}
switch arguments.Type {
case model.Logs:
err = CheckAttributes(ctx, arguments.Type, arguments.Filters, map[string][]string{}, []string{}, nil)
if err != nil {
return nil, err
}
modelRequest := model.LogSummaryRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
}
request.Logs = &modelRequest
break
case model.Trace:
err = CheckAttributes(ctx, arguments.Type, arguments.Filters, map[string][]string{}, []string{}, nil)
if err != nil {
return nil, err
}
modelRequest := model.TracesSummaryRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
}
request.Trace = &modelRequest
break
case model.Metric:
err = CheckAttributes(ctx, arguments.Type, arguments.Filters, map[string][]string{}, []string{}, &model.GetMetricAttributesRequest{
StartTime: startTime,
EndTime: endTime,
MetricName: arguments.MetricName,
})
if err != nil {
return nil, err
}
modelRequest := model.GetMetricAttributesRequest{
StartTime: startTime,
EndTime: endTime,
MetricName: arguments.MetricName,
Environments: arguments.Filters["environment"],
}
request.Metric = &modelRequest
break
//case model.KubernetesResource:
//
// modelRequest := model.GetKubernetesResourceRequest{
// StartTime: startTime,
// EndTime: endTime,
// Filters: arguments.Filters,
// ExcludeFilters: arguments.Filters,
// }
// request.Kubernetes = &modelRequest
// break
default:
return nil, fmt.Errorf("invalid type: %v", arguments.Type)
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "metrics/attribute/values", bytes.NewBuffer(jsonBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("error making Metoro call: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(resp)))), nil
}