This is page 1 of 2. Use http://codebase.md/metoro-io/metoro-mcp-server?page={x} to view the full context.
# Directory Structure
```
├── .github
│ └── workflows
│ ├── go-test.yml
│ └── release.yml
├── .gitignore
├── .goreleaser.yml
├── go.mod
├── go.sum
├── images
│ └── Metoro_square.svg
├── LICENSE
├── main.go
├── model
│ ├── model_action_email_destination.go
│ ├── model_action_pager_duty_destination.go
│ ├── model_action_slack_destination.go
│ ├── model_action_webhook_destination.go
│ ├── model_action.go
│ ├── model_alert_type.go
│ ├── model_alert.go
│ ├── model_condition_type.go
│ ├── model_condition.go
│ ├── model_create_update_alert_request.go
│ ├── model_expression_config_filters_inner.go
│ ├── model_expression_config_metoro_timeseries_definition.go
│ ├── model_expression_config.go
│ ├── model_metadata_object.go
│ ├── model_metoro_ql_timeseries.go
│ ├── model_operator_config.go
│ ├── model_operator_type.go
│ ├── model_persistence_settings.go
│ ├── model_static_condition.go
│ ├── model_timeseries_config_expression.go
│ ├── model_timeseries_config.go
│ ├── model_timeseries_specifier_filters_inner.go
│ ├── model_timeseries_specifier_function.go
│ ├── model_timeseries_specifier_functions_math_expression.go
│ ├── model_timeseries_specifier_functions.go
│ ├── model_timeseries_specifier_kubernetes_resource.go
│ ├── model_timeseries_specifier_logs.go
│ ├── model_timeseries_specifier_metric.go
│ ├── model_timeseries_specifier_traces.go
│ ├── model_timeseries_specifier.go
│ ├── model.go
│ └── utils.go
├── README.md
├── resources
│ ├── environments.go
│ ├── k8s_events_attributes.go
│ ├── log_attributes.go
│ ├── metrics.go
│ ├── namespaces.go
│ ├── nodes.go
│ ├── resources.go
│ ├── services.go
│ └── trace_attributes.go
├── tools
│ ├── create_ai_issue.go
│ ├── create_alert.go
│ ├── create_dashboard.go
│ ├── create_investigation.go
│ ├── get_ai_issue.go
│ ├── get_alert_fires.go
│ ├── get_alerts.go
│ ├── get_attribute_keys.go
│ ├── get_attribute_values.go
│ ├── get_environments.go
│ ├── get_k8s_event_attribute_values.go
│ ├── get_k8s_events_attributes.go
│ ├── get_k8s_events_volume.go
│ ├── get_k8s_events.go
│ ├── get_k8s_service_information.go
│ ├── get_log_attribute_values.go
│ ├── get_log_attributes.go
│ ├── get_logs.go
│ ├── get_metric_attributes.go
│ ├── get_metric_metadata.go
│ ├── get_metric_names.go
│ ├── get_multi_metric.go
│ ├── get_namespaces.go
│ ├── get_node_attributes.go
│ ├── get_node_info.go
│ ├── get_nodes.go
│ ├── get_pod_by_ip.go
│ ├── get_pods.go
│ ├── get_profiles.go
│ ├── get_service_graph.go
│ ├── get_service_summaries.go
│ ├── get_services.go
│ ├── get_source_repository.go
│ ├── get_trace_attribute_values.go
│ ├── get_trace_attributes.go
│ ├── get_trace_metric.go
│ ├── get_trace_spans.go
│ ├── get_traces_distribution.go
│ ├── get_traces.go
│ ├── get_version_for_service.go
│ ├── list_ai_issue_events.go
│ ├── list_ai_issues.go
│ ├── list_investigations.go
│ ├── tools.go
│ ├── unix_to_rfc3339.go
│ ├── update_ai_issue.go
│ └── update_investigation.go
└── utils
├── request_utils.go
├── time_utils_test.go
└── time_utils.go
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
.idea/*
metoro-mcp-server/metoro-mcp-server
```
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
```yaml
version: 2
before:
hooks:
- go mod tidy
builds:
- main: ./main.go
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
- -trimpath
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{ .CommitDate }}
archives:
- format: tar.gz
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else }}{{ .Arch }}{{ end }}
format_overrides:
- goos: windows
format: zip
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- '^ci:'
- Merge pull request
- Merge branch
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
<div align="center">
<img src="./images/Metoro_square.svg" height="300" alt="Metoro MCP Logo">
</div>
<br/>
<div align="center">







[](https://pkg.go.dev/github.com/metoro-io/metoro-mcp-server)
[](https://goreportcard.com/report/github.com/metoro-io/metoro-mcp-server)

</div>
# metoro-mcp-server
This repository contains th Metoro MCP (Model Context Protocol) Server. This MCP Server allows you to interact with your Kubernetes cluster via the Claude Desktop App!
## What is MCP (Model Context Protocol)?
You can read more about the Model Context Protocol here: https://modelcontextprotocol.io
But in a nutshell
> The Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. Whether you’re building an AI-powered IDE, enhancing a chat interface, or creating custom AI workflows, MCP provides a standardized way to connect LLMs with the context they need.
## What is Metoro?
[Metoro](https://metoro.io/) is an observability platform designed for microservices running in Kubernetes and uses eBPF based instrumentation to generate deep telemetry without code changes.
The data that is generated by the eBPF agents is sent to Metoro's backend to be stored and in the Metoro frontend using our apis.
This MCP server exposes those APIs to an LLM so you can ask your AI questions about your Kubernetes cluster.
## Demo
https://github.com/user-attachments/assets/b3f21e9a-45b8-4c17-8d8c-cff560d8694f
## How can I use Metoro MCP Server?
1. Install the [Claude Desktop App](https://claude.ai/download).
2. Make sure you have [Golang](https://golang.org/dl/) installed. `brew install go` for mac or `sudo apt-get install golang` for ubuntu.
3. Clone the repository: `git clone https://github.com/metoro-io/metoro-mcp-server.git`
4. Navigate to the repository directory: `cd metoro-mcp-server`
5. Build the server executable: `go build -o metoro-mcp-server`
### If you already have a Metoro Account:
Copy your auth token from your Metoro account in [Settings](https://us-east.metoro.io/settings) -> Users Settings.
Create a file in `~/Library/Application Support/Claude/claude_desktop_config.json` with the following contents:
```json
{
"mcpServers": {
"metoro-mcp-server": {
"command": "<your path to Metoro MCP server go executable>/metoro-mcp-server",
"args": [],
"env": {
"METORO_AUTH_TOKEN" : "<your auth token>",
"METORO_API_URL": "https://us-east.metoro.io"
}
}
}
}
```
### If you don't have a Metoro Account:
No worries, you can still play around using the [Live Demo Cluster](https://demo.us-east.metoro.io/).
The included token is a demo token, publicly available for anyone to use.
Create a file in `~/Library/Application Support/Claude/claude_desktop_config.json` with the following contents:
```json
{
"mcpServers": {
"metoro-mcp-server": {
"command": "<your path to Metoro MCP server go executable>/metoro-mcp-server",
"args": [],
"env": {
"METORO_AUTH_TOKEN" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoiOThlZDU1M2QtYzY4ZC00MDRhLWFhZjItNDM2ODllNWJiMGUzIiwiZW1haWwiOiJ0ZXN0QGNocmlzYmF0dGFyYmVlLmNvbSIsImV4cCI6MTgyMTI0NzIzN30.7G6alDpcZh_OThYj293Jce5rjeOBqAhOlANR_Fl5auw",
"METORO_API_URL": "https://demo.us-east.metoro.io"
}
}
}
}
```
4. Once you are done editing `claude_desktop_config.json` save the file and restart Claude Desktop app.
5. You should now see the Metoro MCP Server in the dropdown list of MCP Servers in the Claude Desktop App. You are ready to start using Metoro MCP Server with Claude Desktop App!
## Built with
This server is built on top of our [Golang MCP SDK](https://github.com/metoro-io/mcp-golang).
```
--------------------------------------------------------------------------------
/.github/workflows/go-test.yml:
--------------------------------------------------------------------------------
```yaml
name: Go Test
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '>=1.23'
cache: false
- name: Run tests
run: go test -v ./...
```
--------------------------------------------------------------------------------
/resources/services.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"context"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func ServicesResourceHandler() (*mcpgolang.ResourceResponse, error) {
ctx := context.Background()
response, err := utils.MakeMetoroAPIRequest("GET", "services", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://services", string(response), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/resources/namespaces.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"context"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func NamespacesResourceHandler() (*mcpgolang.ResourceResponse, error) {
ctx := context.Background()
response, err := utils.MakeMetoroAPIRequest("GET", "namespaces", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://namespaces", string(response), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/resources/environments.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"context"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func EnvironmentResourceHandler() (*mcpgolang.ResourceResponse, error) {
ctx := context.Background()
response, err := utils.MakeMetoroAPIRequest("GET", "environments", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://environments", string(response), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/resources/log_attributes.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"context"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func LogAttributesResourceHandler() (*mcpgolang.ResourceResponse, error) {
ctx := context.Background()
resp, err := utils.MakeMetoroAPIRequest("GET", "logsSummaryAttributes", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://logAttributes", string(resp), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/resources/trace_attributes.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"context"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func TraceAttributesResourceHandler() (*mcpgolang.ResourceResponse, error) {
ctx := context.Background()
resp, err := utils.MakeMetoroAPIRequest("GET", "tracesSummaryAttributes", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://traceAttributes", string(resp), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/resources/k8s_events_attributes.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"context"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func K8sEventsAttributesResourceHandler() (*mcpgolang.ResourceResponse, error) {
ctx := context.Background()
resp, err := utils.MakeMetoroAPIRequest("GET", "k8s/events/summaryAttributes", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://k8sEventAttributes", string(resp), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/tools/get_trace_attributes.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetTraceAttributesHandlerArgs struct{}
func GetTraceAttributesHandler(ctx context.Context, arguments GetTraceAttributesHandlerArgs) (*mcpgolang.ToolResponse, error) {
resp, err := utils.MakeMetoroAPIRequest("GET", "tracesSummaryAttributes", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(resp)))), nil
}
```
--------------------------------------------------------------------------------
/tools/get_k8s_events_attributes.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetK8sEventsAttributesHandlerArgs struct{}
func GetK8sEventsAttributesHandler(ctx context.Context, arguments GetK8sEventsAttributesHandlerArgs) (*mcpgolang.ToolResponse, error) {
resp, err := utils.MakeMetoroAPIRequest("GET", "k8s/events/summaryAttributes", nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(resp)))), nil
}
```
--------------------------------------------------------------------------------
/tools/get_log_attributes.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetLogAttributesHandlerArgs struct{}
func GetLogAttributesHandler(ctx context.Context, arguments GetLogAttributesHandlerArgs) (*mcpgolang.ToolResponse, error) {
resp, err := utils.MakeMetoroAPIRequest("GET", "logsSummaryAttributes", nil, 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
}
```
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
```yaml
name: Release with GoReleaser
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '>=1.23'
cache: false
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
--------------------------------------------------------------------------------
/tools/get_alerts.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetAlertHandlerArgs struct{}
func GetAlertsHandler(ctx context.Context, arguments GetAlertHandlerArgs) (*mcpgolang.ToolResponse, error) {
body, err := getAlertsMetoroCall(ctx)
if err != nil {
return nil, fmt.Errorf("error getting alerts: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getAlertsMetoroCall(ctx context.Context) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", "searchAlerts", nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_services.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetServicesHandlerArgs struct{}
func GetServicesHandler(ctx context.Context, arguments GetServicesHandlerArgs) (*mcpgolang.ToolResponse, error) {
body, err := getServicesMetoroCall(ctx)
if err != nil {
return nil, fmt.Errorf("error getting services: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getServicesMetoroCall(ctx context.Context) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", "services", nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_namespaces.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetNamespacesHandlerArgs struct{}
func GetNamespacesHandler(ctx context.Context, arguments GetNamespacesHandlerArgs) (*mcpgolang.ToolResponse, error) {
body, err := getNamespacesMetoroCall(ctx)
if err != nil {
return nil, fmt.Errorf("error getting namespaces: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getNamespacesMetoroCall(ctx context.Context) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", "namespaces", nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_environments.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetEnvironmentHandlerArgs struct{}
func GetEnvironmentsHandler(ctx context.Context, arguments GetEnvironmentHandlerArgs) (*mcpgolang.ToolResponse, error) {
body, err := getEnvironmentsMetoroCall(ctx)
if err != nil {
return nil, fmt.Errorf("error getting environments: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getEnvironmentsMetoroCall(ctx context.Context) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", "environments", nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/list_ai_issues.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type ListAIIssueHandlerArgs struct {
OpenOnly *bool `json:"openOnly,omitempty" jsonschema:"description=Set to true to list only open issues (default true), false to list all issues"`
}
func ListAIIssuesHandler(ctx context.Context, arguments ListAIIssueHandlerArgs) (*mcpgolang.ToolResponse, error) {
openOnly := true
if arguments.OpenOnly != nil {
openOnly = *arguments.OpenOnly
}
endpoint := "aiIssues"
if openOnly {
endpoint += "?openOnly=true"
}
responseBody, err := utils.MakeMetoroAPIRequest("GET", endpoint, nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to list AI issues: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(responseBody))), nil
}
```
--------------------------------------------------------------------------------
/tools/get_metric_metadata.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetMetricMetadataHandlerArgs struct {
Name string `json:"name" jsonschema:"required,description=The name of the metric to get metadata for"`
}
func GetMetricMetadata(ctx context.Context, arguments GetMetricMetadataHandlerArgs) (*mcpgolang.ToolResponse, error) {
response, err := getMetricMetadataMetoroCall(ctx, arguments.Name)
if err != nil {
return nil, fmt.Errorf("error calling Metoro get metric metadata api: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(response)))), nil
}
func getMetricMetadataMetoroCall(ctx context.Context, metricName string) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", "metric/metadata?name="+metricName, nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/resources/metrics.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"bytes"
"context"
"encoding/json"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func MetricsResourceHandler() (*mcpgolang.ResourceResponse, error) {
now := time.Now()
twoHoursAgo := now.Add(-2 * time.Hour)
request := model.FuzzyMetricsRequest{
StartTime: twoHoursAgo.Unix(),
EndTime: now.Unix(),
MetricFuzzyMatch: "", // This will return all the metric names.
Environments: []string{}, // All environments
}
jsonData, err := json.Marshal(request)
if err != nil {
return nil, err
}
ctx := context.Background()
resp, err := utils.MakeMetoroAPIRequest("POST", "fuzzyMetricsNames", bytes.NewBuffer(jsonData), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://metrics", string(resp), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/tools/get_node_info.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetNodeInfoHandlerArgs struct {
NodeName string `json:"nodeName" jsonschema:"required,description=The name of the node to get the YAML/information for"`
}
func GetNodeInfoHandler(ctx context.Context, arguments GetNodeInfoHandlerArgs) (*mcpgolang.ToolResponse, error) {
now := time.Now()
fiveMinsAgo := now.Add(-10 * time.Minute)
body, err := getNodeInfoMetoroCall(ctx, arguments.NodeName, fiveMinsAgo.Unix())
if err != nil {
return nil, fmt.Errorf("error getting node info: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getNodeInfoMetoroCall(ctx context.Context, nodeName string, startTime int64) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", fmt.Sprintf("infrastructure/node?nodeName=%s&startTime=%d", nodeName, startTime), nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/resources/nodes.go:
--------------------------------------------------------------------------------
```go
package resources
import (
"bytes"
"context"
"encoding/json"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func NodesResourceHandler() (*mcpgolang.ResourceResponse, error) {
now := time.Now()
tenMinsAgo := now.Add(-10 * time.Minute)
request := model.GetAllNodesRequest{
StartTime: tenMinsAgo.Unix(),
EndTime: now.Unix(),
Filters: map[string][]string{},
ExcludeFilters: map[string][]string{},
Splits: []string{},
Environments: []string{},
}
jsonRequest, err := json.Marshal(request)
if err != nil {
return nil, err
}
ctx := context.Background()
response, err := utils.MakeMetoroAPIRequest("POST", "infrastructure/nodes", bytes.NewBuffer(jsonRequest), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, err
}
return mcpgolang.NewResourceResponse(
mcpgolang.NewTextEmbeddedResource("api://nodes", string(response), "text/plain")), nil
}
```
--------------------------------------------------------------------------------
/tools/get_node_attributes.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"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 GetNodeAttributesHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"timeConfig" jsonschema:"required,description=The time range to get the node attributes for"`
}
func GetNodeAttributesHandler(ctx context.Context, arguments GetNodeAttributesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.MetricAttributesRequest{
StartTime: startTime,
EndTime: endTime,
MetricName: "node_info",
FilterAttributes: map[string][]string{},
}
response, err := getMetricAttributesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error calling Metoro API: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(response)))), nil
}
```
--------------------------------------------------------------------------------
/tools/get_ai_issue.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"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 GetAIIssueHandlerArgs struct {
IssueUUID string `json:"issueUuid" jsonschema:"required,description=UUID of the AI issue to retrieve"`
}
func GetAIIssueHandler(ctx context.Context, arguments GetAIIssueHandlerArgs) (*mcpgolang.ToolResponse, error) {
endpoint := fmt.Sprintf("aiIssue?uuid=%s", arguments.IssueUUID)
responseBody, err := utils.MakeMetoroAPIRequest("GET", endpoint, nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to fetch AI issue: %w", err)
}
var issueResponse model.GetAIIssueResponse
if err := json.Unmarshal(responseBody, &issueResponse); err != nil {
return nil, fmt.Errorf("failed to parse AI issue response: %w", err)
}
serialized, err := json.Marshal(issueResponse.Issue)
if err != nil {
return nil, fmt.Errorf("failed to marshal AI issue: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(serialized))), nil
}
```
--------------------------------------------------------------------------------
/tools/list_ai_issue_events.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"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 ListAIIssueEventsHandlerArgs struct {
IssueUUID string `json:"issueUuid" jsonschema:"required,description=UUID of the AI issue whose events should be listed"`
}
func ListAIIssueEventsHandler(ctx context.Context, arguments ListAIIssueEventsHandlerArgs) (*mcpgolang.ToolResponse, error) {
endpoint := fmt.Sprintf("aiIssue/events?issueUuid=%s", arguments.IssueUUID)
responseBody, err := utils.MakeMetoroAPIRequest("GET", endpoint, nil, utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to list AI issue events: %w", err)
}
var resp model.ListAIIssueEventsResponse
if err := json.Unmarshal(responseBody, &resp); err != nil {
return nil, fmt.Errorf("failed to parse AI issue events response: %w", err)
}
serialized, err := json.Marshal(resp.Events)
if err != nil {
return nil, fmt.Errorf("failed to marshal AI issue events: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(serialized))), nil
}
```
--------------------------------------------------------------------------------
/tools/create_ai_issue.go:
--------------------------------------------------------------------------------
```go
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 CreateAIIssueHandlerArgs struct {
Title string `json:"title" jsonschema:"required,description=Title of the AI issue"`
Description string `json:"description" jsonschema:"required,description=Detailed description of the AI issue"`
Summary string `json:"summary" jsonschema:"required,description=One sentence summary of the AI issue"`
}
func CreateAIIssueHandler(ctx context.Context, arguments CreateAIIssueHandlerArgs) (*mcpgolang.ToolResponse, error) {
request := model.CreateAIIssueRequest{
Title: arguments.Title,
Description: arguments.Description,
Summary: arguments.Summary,
}
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
responseBody, err := utils.MakeMetoroAPIRequest("POST", "aiIssue", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to create AI issue: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(responseBody))), nil
}
```
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
```go
package main
import (
"fmt"
"os"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/mcp-golang/transport/stdio"
"github.com/metoro-io/metoro-mcp-server/resources"
"github.com/metoro-io/metoro-mcp-server/tools"
"github.com/metoro-io/metoro-mcp-server/utils"
)
func main() {
// Check if the appropriate environment variables are set
if err := checkEnvVars(); err != nil {
panic(err)
}
done := make(chan struct{})
mcpServer := mcpgolang.NewServer(stdio.NewStdioServerTransport())
// Add tools
for _, tool := range tools.MetoroToolsList {
err := mcpServer.RegisterTool(tool.Name, tool.Description, tool.Handler)
if err != nil {
panic(err)
}
}
// Add resources
for _, resource := range resources.MetoroResourcesList {
err := mcpServer.RegisterResource(
resource.Path,
resource.Name,
resource.Description,
resource.ContentType,
resource.Handler)
if err != nil {
panic(err)
}
}
err := mcpServer.Serve()
if err != nil {
panic(err)
}
<-done
}
func checkEnvVars() error {
if os.Getenv(utils.METORO_API_URL_ENV_VAR) == "" {
return fmt.Errorf("%s environment variable not set", utils.METORO_API_URL_ENV_VAR)
}
if os.Getenv(utils.METORO_AUTH_TOKEN_ENV_VAR) == "" {
return fmt.Errorf("%s environment variable not set", utils.METORO_AUTH_TOKEN_ENV_VAR)
}
return nil
}
```
--------------------------------------------------------------------------------
/tools/get_metric_names.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetMetricNamesHandlerArgs struct {
Environments []string `json:"environments" jsonschema:"description=Environments to get metrics names from. If empty all environments will be used."`
}
func GetMetricNamesHandler(ctx context.Context, arguments GetMetricNamesHandlerArgs) (*mcpgolang.ToolResponse, error) {
now := time.Now()
hourAgo := now.Add(-1 * time.Hour)
request := model.FuzzyMetricsRequest{
StartTime: hourAgo.Unix(),
EndTime: now.Unix(),
MetricFuzzyMatch: "", // This will return all the metric names.
Environments: arguments.Environments,
}
response, err := getMetricNamesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error calling Metoro API: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(response)))), nil
}
func getMetricNamesMetoroCall(ctx context.Context, request model.FuzzyMetricsRequest) ([]byte, error) {
jsonData, err := json.Marshal(request)
if err != nil {
return nil, err
}
return utils.MakeMetoroAPIRequest("POST", "fuzzyMetricsNames", bytes.NewBuffer(jsonData), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_alert_fires.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetAlertFiresHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get alert fires for. e.g. if you want to get alert fires 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"`
AlertId string `json:"alert_id" jsonschema:"required,description=The ID of the alert to get the alert fires for"`
}
func GetAlertFiresHandler(ctx context.Context, arguments GetAlertFiresHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
body, err := getAlertFiresMetoroCall(ctx, arguments.AlertId, startTime, endTime)
if err != nil {
return nil, fmt.Errorf("error getting alert fires: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getAlertFiresMetoroCall(ctx context.Context, alertId string, startTime, endTime int64) ([]byte, error) {
return utils.MakeMetoroAPIRequest("GET", fmt.Sprintf("alertFires?alertId=%s&startTime=%d&endTime=%d", alertId, startTime, endTime), nil, utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/unix_to_rfc3339.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"context"
"fmt"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
)
type UnixToRFC3339HandlerArgs struct {
UnixTimestamp int64 `json:"unix_timestamp" jsonschema:"required,description=Unix timestamp in seconds or milliseconds"`
}
func UnixToRFC3339Handler(ctx context.Context, arguments UnixToRFC3339HandlerArgs) (*mcpgolang.ToolResponse, error) {
// Determine if the timestamp is in seconds or milliseconds
// Unix timestamps in seconds are typically 10 digits (until year 2286)
// Unix timestamps in milliseconds are typically 13 digits
var t time.Time
// Check if it's likely milliseconds (more than 10 digits or would result in a date far in the future)
if arguments.UnixTimestamp > 9999999999 {
// Treat as milliseconds
t = time.Unix(0, arguments.UnixTimestamp*int64(time.Millisecond))
} else {
// Treat as seconds
t = time.Unix(arguments.UnixTimestamp, 0)
}
// Convert to RFC3339 format
rfc3339String := t.UTC().Format(time.RFC3339)
// Create a response with both interpretations if the timestamp could be ambiguous
var response string
if arguments.UnixTimestamp <= 9999999999 && arguments.UnixTimestamp >= 1000000000 {
// Could be either seconds or milliseconds, show both
tAsMillis := time.Unix(0, arguments.UnixTimestamp*int64(time.Millisecond))
response = fmt.Sprintf("Interpreted as seconds: %s\nInterpreted as milliseconds: %s",
rfc3339String,
tAsMillis.UTC().Format(time.RFC3339))
} else {
response = rfc3339String
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(response)), nil
}
```
--------------------------------------------------------------------------------
/tools/create_dashboard.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/google/uuid"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type CreateDashboardHandlerArgs struct {
DashboardName string `json:"dashboard_name" jsonschema:"required,description=The name of the dashboard to create"`
GroupWidget model.GroupWidget `json:"group_widget" jsonschema:"required,description=The group widget this dashboard will have. This is the top level widget of the dashboard that will contain all other widgets. A widget can be either a group widget or a MetricChartWidget"`
}
func CreateDashboardHandler(ctx context.Context, arguments CreateDashboardHandlerArgs) (*mcpgolang.ToolResponse, error) {
dashboardJson, err := json.Marshal(arguments.GroupWidget)
if err != nil {
return nil, fmt.Errorf("error marshaling dashboard properties: %v", err)
}
newDashboardRequest := model.SetDashboardRequest{
Name: arguments.DashboardName,
Id: uuid.NewString(),
DashboardJson: string(dashboardJson),
DefaultTimeRange: "1h",
}
resp, err := setDashboardMetoroCall(ctx, newDashboardRequest)
if err != nil {
return nil, fmt.Errorf("error setting dashboard: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(resp)))), nil
}
func setDashboardMetoroCall(ctx context.Context, request model.SetDashboardRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling dashboard request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "dashboard", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_k8s_service_information.go:
--------------------------------------------------------------------------------
```go
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 GetK8sServiceInformationHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time to get state of the YAML file. e.g. if you want to see the state of the service 5 minutes ago 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"`
ServiceName string `json:"serviceName" jsonschema:"required,description=The name of the service to get YAML file for."`
Environments []string `json:"environments" jsonschema:"description=The environments to get service YAML for. If empty all environments will be used."`
}
func GetK8sServiceInformationHandler(ctx context.Context, arguments GetK8sServiceInformationHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetPodsRequest{
StartTime: startTime,
EndTime: endTime,
ServiceName: arguments.ServiceName,
Environments: arguments.Environments,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "k8s/summary", 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
}
```
--------------------------------------------------------------------------------
/tools/update_ai_issue.go:
--------------------------------------------------------------------------------
```go
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 UpdateAIIssueHandlerArgs struct {
IssueUUID string `json:"issueUuid" jsonschema:"required,description=UUID of the AI issue to update"`
Title *string `json:"title,omitempty" jsonschema:"description=Optional new title for the AI issue"`
Description *string `json:"description,omitempty" jsonschema:"description=Optional new description for the AI issue"`
Summary *string `json:"summary,omitempty" jsonschema:"description=Optional new summary for the AI issue"`
Open *bool `json:"open,omitempty" jsonschema:"description=Optional flag to set whether the AI issue is open (true) or resolved (false)"`
}
func UpdateAIIssueHandler(ctx context.Context, arguments UpdateAIIssueHandlerArgs) (*mcpgolang.ToolResponse, error) {
if arguments.Title == nil && arguments.Description == nil && arguments.Summary == nil && arguments.Open == nil {
return nil, fmt.Errorf("at least one of title, description, summary, or open must be provided to update an AI issue")
}
request := model.UpdateAIIssueRequest{
Title: arguments.Title,
Description: arguments.Description,
Summary: arguments.Summary,
Open: arguments.Open,
}
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
endpoint := fmt.Sprintf("aiIssue?uuid=%s", arguments.IssueUUID)
responseBody, err := utils.MakeMetoroAPIRequest("PUT", endpoint, bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to update AI issue: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(responseBody))), nil
}
```
--------------------------------------------------------------------------------
/tools/get_profiles.go:
--------------------------------------------------------------------------------
```go
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 GetProfileHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the profiles data. e.g. if you want to get profiles 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"`
ServiceName string `json:"serviceName" jsonschema:"required,description=The name of the service to get profiles for"`
ContainerNames []string `json:"containerNames" jsonschema:"description=The container names to get profiles for"`
}
func GetProfilesHandler(ctx context.Context, arguments GetProfileHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetProfileRequest{
StartTime: startTime,
EndTime: endTime,
ServiceName: arguments.ServiceName,
ContainerNames: arguments.ContainerNames,
}
body, err := getProfilesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting profiles: %v", err)
}
if len(body) > 200000 {
return nil, fmt.Errorf("response too large, please refine your query to get a smaller response")
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getProfilesMetoroCall(ctx context.Context, request model.GetProfileRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling profiles request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "profiles", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/list_investigations.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type ListInvestigationsHandlerArgs struct {
Limit int `json:"limit,omitempty" jsonschema:"description=Maximum number of investigations to return (default 20 max 100)"`
Offset int `json:"offset,omitempty" jsonschema:"description=Number of investigations to skip for pagination"`
Tags map[string]string `json:"tags,omitempty" jsonschema:"description=Filter investigations by tags"`
IncludeResolved bool `json:"includeResolved,omitempty" jsonschema:"description=Include resolved investigations in the results"`
}
func ListInvestigationsHandler(ctx context.Context, arguments ListInvestigationsHandlerArgs) (*mcpgolang.ToolResponse, error) {
// Create the request body
request := struct {
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
IncludeResolved bool `json:"includeResolved,omitempty"`
ExcludeInProgress bool `json:"excludeInProgress,omitempty"`
}{
Limit: arguments.Limit,
Offset: arguments.Offset,
Tags: arguments.Tags,
IncludeResolved: arguments.IncludeResolved,
ExcludeInProgress: true, // Always exclude in-progress investigations as the AI only wants to see the past investigations.
}
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
// Make the API request
responseBody, err := utils.MakeMetoroAPIRequest("POST", "investigations/list", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to list investigations: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(responseBody))), nil
}
```
--------------------------------------------------------------------------------
/utils/request_utils.go:
--------------------------------------------------------------------------------
```go
package utils
import (
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
const METORO_API_URL_ENV_VAR = "METORO_API_URL"
const METORO_AUTH_TOKEN_ENV_VAR = "METORO_AUTH_TOKEN"
type APIRequirements struct {
authHeader string
metoroUrl string
}
func GetAPIRequirementsFromRequest(ctx context.Context) *APIRequirements {
c := ctx.Value("ginContext")
if c == nil {
return nil
}
ginContext, ok := c.(*gin.Context)
if !ok {
return nil
}
if ginContext.Request.Header.Get("Authorization") != "" {
return &APIRequirements{
authHeader: ginContext.Request.Header.Get("Authorization"),
metoroUrl: "http://localhost:8080",
}
}
return nil
}
// makeMetoroAPIRequest makes an HTTP request to the Metoro API with the given method, endpoint, and body.
// It handles authentication and common error cases.
func MakeMetoroAPIRequest(method, endpoint string, body io.Reader, apiRequirements *APIRequirements) ([]byte, error) {
// Create a new HTTP client
client := &http.Client{}
if apiRequirements == nil {
apiRequirements = &APIRequirements{
authHeader: "Bearer " + os.Getenv(METORO_AUTH_TOKEN_ENV_VAR),
metoroUrl: os.Getenv(METORO_API_URL_ENV_VAR),
}
}
// Create a new request
req, err := http.NewRequest(method, fmt.Sprintf("%s/api/v1/%s", apiRequirements.metoroUrl, endpoint), body)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
}
// Add the Authorization header
req.Header.Add("Authorization", apiRequirements.authHeader)
// Send the request
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("error sending request: %v", err)
}
defer resp.Body.Close()
// Read the response body
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response body: %v", err)
}
// Check the response status code
if resp.StatusCode >= 300 {
return nil, fmt.Errorf("unexpected status code: %d, body: %s", resp.StatusCode, string(responseBody))
}
return responseBody, nil
}
```
--------------------------------------------------------------------------------
/tools/get_service_summaries.go:
--------------------------------------------------------------------------------
```go
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 GetServiceSummariesHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get service summaries for. e.g. if you want to get summaries for the last 5 minutes you would set time_period=5 and time_window=Minutes. Try to use a time period 1 hour or less. You can also set an absoulute time range by setting start_time and end_time"`
Namespaces string `json:"namespace" jsonschema:"description=The namespace to get service summaries for. If empty all namespaces will be used."`
Environments []string `json:"environments" jsonschema:"description=The environments to get service summaries for. If empty all environments will be used."`
}
func GetServiceSummariesHandler(ctx context.Context, arguments GetServiceSummariesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetServiceSummariesRequest{
StartTime: startTime,
EndTime: endTime,
Namespace: arguments.Namespaces,
Environments: arguments.Environments,
}
body, err := getServiceSummariesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting service summaries: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getServiceSummariesMetoroCall(ctx context.Context, request model.GetServiceSummariesRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling service summaries request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "serviceSummaries", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_metric_attributes.go:
--------------------------------------------------------------------------------
```go
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 GetMetricAttributesHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"timeConfig" jsonschema:"required,description=The time period to get the possible values of metric attributes for. e.g. if you want to get the possible 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"`
MetricName string `json:"metricName" jsonschema:"required,description=The name of the metric to get the possible attribute keys and values."`
FilterAttributes map[string][]string `json:"filterAttributes" jsonschema:"description=The attributes to filter the metric attributes by before getting the possible values. For example if you want to get the possible keys and values where the environment is X you would set the filterAttributes as {environment: [X]}"`
}
func GetMetricAttributesHandler(ctx context.Context, arguments GetMetricAttributesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.MetricAttributesRequest{
StartTime: startTime,
EndTime: endTime,
MetricName: arguments.MetricName,
FilterAttributes: arguments.FilterAttributes,
}
response, err := getMetricAttributesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error calling Metoro API: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(response)))), nil
}
func getMetricAttributesMetoroCall(ctx context.Context, request model.MetricAttributesRequest) ([]byte, error) {
jsonData, err := json.Marshal(request)
if err != nil {
return nil, err
}
return utils.MakeMetoroAPIRequest("POST", "metricAttributes", bytes.NewBuffer(jsonData), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/model/model_alert_type.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
"fmt"
)
// AlertType Type of alert
type AlertType string
// List of AlertType
const (
TIMESERIES AlertType = "timeseries"
)
// All allowed values of AlertType enum
var AllowedAlertTypeEnumValues = []AlertType{
"timeseries",
}
func (v *AlertType) UnmarshalJSON(src []byte) error {
var value string
err := json.Unmarshal(src, &value)
if err != nil {
return err
}
enumTypeValue := AlertType(value)
for _, existing := range AllowedAlertTypeEnumValues {
if existing == enumTypeValue {
*v = enumTypeValue
return nil
}
}
return fmt.Errorf("%+v is not a valid AlertType", value)
}
// NewAlertTypeFromValue returns a pointer to a valid AlertType
// for the value passed as argument, or an error if the value passed is not allowed by the enum
func NewAlertTypeFromValue(v string) (*AlertType, error) {
ev := AlertType(v)
if ev.IsValid() {
return &ev, nil
} else {
return nil, fmt.Errorf("invalid value '%v' for AlertType: valid values are %v", v, AllowedAlertTypeEnumValues)
}
}
// IsValid return true if the value is valid for the enum, false otherwise
func (v AlertType) IsValid() bool {
for _, existing := range AllowedAlertTypeEnumValues {
if existing == v {
return true
}
}
return false
}
// Ptr returns reference to AlertType value
func (v AlertType) Ptr() *AlertType {
return &v
}
type NullableAlertType struct {
value *AlertType
isSet bool
}
func (v NullableAlertType) Get() *AlertType {
return v.value
}
func (v *NullableAlertType) Set(val *AlertType) {
v.value = val
v.isSet = true
}
func (v NullableAlertType) IsSet() bool {
return v.isSet
}
func (v *NullableAlertType) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableAlertType(val *AlertType) *NullableAlertType {
return &NullableAlertType{value: val, isSet: true}
}
func (v NullableAlertType) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableAlertType) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/tools/get_pod_by_ip.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetResourcesByIpHandlerArgs struct {
Ip string `json:"ip" jsonschema:"required,description=IP address to search for"`
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the resources for. e.g. if you want the get the resources for the last 5 minutes you would set time_period=5 and time_window=Minutes. You can also set an absolute time range by setting start_time and end_time"`
Environment string `json:"environment" jsonschema:"required,description=Environment to filter the resources by"`
}
type GetResourcesByIpRequest struct {
Ip string `json:"ip"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
Environment string `json:"environment"`
}
type GetResourcesByIpResponse struct {
Resources []ResourcesByIpData `json:"resources"`
}
type ResourcesByIpData struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Ip string `json:"ip"`
NodeName string `json:"nodeName"`
Status string `json:"status"`
Environment string `json:"environment"`
}
func GetResourcesByIpHandler(ctx context.Context, arguments GetResourcesByIpHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := GetResourcesByIpRequest{
Ip: arguments.Ip,
StartTime: startTime,
EndTime: endTime,
Environment: arguments.Environment,
}
resp, err := getPodByIpMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting pod by IP: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(resp)))), nil
}
func getPodByIpMetoroCall(ctx context.Context, request GetResourcesByIpRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling pod by IP request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "k8s/resources/byIp", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/model/model_condition_type.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
"fmt"
)
// ConditionType Type of alert condition
type ConditionType string
// List of ConditionType
const (
STATIC ConditionType = "static"
)
// All allowed values of ConditionType enum
var AllowedConditionTypeEnumValues = []ConditionType{
"static",
}
func (v *ConditionType) UnmarshalJSON(src []byte) error {
var value string
err := json.Unmarshal(src, &value)
if err != nil {
return err
}
enumTypeValue := ConditionType(value)
for _, existing := range AllowedConditionTypeEnumValues {
if existing == enumTypeValue {
*v = enumTypeValue
return nil
}
}
return fmt.Errorf("%+v is not a valid ConditionType", value)
}
// NewConditionTypeFromValue returns a pointer to a valid ConditionType
// for the value passed as argument, or an error if the value passed is not allowed by the enum
func NewConditionTypeFromValue(v string) (*ConditionType, error) {
ev := ConditionType(v)
if ev.IsValid() {
return &ev, nil
} else {
return nil, fmt.Errorf("invalid value '%v' for ConditionType: valid values are %v", v, AllowedConditionTypeEnumValues)
}
}
// IsValid return true if the value is valid for the enum, false otherwise
func (v ConditionType) IsValid() bool {
for _, existing := range AllowedConditionTypeEnumValues {
if existing == v {
return true
}
}
return false
}
// Ptr returns reference to ConditionType value
func (v ConditionType) Ptr() *ConditionType {
return &v
}
type NullableConditionType struct {
value *ConditionType
isSet bool
}
func (v NullableConditionType) Get() *ConditionType {
return v.value
}
func (v *NullableConditionType) Set(val *ConditionType) {
v.value = val
v.isSet = true
}
func (v NullableConditionType) IsSet() bool {
return v.isSet
}
func (v *NullableConditionType) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableConditionType(val *ConditionType) *NullableConditionType {
return &NullableConditionType{value: val, isSet: true}
}
func (v NullableConditionType) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableConditionType) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/tools/get_pods.go:
--------------------------------------------------------------------------------
```go
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 GetPodsHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get pods for. e.g. if you want to get pods 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"`
ServiceName string `json:"serviceName" jsonschema:"description=The name of the service to get pods for. One of serviceName or nodeName is required"`
NodeName string `json:"nodeName" jsonschema:"description=The name of the node to get pods for. One of serviceName or nodeName is required"`
Environments []string `json:"environments" jsonschema:"description=The environments to get pods for. If empty, all environments will be used."`
}
func GetPodsHandler(ctx context.Context, arguments GetPodsHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
// One of serviceName or nodeName is required.
if arguments.ServiceName == "" && arguments.NodeName == "" {
return nil, fmt.Errorf("one of serviceName or nodeName is required")
}
request := model.GetPodsRequest{
StartTime: startTime,
EndTime: endTime,
Environments: arguments.Environments,
ServiceName: arguments.ServiceName,
NodeName: arguments.NodeName,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "k8s/pods", bytes.NewBuffer(jsonBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("error making Metoro call: %v", err)
}
response := []PodsResponse{}
err = json.Unmarshal(resp, &response)
if err != nil {
return nil, fmt.Errorf("error unmarshaling response: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprint(response))), nil
}
type PodsResponse struct {
Name string `json:"name"`
Environment string `json:"environment"`
Status string `json:"status"`
}
```
--------------------------------------------------------------------------------
/tools/get_nodes.go:
--------------------------------------------------------------------------------
```go
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 GetNodesHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get nodes for. e.g. if you want to get nodes for the last 5 minutes you would set time_period=5 and time_window=Minutes or if you want to get nodes for the last 2 hours you would set time_period=2 and time_window=Hours. You can also set an absoulute time range by setting start_time and end_time"`
Filters map[string][]string `json:"filters" jsonschema:"description=The filters to apply to the nodes. Only the nodes that match these filters will be returned. To get possible filter keys and values use the get_node_attributes tool."`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The filters to exclude the nodes. Nodes matching the exclude filters will not be returned. To get possible exclude filter keys and values use the get_node_attributes tool."`
Environments []string `json:"environments" jsonschema:"description=The environments to get nodes that belong to. If empty all environments will be used."`
}
func GetNodesHandler(ctx context.Context, arguments GetNodesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetAllNodesRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Splits: []string{},
Environments: arguments.Environments,
}
body, err := getNodesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting nodes: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getNodesMetoroCall(ctx context.Context, request model.GetAllNodesRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling nodes request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "infrastructure/nodes", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_source_repository.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetSourceRepositoryHandlerArgs struct {
// Required: Service name to get the source repository for
ServiceName string `json:"serviceName" jsonschema:"required,description=The name of the service to get the source repository for"`
// Optional: Environment to filter by. If not provided, all environments are considered
Environments []string `json:"environments" jsonschema:"description=List of environments to search for the service in. If empty all environments will be considered"`
// Required: Time configuration for the query
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the source repository information for. You can use relative time (e.g. last 5 minutes) or absolute time range."`
}
type GetSourceRepositoryRequest struct {
ServiceName string `json:"serviceName"`
Environments []string `json:"environments"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
}
type GetSourceRepositoryResponse struct {
// The source repository URL/path found in the deployment
Repository string `json:"repository"`
// Whether a repository was found
Found bool `json:"found"`
// The environment where the repository information was found
Environment string `json:"environment,omitempty"`
}
func GetSourceRepositoryHandler(ctx context.Context, arguments GetSourceRepositoryHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
body, err := getSourceRepositoryMetoroCall(ctx, arguments, startTime, endTime)
if err != nil {
return nil, fmt.Errorf("error getting source repository: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getSourceRepositoryMetoroCall(ctx context.Context, args GetSourceRepositoryHandlerArgs, startTime, endTime int64) ([]byte, error) {
req := GetSourceRepositoryRequest{
ServiceName: args.ServiceName,
Environments: args.Environments,
StartTime: startTime,
EndTime: endTime,
}
reqBody, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("error marshalling request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "source/repository", bytes.NewBuffer(reqBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/tools/get_trace_spans.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetTraceSpansHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get trace spans for. e.g. if you want to get spans for the last 5 minutes you would set time_period=5 and time_window=Minutes. You can also set an absolute time range by setting start_time and end_time"`
TraceId string `json:"trace_id" jsonschema:"required,description=The traceId of the trace to get the associated spans. get_traces tool will return list of traceIds which should be used for this field."`
Environments []string `json:"environments" jsonschema:"description=The environments to get the spans for. If empty all environments will be included"`
}
type GetSpansForTraceRequest struct {
// Required: Start time of when to get the traces in seconds since epoch
StartTime int64 `json:"startTime"`
// Required: End time of when to get the traces in seconds since epoch
EndTime int64 `json:"endTime"`
// Required: The traceId of the trace to get the associated spans.
TraceId string `json:"traceId"`
// The environments to get the traces for. If empty, all environments will be included
Environments []string `json:"environments"`
ShouldReturnNonMetoroEpbfSpans bool `json:"shouldReturnNonMetoroEpbfSpans"`
}
func GetTraceSpansHandler(ctx context.Context, arguments GetTraceSpansHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := GetSpansForTraceRequest{
StartTime: startTime,
EndTime: endTime,
TraceId: arguments.TraceId,
Environments: arguments.Environments,
ShouldReturnNonMetoroEpbfSpans: true,
}
body, err := getTraceSpansMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting trace spans: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getTraceSpansMetoroCall(ctx context.Context, request GetSpansForTraceRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling trace spans request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "spans", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/model/model_operator_type.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
"fmt"
)
// OperatorType Type of comparison operator
type OperatorType string
// List of OperatorType
const (
GREATER_THAN OperatorType = "greaterThan"
LESS_THAN OperatorType = "lessThan"
GREATER_THAN_OR_EQUAL OperatorType = "greaterThanOrEqual"
LESS_THAN_OR_EQUAL OperatorType = "lessThanOrEqual"
EQUALS OperatorType = "equals"
NOT_EQUALS OperatorType = "notEquals"
)
// All allowed values of OperatorType enum
var AllowedOperatorTypeEnumValues = []OperatorType{
"greaterThan",
"lessThan",
"greaterThanOrEqual",
"lessThanOrEqual",
"equals",
"notEquals",
}
func (v *OperatorType) UnmarshalJSON(src []byte) error {
var value string
err := json.Unmarshal(src, &value)
if err != nil {
return err
}
enumTypeValue := OperatorType(value)
for _, existing := range AllowedOperatorTypeEnumValues {
if existing == enumTypeValue {
*v = enumTypeValue
return nil
}
}
return fmt.Errorf("%+v is not a valid OperatorType", value)
}
// NewOperatorTypeFromValue returns a pointer to a valid OperatorType
// for the value passed as argument, or an error if the value passed is not allowed by the enum
func NewOperatorTypeFromValue(v string) (*OperatorType, error) {
ev := OperatorType(v)
if ev.IsValid() {
return &ev, nil
} else {
return nil, fmt.Errorf("invalid value '%v' for OperatorType: valid values are %v", v, AllowedOperatorTypeEnumValues)
}
}
// IsValid return true if the value is valid for the enum, false otherwise
func (v OperatorType) IsValid() bool {
for _, existing := range AllowedOperatorTypeEnumValues {
if existing == v {
return true
}
}
return false
}
// Ptr returns reference to OperatorType value
func (v OperatorType) Ptr() *OperatorType {
return &v
}
type NullableOperatorType struct {
value *OperatorType
isSet bool
}
func (v NullableOperatorType) Get() *OperatorType {
return v.value
}
func (v *NullableOperatorType) Set(val *OperatorType) {
v.value = val
v.isSet = true
}
func (v NullableOperatorType) IsSet() bool {
return v.isSet
}
func (v *NullableOperatorType) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableOperatorType(val *OperatorType) *NullableOperatorType {
return &NullableOperatorType{value: val, isSet: true}
}
func (v NullableOperatorType) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableOperatorType) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/tools/get_k8s_events_volume.go:
--------------------------------------------------------------------------------
```go
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 GetK8sEventsVolumeHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get events volumes for. e.g. if you want to get events 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"`
Filters map[string][]string `json:"filters" jsonschema:"description=Filters to apply to the events. Only the event matching these filters will be counted. Get the possible filter keys from the get_k8s_events_attributes tool and possible filter values from the get_k8s_event_attribute_values tool (for a filter key)"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=Filters to exclude the events. Events matching the exclude filters will not be counted. Get the possible exclude filter keys from the get_k8s_events_attributes tool and possible exclude filter values from the get_k8s_event_attribute_values tool (for a key)"`
Regexes []string `json:"regexes" jsonschema:"description=Only the events with messages that match these regexes will be counted"`
ExcludeRegexes []string `json:"excludeRegexes" jsonschema:"description=Events with messages that match these regexes will not be counted"`
Environments []string `json:"environments" jsonschema:"description=Environments to get events from"`
}
func GetK8sEventsVolumeHandler(ctx context.Context, arguments GetK8sEventsVolumeHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetK8sEventMetricsRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: arguments.Regexes,
ExcludeRegexes: arguments.ExcludeRegexes,
Environments: arguments.Environments,
Splits: []string{"EventType"}, // We want the volume to be split by EventType so we can see the breakdown of Warning/Normal events.
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "k8s/events/metrics", 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
}
```
--------------------------------------------------------------------------------
/tools/get_traces_distribution.go:
--------------------------------------------------------------------------------
```go
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 GetTracesDistributionHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get traces distribution for. e.g. if you want to get traces distribution 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. Try to use a time period 1 hour or less unless its requested."`
Filters map[string][]string `json:"filters" jsonschema:"description=Filters to apply to the traces. Only the traces that match these filters will be returned. You have to get the possible filter keys from the get_attribute_keys tool and possible values of a filter key from the get_attribute_values tool. DO NOT GUESS THE FILTER KEYS OR VALUES. Multiple filter keys are ANDed together and values for a filter key are ORed together"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The exclude filters to exclude/eliminate the traces. Traces matching the exclude traces will not be returned. You have to get the possible exclude filter keys from the get_attribute_keys tool and possible value for the key from the get_attribute_values tool. DO NOT GUESS THE FILTER KEYS OR VALUES. Multiple keys are ORed together and values for a filter key are ANDed together"`
}
func GetTracesDistributionHandler(ctx context.Context, arguments GetTracesDistributionHandlerArgs) (*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, model.Trace, arguments.Filters, arguments.ExcludeFilters, []string{}, nil)
if err != nil {
return nil, err
}
limit := 20
request := model.GetTracesRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Limit: &limit,
}
body, err := getTracesDistributionMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting traces distribution: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getTracesDistributionMetoroCall(ctx context.Context, request model.GetTracesRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling traces distribution request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "traces/distribution", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/resources/resources.go:
--------------------------------------------------------------------------------
```go
package resources
type MetoroResource struct {
Path string
Name string
Description string
ContentType string
Handler any
}
var MetoroResourcesList = []MetoroResource{
{
Path: "api://environments",
Name: "environments",
Description: "This resource provides a list of names of the kubernetes clusters/environments monitored by Metoro",
ContentType: "text/plain",
Handler: EnvironmentResourceHandler,
},
{
Path: "api://namespaces",
Name: "namespaces",
Description: "This resource provides a list of namespaces in the kubernetes clusters/environments monitored by Metoro",
ContentType: "text/plain",
Handler: NamespacesResourceHandler,
},
{
Path: "api://services",
Name: "services",
Description: "This resource provides a list of services running in the kubernetes clusters/environments monitored by Metoro",
ContentType: "text/plain",
Handler: ServicesResourceHandler,
},
{
Path: "api://traceAttributes",
Name: "traceAttributes",
Description: "Provides a list of trace attribute keys that are available to be used for filtering or grouping traces. These trace attribute keys should be used as Filter/ExcludeFilter keys or Splits for get_traces, get_trace_metric and get_trace_attribute_values_for_individual_attribute tools arguments.",
ContentType: "text/plain",
Handler: TraceAttributesResourceHandler,
},
{
Path: "api://k8sEventAttributes",
Name: "k8sEventAttributes",
Description: "Provides a list of Kubernetes Event's attribute keys that are available to be used for filtering or grouping K8s Events. These K8s Event attribute keys should be used as Filter/ExcludeFilter keys or Splits for get_k8s_events, get_k8s_events_volume and get_k8s_events_volume tools arguments.",
ContentType: "text/plain",
Handler: K8sEventsAttributesResourceHandler,
},
{
Path: "api://metrics",
Name: "metricNames",
Description: "Provides a list of available metric names that can be used for as MetricName arguments to get_metric, get_metric_metadata and get_metric_attributes tools to get metrics data.",
ContentType: "text/plain",
Handler: MetricsResourceHandler,
},
{
Path: "api://logAttributes",
Name: "logAttributes",
Description: "Provides a list of log attribute keys that are available to be used for filtering or grouping logs. These log attribute keys should be used as Filter/ExcludeFilter keys or Splits for get_logs, get_log_attribute_values_for_individual_attribute tools arguments.",
ContentType: "text/plain",
Handler: LogAttributesResourceHandler,
},
{
Path: "api://nodes",
Name: "nodes",
Description: "Provides a list of nodes in the kubernetes clusters/environments monitored by Metoro. Any of these nodes/instances can be used as a filter/exclude for get_metric tool with the key 'kubernetes.io/hostname' and value as the node names in this resource.",
ContentType: "text/plain",
Handler: NodesResourceHandler,
},
}
```
--------------------------------------------------------------------------------
/tools/get_k8s_events.go:
--------------------------------------------------------------------------------
```go
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 GetK8sEventsHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get k8s events for. e.g. if you want to get k8s events for the last 6 hours you would set time_period=6 and time_window=Hours. You can also set an absoulute time range by setting start_time and end_time"`
Filters map[string][]string `json:"filters" jsonschema:"description=Filters to apply to the events. Only the events that match these filters will be returned. Get the possible filter keys from the get_k8s_events_attributes tool and possible filter values from the get_k8s_event_attribute_values tool (for a filter key)"`
ExcludeFilters map[string][]string `json:"exclude_filters" jsonschema:"description=Filters to exclude the events. Events matching the exclude filters will not be returned. Get the possible exclude filter keys from the get_k8s_events_attributes tool and possible exclude filter values from the get_k8s_event_attribute_values tool (for a key)"`
Regexes []string `json:"regexes" jsonschema:"description=Regexes to apply to the event messages. Only the events with messages that match these regexes will be returned. Regexes are ORed together. For example if you want to get events with messages that contain the word 'error' or 'warning' you would set the regexes as ['error' 'warning']"`
ExcludeRegexes []string `json:"exclude_regexes" jsonschema:"description=Regexes to exclude the events. Events with messages that match these regexes will not be returned. Exclude regexes are AND together. For example if you want to get events with messages that do not contain the word 'error' or 'warning' you would set the exclude regexes as ['error' 'warning']"`
Environments []string `json:"environments" jsonschema:"description=Environments/Clusters to get events for"`
}
func GetK8sEventsHandler(ctx context.Context, arguments GetK8sEventsHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetK8sEventsRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: arguments.Regexes,
ExcludeRegexes: arguments.ExcludeRegexes,
Environments: arguments.Environments,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "k8s/events", 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
}
```
--------------------------------------------------------------------------------
/tools/get_attribute_keys.go:
--------------------------------------------------------------------------------
```go
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"
"slices"
"strings"
"time"
)
type GetAttributeKeysHandlerArgs struct {
Type model.MetricType `json:"type" jsonschema:"required,description=The type of attribute keys to get. Either 'logs' or 'trace' or 'metric' or 'kubernetes_resource'"`
TimeConfig utils.TimeConfig `json:"timeConfig" jsonschema:"required,description=The time period to get the possible attribute keys. e.g. if you want to get the possible 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"`
MetricName string `json:"metricName" jsonschema:"description=The name of the metric to get the possible attribute keys for. This is required if type is 'metric'"`
}
func GetAttributeKeysHandler(ctx context.Context, arguments GetAttributeKeysHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
if arguments.Type == model.Metric {
if arguments.MetricName == "" {
return nil, fmt.Errorf("metricName is required when type is 'metric'")
}
// Check whether the metric is valid. If not, return an error.
err = CheckMetric(ctx, arguments.MetricName)
if err != nil {
return nil, err
}
}
metricAttr := model.GetMetricAttributesRequest{
StartTime: startTime,
EndTime: endTime,
MetricName: arguments.MetricName,
Environments: []string{}, // TODO: Add environments to the request if needed. For now, we are not using it as I don't think its needed.
}
request := model.MultiMetricAttributeKeysRequest{
Type: string(arguments.Type),
Metric: &metricAttr,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "metrics/attributes", 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
}
func CheckMetric(ctx context.Context, metricName string) error {
now := time.Now()
hourAgo := now.Add(-30 * time.Minute)
request := model.FuzzyMetricsRequest{
StartTime: hourAgo.Unix(),
EndTime: now.Unix(),
MetricFuzzyMatch: "", // This will return all the metric names.
}
metricNamesResp, err := getMetricNamesMetoroCall(ctx, request)
metricNames := model.GetMetricNamesResponse{}
err = json.Unmarshal(metricNamesResp, &metricNames)
if err != nil {
return fmt.Errorf("error unmarshaling response: %v", err)
}
metricNamesStr := strings.Join(metricNames.MetricNames, ", ")
if !slices.Contains(metricNames.MetricNames, metricName) {
return fmt.Errorf("metricName '%s' is not valid. Valid metric names are: %s", metricName, metricNamesStr)
}
return nil
}
```
--------------------------------------------------------------------------------
/model/model_expression_config.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the ExpressionConfig type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &ExpressionConfig{}
// ExpressionConfig struct for ExpressionConfig
type ExpressionConfig struct {
MetoroQLTimeseries *MetoroQlTimeseries `json:"metoroQLTimeseries,omitempty"`
}
// NewExpressionConfig instantiates a new ExpressionConfig object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewExpressionConfig() *ExpressionConfig {
this := ExpressionConfig{}
return &this
}
// NewExpressionConfigWithDefaults instantiates a new ExpressionConfig object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewExpressionConfigWithDefaults() *ExpressionConfig {
this := ExpressionConfig{}
return &this
}
// GetMetoroQLTimeseries returns the MetoroQLTimeseries field value if set, zero value otherwise.
func (o *ExpressionConfig) GetMetoroQLTimeseries() MetoroQlTimeseries {
if o == nil || IsNil(o.MetoroQLTimeseries) {
var ret MetoroQlTimeseries
return ret
}
return *o.MetoroQLTimeseries
}
// GetMetoroQLTimeseriesOk returns a tuple with the MetoroQLTimeseries field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ExpressionConfig) GetMetoroQLTimeseriesOk() (*MetoroQlTimeseries, bool) {
if o == nil || IsNil(o.MetoroQLTimeseries) {
return nil, false
}
return o.MetoroQLTimeseries, true
}
// HasMetoroQLTimeseries returns a boolean if a field has been set.
func (o *ExpressionConfig) HasMetoroQLTimeseries() bool {
if o != nil && !IsNil(o.MetoroQLTimeseries) {
return true
}
return false
}
// SetMetoroQLTimeseries gets a reference to the given MetoroQlTimeseries and assigns it to the MetoroQLTimeseries field.
func (o *ExpressionConfig) SetMetoroQLTimeseries(v MetoroQlTimeseries) {
o.MetoroQLTimeseries = &v
}
func (o ExpressionConfig) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o ExpressionConfig) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.MetoroQLTimeseries) {
toSerialize["metoroQLTimeseries"] = o.MetoroQLTimeseries
}
return toSerialize, nil
}
type NullableExpressionConfig struct {
value *ExpressionConfig
isSet bool
}
func (v NullableExpressionConfig) Get() *ExpressionConfig {
return v.value
}
func (v *NullableExpressionConfig) Set(val *ExpressionConfig) {
v.value = val
v.isSet = true
}
func (v NullableExpressionConfig) IsSet() bool {
return v.isSet
}
func (v *NullableExpressionConfig) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableExpressionConfig(val *ExpressionConfig) *NullableExpressionConfig {
return &NullableExpressionConfig{value: val, isSet: true}
}
func (v NullableExpressionConfig) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableExpressionConfig) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/tools/get_service_graph.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type GetServiceGraphHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the service graph for. e.g. if you want to get the graph 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"`
ServiceName string `json:"serviceName" jsonschema:"required,description=The name of the service to get the graph for"`
Environments []string `json:"environments" jsonschema:"description=The environments to get the service graph for. If empty all environments will be used."`
}
type GetServiceGraphRequest struct {
// If Environments is not empty, only services that are in the list will be included in the graph.
// If Environments is empty, all services will be included in the graph.
Environments []string `json:"environments"`
// If InitialServices is not empty, only services that are in the list will be included in the graph.
// If InitialServices is empty, all services will be included in the graph.
InitialServices []string `json:"initialServices"`
// If EndingServices is not empty, only services that are in the list will be included in the graph.
// If EndingServices is empty, all services will be included in the graph.
EndingServices []string `json:"endingServices"`
// StartTime is the start time of the graph in seconds since epoch
StartTime int64 `json:"startTime"`
// EndTime is the end time of the graph in seconds since epoch
EndTime int64 `json:"endTime"`
// The filters to apply to the traces, so for example, if you want to get traces for a specific service
// you can pass in a filter like {"service_name": ["microservice_a"]}
Filters map[string][]string `json:"filters"`
// ExcludeFilters are filters that should be excluded from the traces
// For example, if you want to get traces for all services except microservice_a you can pass in
// {"service_name": ["microservice_a"]}
ExcludeFilters map[string][]string `json:"excludeFilters"`
// Regexes are used to filter traces based on a regex inclusively
Regexes []string `json:"regexes"`
// ExcludeRegexes are used to filter traces based on a regex exclusively
ExcludeRegexes []string `json:"excludeRegexes"`
}
func GetServiceGraphHandler(ctx context.Context, arguments GetServiceGraphHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := GetServiceGraphRequest{
StartTime: startTime,
EndTime: endTime,
Environments: arguments.Environments,
InitialServices: []string{arguments.ServiceName},
EndingServices: []string{arguments.ServiceName},
}
body, err := getServiceGraphMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting service graph: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getServiceGraphMetoroCall(ctx context.Context, request GetServiceGraphRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling service graph request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "serviceGraph", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
```
--------------------------------------------------------------------------------
/model/model_timeseries_specifier_metric.go:
--------------------------------------------------------------------------------
```go
/*
Metoro Alerts API
API for managing alerts in the Metoro observability platform.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the TimeseriesSpecifierMetric type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &TimeseriesSpecifierMetric{}
// TimeseriesSpecifierMetric Configuration for a metric timeseries
type TimeseriesSpecifierMetric struct {
// Name of the metric
MetricName *string `json:"metricName,omitempty"`
}
// NewTimeseriesSpecifierMetric instantiates a new TimeseriesSpecifierMetric object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewTimeseriesSpecifierMetric() *TimeseriesSpecifierMetric {
this := TimeseriesSpecifierMetric{}
return &this
}
// NewTimeseriesSpecifierMetricWithDefaults instantiates a new TimeseriesSpecifierMetric object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewTimeseriesSpecifierMetricWithDefaults() *TimeseriesSpecifierMetric {
this := TimeseriesSpecifierMetric{}
return &this
}
// GetMetricName returns the MetricName field value if set, zero value otherwise.
func (o *TimeseriesSpecifierMetric) GetMetricName() string {
if o == nil || IsNil(o.MetricName) {
var ret string
return ret
}
return *o.MetricName
}
// GetMetricNameOk returns a tuple with the MetricName field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *TimeseriesSpecifierMetric) GetMetricNameOk() (*string, bool) {
if o == nil || IsNil(o.MetricName) {
return nil, false
}
return o.MetricName, true
}
// HasMetricName returns a boolean if a field has been set.
func (o *TimeseriesSpecifierMetric) HasMetricName() bool {
if o != nil && !IsNil(o.MetricName) {
return true
}
return false
}
// SetMetricName gets a reference to the given string and assigns it to the MetricName field.
func (o *TimeseriesSpecifierMetric) SetMetricName(v string) {
o.MetricName = &v
}
func (o TimeseriesSpecifierMetric) MarshalJSON() ([]byte, error) {
toSerialize,err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o TimeseriesSpecifierMetric) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.MetricName) {
toSerialize["metricName"] = o.MetricName
}
return toSerialize, nil
}
type NullableTimeseriesSpecifierMetric struct {
value *TimeseriesSpecifierMetric
isSet bool
}
func (v NullableTimeseriesSpecifierMetric) Get() *TimeseriesSpecifierMetric {
return v.value
}
func (v *NullableTimeseriesSpecifierMetric) Set(val *TimeseriesSpecifierMetric) {
v.value = val
v.isSet = true
}
func (v NullableTimeseriesSpecifierMetric) IsSet() bool {
return v.isSet
}
func (v *NullableTimeseriesSpecifierMetric) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimeseriesSpecifierMetric(val *TimeseriesSpecifierMetric) *NullableTimeseriesSpecifierMetric {
return &NullableTimeseriesSpecifierMetric{value: val, isSet: true}
}
func (v NullableTimeseriesSpecifierMetric) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimeseriesSpecifierMetric) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/utils/time_utils.go:
--------------------------------------------------------------------------------
```go
package utils
import (
"fmt"
"os"
"strings"
"time"
)
// TimeWindow represents supported time window units
type TimeWindow string
const (
Minutes TimeWindow = "Minutes"
Hours TimeWindow = "Hours"
Days TimeWindow = "Days"
)
// TimeRangeType indicates whether the time range is relative or absolute
type TimeRangeType string
const (
RelativeTimeRange TimeRangeType = "relative"
AbsoluteTimeRange TimeRangeType = "absolute"
)
// TimeConfig holds the configuration for time range calculation
type TimeConfig struct {
// Type of time range (relative or absolute)
Type TimeRangeType `json:"type" jsonschema:"required,enum=relative,enum=absolute,description=Type of time range. Must be either 'relative' or 'absolute'"`
// Fields for relative time range
TimePeriod *int `json:"time_period,omitempty" jsonschema:"description=For relative time range: the number of time units to look back"`
TimeWindow *TimeWindow `json:"time_window,omitempty" jsonschema:"description=For relative time range: the unit of time (Minutes, Hours, Days)"`
// Fields for absolute time range
StartTime *string `json:"start_time,omitempty" jsonschema:"description=For absolute time range: start time in RFC3339 format (e.g., '2024-12-12T14:27:22Z')"`
EndTime *string `json:"end_time,omitempty" jsonschema:"description=For absolute time range: end time in RFC3339 format (e.g., '2024-12-12T14:27:22Z')"`
}
// CalculateTimeRange returns start and end timestamps based on the time configuration
func CalculateTimeRange(config TimeConfig) (startTime, endTime int64, err error) {
now := time.Now()
thirtyDaysAgo := now.Add(-30 * 24 * time.Hour)
switch config.Type {
case RelativeTimeRange:
if config.TimePeriod == nil || config.TimeWindow == nil {
return 0, 0, fmt.Errorf("time_period and time_window are required for relative time range")
}
var duration time.Duration
window := strings.ToLower(string(*config.TimeWindow))
switch window {
case "minutes", "minute", "min", "mins":
duration = time.Duration(*config.TimePeriod) * time.Minute
case "hours", "hour", "hr", "hrs":
duration = time.Duration(*config.TimePeriod) * time.Hour
case "days", "day":
duration = time.Duration(*config.TimePeriod) * 24 * time.Hour
default:
return 0, 0, fmt.Errorf("invalid time window: %s", *config.TimeWindow)
}
startTimeObj := now.Add(-duration)
// Check if the start time is more than 30 days ago in Prod.
if os.Getenv("IS_PROD") == "true" && startTimeObj.Before(thirtyDaysAgo) {
return 0, 0, fmt.Errorf("time range cannot exceed 30 days ago, please adjust the time_period or time_window")
}
return startTimeObj.Unix(), now.Unix(), nil
case AbsoluteTimeRange:
if config.StartTime == nil || config.EndTime == nil {
return 0, 0, fmt.Errorf("start_time and end_time are required for absolute time range")
}
startTimeObj, err := time.Parse(time.RFC3339, *config.StartTime)
if err != nil {
return 0, 0, fmt.Errorf("invalid start_time format: %v", err)
}
endTimeObj, err := time.Parse(time.RFC3339, *config.EndTime)
if err != nil {
return 0, 0, fmt.Errorf("invalid end_time format: %v", err)
}
if endTimeObj.Before(startTimeObj) {
return 0, 0, fmt.Errorf("end_time cannot be before start_time")
}
// Check if the start time is more than 30 days ago
if os.Getenv("IS_PROD") == "true" && startTimeObj.Before(thirtyDaysAgo) {
return 0, 0, fmt.Errorf("time range cannot exceed 30 days")
}
return startTimeObj.Unix(), endTimeObj.Unix(), nil
default:
return 0, 0, fmt.Errorf("invalid time range type: %s", config.Type)
}
}
```
--------------------------------------------------------------------------------
/tools/get_log_attribute_values.go:
--------------------------------------------------------------------------------
```go
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 GetLogAttributeValuesHandlerArgs struct {
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"`
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 attribute key service.name where the environment is X you would set the Filters as {environment: [X]}"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The exclude filters to exclude/eliminate possible values an attribute can take. Log attributes matching the exclude filters will not be returned. For example if you want the possible values for attribute key service.name where the attribute environment is not X then you would set the ExcludeFilters as {environment: [X]}"`
Regexes []string `json:"regexes" jsonschema:"description=The regexes to apply to the log messages. Only the attribute values (for a given attribute key) of logs messages that match these regexes will be returned. For example if you want the possible values for attribute key service.name where the log message contains the word 'error' you would set the regexes as ['error']"`
ExcludeRegexes []string `json:"excludeRegexes" jsonschema:"description=The exclude regexes to apply to the log messages. The attribute values (for a given attribute key) of log messages that match these regexes will not be returned. For example if you want the possible values for attribute key service.name where the log message does not contain the word 'error' you would set the exclude regexes as ['error']"`
Environments []string `json:"environments" jsonschema:"description=The environments to get possible values of a log attributes for. If empty, possible values from all environments will be returned"`
}
func GetLogAttributeValuesForIndividualAttributeHandler(ctx context.Context, arguments GetLogAttributeValuesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetSingleLogSummaryRequest{
LogSummaryRequest: model.LogSummaryRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: arguments.Regexes,
ExcludeRegexes: arguments.ExcludeRegexes,
Environments: arguments.Environments,
},
Attribute: arguments.Attribute,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "logsSummaryIndividualAttribute", 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
}
```
--------------------------------------------------------------------------------
/tools/get_trace_attribute_values.go:
--------------------------------------------------------------------------------
```go
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 GetTraceAttributeValuesHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to use for getting the possible values for a trace attribute key. e.g. if you want to get possible trace attribute values for key x 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 name of the attribute key to get the possible values for"`
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 attribute key service.name where the environment is X you would set the Filters as {environment: [X]}"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The exclude filters to exclude/eliminate possible values an attribute can take. Traces matching the exclude filters will not be returned. For example if you want the possible values for attribute key service.name where the attribute environment is not X then you would set the ExcludeFilters as {environment: [X]}"`
Regexes []string `json:"regexes" jsonschema:"description=The regexes to apply to the trace endpoint. Only the attribute values (for a given attribute key) of trace endpoint that match these regexes will be returned. For example if you want the possible values for attribute key service.name where the trace endpoint contains the word 'get' you would set the regexes as ['get']"`
ExcludeRegexes []string `json:"excludeRegexes" jsonschema:"description=The exclude regexes to apply to the trace endpoint. The attribute values (for a given attribute key) of trace endpoint that match these regexes will not be returned. For example if you want the possible values for attribute key service.name where the trace endpoint does not contain the word 'get' you would set the exclude regexes as ['get']"`
Environments []string `json:"environments" jsonschema:"description=The environments to get traces from. If empty traces from all environments will be returned"`
}
func GetTraceAttributeValuesForIndividualAttributeHandler(ctx context.Context, arguments GetTraceAttributeValuesHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetSingleTraceSummaryRequest{
TracesSummaryRequest: model.TracesSummaryRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: arguments.Regexes,
ExcludeRegexes: arguments.ExcludeRegexes,
Environments: arguments.Environments,
},
Attribute: arguments.Attribute,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "tracesSummaryIndividualAttribute", 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
}
```
--------------------------------------------------------------------------------
/tools/update_investigation.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type UpdateInvestigationHandlerArgs struct {
InvestigationUUID string `json:"investigationUuid" jsonschema:"required,description=UUID of the investigation to update"`
Title string `json:"title" jsonschema:"required,description=Title of the investigation"`
Summary string `json:"summary" jsonschema:"description=Summary of the investigation - should be at most 3 sentences"`
RecommendedActions *[]string `json:"recommendedActions,omitempty" jsonschema:"description=Optional recommended actions to take to remedy the issue. Should be concise - each item should be a single sentence."`
ServiceName *string `json:"serviceName,omitempty" jsonschema:"description=Optional root cause service name to associate with this investigation."`
Markdown string `json:"markdown" jsonschema:"required,description=Markdown content of the investigation"`
InProgress *bool `json:"inProgress" jsonschema:"description=Whether the investigation is in progress or not. Defaults to false"`
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the pods for. e.g. if you want the get the pods for the last 5 minutes you would set time_period=5 and time_window=Minutes. You can also set an absolute time range by setting start_time and end_time"`
ChatHistoryUUID *string `json:"chatHistoryUuid,omitempty" jsonschema:"description=Optional chat history UUID to associate with this investigation"`
IssueUUID *string `json:"issueUuid,omitempty" jsonschema:"description=Optional related AI issue UUID for this investigation"`
}
func UpdateInvestigationHandler(ctx context.Context, arguments UpdateInvestigationHandlerArgs) (*mcpgolang.ToolResponse, error) {
// Create the request body
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
falsePtr := false
reviewRequiredPtr := "ReviewRequired"
start := time.Unix(startTime, 0)
end := time.Unix(endTime, 0)
tags := make(map[string]string)
if arguments.ServiceName != nil {
tags["service"] = *arguments.ServiceName
}
title := arguments.Title
summary := arguments.Summary
markdown := arguments.Markdown
tagsPtr := tags
request := model.UpdateInvestigationRequest{
Title: &title,
Summary: &summary,
Markdown: &markdown,
Tags: &tagsPtr,
IssueStartTime: &start,
IssueEndTime: &end,
ChatHistoryUUID: arguments.ChatHistoryUUID,
IsVisible: &falsePtr,
InProgress: arguments.InProgress,
MetoroApprovalStatus: &reviewRequiredPtr,
IssueUUID: arguments.IssueUUID,
RecommendedActions: arguments.RecommendedActions,
}
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
// Make the API request - using PUT method for update
endpoint := fmt.Sprintf("investigation?uuid=%s", arguments.InvestigationUUID)
responseBody, err := utils.MakeMetoroAPIRequest("PUT", endpoint, bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to update investigation: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(responseBody))), nil
}
```
--------------------------------------------------------------------------------
/tools/create_investigation.go:
--------------------------------------------------------------------------------
```go
package tools
import (
"bytes"
"context"
"encoding/json"
"fmt"
"time"
mcpgolang "github.com/metoro-io/mcp-golang"
"github.com/metoro-io/metoro-mcp-server/model"
"github.com/metoro-io/metoro-mcp-server/utils"
)
type CreateInvestigationHandlerArgs struct {
Title string `json:"title" jsonschema:"required,description=Title of the investigation"`
Summary string `json:"summary" jsonschema:"description=Summary of the investigation - should be at most 3 sentences"`
RecommendedActions *[]string `json:"recommendedActions,omitempty" jsonschema:"description=Optional recommended actions to take to remedy the issue. Should be concise - each item should be a single sentence."`
ServiceName *string `json:"serviceName,omitempty" jsonschema:"description=Optional root cause service name to associate with this investigation."`
Markdown string `json:"markdown" jsonschema:"required,description=Markdown content of the investigation"`
InProgress *bool `json:"inProgress" jsonschema:"description=Whether the investigation is in progress or not. Defaults to false"`
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the pods for. e.g. if you want the get the pods for the last 5 minutes you would set time_period=5 and time_window=Minutes. You can also set an absolute time range by setting start_time and end_time"`
ChatHistoryUUID *string `json:"chatHistoryUuid,omitempty" jsonschema:"description=Optional chat history UUID to associate with this investigation"`
IssueUUID *string `json:"issueUuid,omitempty" jsonschema:"description=Optional related AI issue UUID for this investigation"`
AlertFireUUID *string `json:"alertFireUuid,omitempty" jsonschema:"description=Optional alert fire UUID to associate with this investigation"`
AlertUUID *string `json:"alertUuid,omitempty" jsonschema:"description=Optional alert UUID to associate with this investigation"`
}
func CreateInvestigationHandler(ctx context.Context, arguments CreateInvestigationHandlerArgs) (*mcpgolang.ToolResponse, error) {
// Create the request body
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
falsePtr := false
reviewRequiredPtr := "ReviewRequired"
start := time.Unix(startTime, 0)
end := time.Unix(endTime, 0)
tags := make(map[string]string)
if arguments.ServiceName != nil {
tags["service"] = *arguments.ServiceName
}
request := model.CreateInvestigationRequest{
Title: arguments.Title,
Summary: arguments.Summary,
RecommendedActions: arguments.RecommendedActions,
Markdown: arguments.Markdown,
Tags: tags,
IssueStartTime: &start,
IssueEndTime: &end,
ChatHistoryUUID: arguments.ChatHistoryUUID,
IsVisible: &falsePtr,
InProgress: arguments.InProgress,
MetoroApprovalStatus: &reviewRequiredPtr,
IssueUUID: arguments.IssueUUID,
AlertFireUUID: arguments.AlertFireUUID,
AlertUUID: arguments.AlertUUID,
}
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
// Make the API request
responseBody, err := utils.MakeMetoroAPIRequest("POST", "investigation", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("failed to create investigation: %w", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(responseBody))), nil
}
```
--------------------------------------------------------------------------------
/tools/get_k8s_event_attribute_values.go:
--------------------------------------------------------------------------------
```go
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 GetK8sEventAttributeValueHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the possible values of K8 event attributes values. e.g. if you want to see the possible values for the attributes in 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"`
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 attribute key service.name where the environment is X you would set the Filters as {environment: [X]}"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The exclude filters to exclude/eliminate possible values an attribute can take. Events matching the exclude filters will not be returned. For example if you want the possible values for attribute key service.name where the attribute environment is not X then you would set the ExcludeFilters as {environment: [X]}"`
Regexes []string `json:"regexes" jsonschema:"description=The regexes to apply to the event messages. Only the attribute values (for a given attribute key) of events messages that match these regexes will be returned. For example if you want the possible values for attribute key service.name where the event message contains the word 'error' you would set the regexes as ['error']"`
ExcludeRegexes []string `json:"excludeRegexes" jsonschema:"description=The exclude regexes to apply to the event messages. The attribute values (for a given attribute key) of events messages that match these regexes will not be returned. For example if you want the possible values for attribute key service.name where the event message does not contain the word 'error' you would set the exclude regexes as ['error']"`
Environments []string `json:"environments" jsonschema:"description=The environments to get events from. If empty events from all environments will be returned"`
Ascending bool `json:"ascending" jsonschema:"description=If true events will be returned in ascending order otherwise in descending order"`
}
func GetK8sEventAttributeValuesForIndividualAttributeHandler(ctx context.Context, arguments GetK8sEventAttributeValueHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetSingleK8sEventSummaryRequest{
GetK8sEventsRequest: model.GetK8sEventsRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: arguments.Regexes,
ExcludeRegexes: arguments.ExcludeRegexes,
Environments: arguments.Environments,
Ascending: arguments.Ascending,
},
Attribute: arguments.Attribute,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "k8s/events/summaryIndividualAttribute", 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
}
```
--------------------------------------------------------------------------------
/tools/get_attribute_values.go:
--------------------------------------------------------------------------------
```go
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)
}
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
}
```
--------------------------------------------------------------------------------
/model/model_timeseries_specifier_kubernetes_resource.go:
--------------------------------------------------------------------------------
```go
/*
Metoro Alerts API
API for managing alerts in the Metoro observability platform.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the TimeseriesSpecifierKubernetesResource type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &TimeseriesSpecifierKubernetesResource{}
// TimeseriesSpecifierKubernetesResource Configuration for a Kubernetes resource timeseries
type TimeseriesSpecifierKubernetesResource struct {
// JSONPath expression to extract data from Kubernetes resources
JsonPath *string `json:"jsonPath,omitempty"`
}
// NewTimeseriesSpecifierKubernetesResource instantiates a new TimeseriesSpecifierKubernetesResource object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewTimeseriesSpecifierKubernetesResource() *TimeseriesSpecifierKubernetesResource {
this := TimeseriesSpecifierKubernetesResource{}
return &this
}
// NewTimeseriesSpecifierKubernetesResourceWithDefaults instantiates a new TimeseriesSpecifierKubernetesResource object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewTimeseriesSpecifierKubernetesResourceWithDefaults() *TimeseriesSpecifierKubernetesResource {
this := TimeseriesSpecifierKubernetesResource{}
return &this
}
// GetJsonPath returns the JsonPath field value if set, zero value otherwise.
func (o *TimeseriesSpecifierKubernetesResource) GetJsonPath() string {
if o == nil || IsNil(o.JsonPath) {
var ret string
return ret
}
return *o.JsonPath
}
// GetJsonPathOk returns a tuple with the JsonPath field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *TimeseriesSpecifierKubernetesResource) GetJsonPathOk() (*string, bool) {
if o == nil || IsNil(o.JsonPath) {
return nil, false
}
return o.JsonPath, true
}
// HasJsonPath returns a boolean if a field has been set.
func (o *TimeseriesSpecifierKubernetesResource) HasJsonPath() bool {
if o != nil && !IsNil(o.JsonPath) {
return true
}
return false
}
// SetJsonPath gets a reference to the given string and assigns it to the JsonPath field.
func (o *TimeseriesSpecifierKubernetesResource) SetJsonPath(v string) {
o.JsonPath = &v
}
func (o TimeseriesSpecifierKubernetesResource) MarshalJSON() ([]byte, error) {
toSerialize,err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o TimeseriesSpecifierKubernetesResource) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.JsonPath) {
toSerialize["jsonPath"] = o.JsonPath
}
return toSerialize, nil
}
type NullableTimeseriesSpecifierKubernetesResource struct {
value *TimeseriesSpecifierKubernetesResource
isSet bool
}
func (v NullableTimeseriesSpecifierKubernetesResource) Get() *TimeseriesSpecifierKubernetesResource {
return v.value
}
func (v *NullableTimeseriesSpecifierKubernetesResource) Set(val *TimeseriesSpecifierKubernetesResource) {
v.value = val
v.isSet = true
}
func (v NullableTimeseriesSpecifierKubernetesResource) IsSet() bool {
return v.isSet
}
func (v *NullableTimeseriesSpecifierKubernetesResource) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimeseriesSpecifierKubernetesResource(val *TimeseriesSpecifierKubernetesResource) *NullableTimeseriesSpecifierKubernetesResource {
return &NullableTimeseriesSpecifierKubernetesResource{value: val, isSet: true}
}
func (v NullableTimeseriesSpecifierKubernetesResource) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimeseriesSpecifierKubernetesResource) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_timeseries_config_expression.go:
--------------------------------------------------------------------------------
```go
/*
Metoro Alerts API
API for managing alerts in the Metoro observability platform.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
"fmt"
"gopkg.in/validator.v2"
)
// TimeseriesConfigExpression - Expression defining the metrics to monitor
type TimeseriesConfigExpression struct {
ExpressionConfig *ExpressionConfig
String *string
}
// ExpressionConfigAsTimeseriesConfigExpression is a convenience function that returns ExpressionConfig wrapped in TimeseriesConfigExpression
func ExpressionConfigAsTimeseriesConfigExpression(v *ExpressionConfig) TimeseriesConfigExpression {
return TimeseriesConfigExpression{
ExpressionConfig: v,
}
}
// stringAsTimeseriesConfigExpression is a convenience function that returns string wrapped in TimeseriesConfigExpression
func StringAsTimeseriesConfigExpression(v *string) TimeseriesConfigExpression {
return TimeseriesConfigExpression{
String: v,
}
}
// Unmarshal JSON data into one of the pointers in the struct
func (dst *TimeseriesConfigExpression) UnmarshalJSON(data []byte) error {
var err error
match := 0
// try to unmarshal data into ExpressionConfig
err = newStrictDecoder(data).Decode(&dst.ExpressionConfig)
if err == nil {
jsonExpressionConfig, _ := json.Marshal(dst.ExpressionConfig)
if string(jsonExpressionConfig) == "{}" { // empty struct
dst.ExpressionConfig = nil
} else {
if err = validator.Validate(dst.ExpressionConfig); err != nil {
dst.ExpressionConfig = nil
} else {
match++
}
}
} else {
dst.ExpressionConfig = nil
}
// try to unmarshal data into String
err = newStrictDecoder(data).Decode(&dst.String)
if err == nil {
jsonString, _ := json.Marshal(dst.String)
if string(jsonString) == "{}" { // empty struct
dst.String = nil
} else {
if err = validator.Validate(dst.String); err != nil {
dst.String = nil
} else {
match++
}
}
} else {
dst.String = nil
}
if match > 1 { // more than 1 match
// reset to nil
dst.ExpressionConfig = nil
dst.String = nil
return fmt.Errorf("data matches more than one schema in oneOf(TimeseriesConfigExpression)")
} else if match == 1 {
return nil // exactly one match
} else { // no match
return fmt.Errorf("data failed to match schemas in oneOf(TimeseriesConfigExpression)")
}
}
// Marshal data from the first non-nil pointers in the struct to JSON
func (src TimeseriesConfigExpression) MarshalJSON() ([]byte, error) {
if src.ExpressionConfig != nil {
return json.Marshal(&src.ExpressionConfig)
}
if src.String != nil {
return json.Marshal(&src.String)
}
return nil, nil // no data in oneOf schemas
}
// Get the actual instance
func (obj *TimeseriesConfigExpression) GetActualInstance() (interface{}) {
if obj == nil {
return nil
}
if obj.ExpressionConfig != nil {
return obj.ExpressionConfig
}
if obj.String != nil {
return obj.String
}
// all schemas are nil
return nil
}
// Get the actual instance value
func (obj TimeseriesConfigExpression) GetActualInstanceValue() (interface{}) {
if obj.ExpressionConfig != nil {
return *obj.ExpressionConfig
}
if obj.String != nil {
return *obj.String
}
// all schemas are nil
return nil
}
type NullableTimeseriesConfigExpression struct {
value *TimeseriesConfigExpression
isSet bool
}
func (v NullableTimeseriesConfigExpression) Get() *TimeseriesConfigExpression {
return v.value
}
func (v *NullableTimeseriesConfigExpression) Set(val *TimeseriesConfigExpression) {
v.value = val
v.isSet = true
}
func (v NullableTimeseriesConfigExpression) IsSet() bool {
return v.isSet
}
func (v *NullableTimeseriesConfigExpression) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimeseriesConfigExpression(val *TimeseriesConfigExpression) *NullableTimeseriesConfigExpression {
return &NullableTimeseriesConfigExpression{value: val, isSet: true}
}
func (v NullableTimeseriesConfigExpression) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimeseriesConfigExpression) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_create_update_alert_request.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"bytes"
"encoding/json"
"fmt"
)
// checks if the CreateUpdateAlertRequest type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &CreateUpdateAlertRequest{}
// CreateUpdateAlertRequest Request to create a new alert or update an existing one. If alert.metadata.id is provided and matches an existing alert, that alert will be updated.
type CreateUpdateAlertRequest struct {
Alert Alert `json:"alert"`
}
type _CreateUpdateAlertRequest CreateUpdateAlertRequest
// NewCreateUpdateAlertRequest instantiates a new CreateUpdateAlertRequest object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewCreateUpdateAlertRequest(alert Alert) *CreateUpdateAlertRequest {
this := CreateUpdateAlertRequest{}
this.Alert = alert
return &this
}
// NewCreateUpdateAlertRequestWithDefaults instantiates a new CreateUpdateAlertRequest object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewCreateUpdateAlertRequestWithDefaults() *CreateUpdateAlertRequest {
this := CreateUpdateAlertRequest{}
return &this
}
// GetAlert returns the Alert field value
func (o *CreateUpdateAlertRequest) GetAlert() Alert {
if o == nil {
var ret Alert
return ret
}
return o.Alert
}
// GetAlertOk returns a tuple with the Alert field value
// and a boolean to check if the value has been set.
func (o *CreateUpdateAlertRequest) GetAlertOk() (*Alert, bool) {
if o == nil {
return nil, false
}
return &o.Alert, true
}
// SetAlert sets field value
func (o *CreateUpdateAlertRequest) SetAlert(v Alert) {
o.Alert = v
}
func (o CreateUpdateAlertRequest) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o CreateUpdateAlertRequest) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["alert"] = o.Alert
return toSerialize, nil
}
func (o *CreateUpdateAlertRequest) UnmarshalJSON(data []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
requiredProperties := []string{
"alert",
}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
if err != nil {
return err
}
for _, requiredProperty := range requiredProperties {
if _, exists := allProperties[requiredProperty]; !exists {
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
varCreateUpdateAlertRequest := _CreateUpdateAlertRequest{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varCreateUpdateAlertRequest)
if err != nil {
return err
}
*o = CreateUpdateAlertRequest(varCreateUpdateAlertRequest)
return err
}
type NullableCreateUpdateAlertRequest struct {
value *CreateUpdateAlertRequest
isSet bool
}
func (v NullableCreateUpdateAlertRequest) Get() *CreateUpdateAlertRequest {
return v.value
}
func (v *NullableCreateUpdateAlertRequest) Set(val *CreateUpdateAlertRequest) {
v.value = val
v.isSet = true
}
func (v NullableCreateUpdateAlertRequest) IsSet() bool {
return v.isSet
}
func (v *NullableCreateUpdateAlertRequest) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableCreateUpdateAlertRequest(val *CreateUpdateAlertRequest) *NullableCreateUpdateAlertRequest {
return &NullableCreateUpdateAlertRequest{value: val, isSet: true}
}
func (v NullableCreateUpdateAlertRequest) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableCreateUpdateAlertRequest) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/tools/get_traces.go:
--------------------------------------------------------------------------------
```go
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 GetTracesHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get traces for. e.g. if you want to get traces 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. Try to use a time period 1 hour or less unless its requested."`
Filters map[string][]string `json:"filters" jsonschema:"description=Filters to apply to the traces. Only the traces that match these filters will be returned. You have to get the possible filter keys from the get_attribute_keys tool and possible values of a filter key from the get_attribute_values tool. DO NOT GUESS THE FILTER KEYS OR VALUES. Multiple filter keys are ANDed together and values for a filter key are ORed together"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The exclude filters to exclude/eliminate the traces. Traces matching the exclude traces will not be returned. You have to get the possible exclude filter keys from the get_attribute_keys tool and possible value for the key from the get_attribute_values tool. DO NOT GUESS THE FILTER KEYS OR VALUES. Multiple keys are ORed together and values for a filter key are ANDed together"`
}
func GetTracesHandler(ctx context.Context, arguments GetTracesHandlerArgs) (*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, model.Trace, arguments.Filters, arguments.ExcludeFilters, []string{}, nil)
if err != nil {
return nil, err
}
limit := 20
request := model.GetTracesRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Limit: &limit,
}
body, err := getTracesMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting traces: %v", err)
}
// Add human readable duration to the response
bodyWithDuration, err := addHumanReadableDuration(body)
if err != nil {
return nil, fmt.Errorf("error adding human readable duration: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(bodyWithDuration)))), nil
}
func getTracesMetoroCall(ctx context.Context, request model.GetTracesRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling traces request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "traces", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
func addHumanReadableDuration(response []byte) ([]byte, error) {
var tracesResponse model.GetTracesResponse
err := json.Unmarshal(response, &tracesResponse)
if err != nil {
return nil, fmt.Errorf("error unmarshaling get traces response: %v", err)
}
// Add human readable duration to each trace
for i := range tracesResponse.Traces {
trace := &tracesResponse.Traces[i]
durationNs := trace.Duration
// Convert duration to human readable format
var humanReadable string
switch {
case durationNs < 1000: // Less than 1 microsecond
humanReadable = fmt.Sprintf("%d nanoseconds", durationNs)
case durationNs < 1000000: // Less than 1 millisecond
humanReadable = fmt.Sprintf("%.2f microseconds", float64(durationNs)/1000)
case durationNs < 1000000000: // Less than 1 second
humanReadable = fmt.Sprintf("%.2f milliseconds", float64(durationNs)/1000000)
case durationNs < 60000000000: // Less than 1 minute
humanReadable = fmt.Sprintf("%.2f seconds", float64(durationNs)/1000000000)
default: // 1 minute or more
minutes := durationNs / 60000000000
seconds := (durationNs % 60000000000) / 1000000000
humanReadable = fmt.Sprintf("%d minutes %.2f seconds", minutes, float64(seconds))
}
// Add human readable duration to span attributes
trace.DurationReadable = humanReadable
}
return json.Marshal(tracesResponse)
}
```
--------------------------------------------------------------------------------
/tools/get_version_for_service.go:
--------------------------------------------------------------------------------
```go
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"
"gopkg.in/yaml.v3"
)
type GetVersionForServiceHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time to get container versions. e.g. if you want to see the versions 5 minutes ago you would set time_period=5 and time_window=Minutes. You can also set an absolute time range by setting start_time and end_time"`
ServiceName string `json:"serviceName" jsonschema:"required,description=The name of the service to get container versions for."`
Environments []string `json:"environments" jsonschema:"description=The environments to get service versions for. If empty all environments will be used."`
}
type GetVersionForServiceResponse struct {
ContainerVersions map[string]map[string]string `json:"container_versions"`
}
type K8sResourceSummaryResponse struct {
K8sResourceSummary []struct {
Environment string `json:"environment"`
Kind string `json:"kind"`
ResourceYaml string `json:"resourceYaml"`
} `json:"k8sResourceSummary"`
}
func GetVersionForServiceHandler(ctx context.Context, arguments GetVersionForServiceHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetPodsRequest{
StartTime: startTime,
EndTime: endTime,
ServiceName: arguments.ServiceName,
Environments: arguments.Environments,
}
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "k8s/summary", bytes.NewBuffer(jsonBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("error making Metoro call: %v", err)
}
// Parse the JSON response
var summaryResponse K8sResourceSummaryResponse
err = json.Unmarshal(resp, &summaryResponse)
if err != nil {
return nil, fmt.Errorf("error parsing JSON response: %v", err)
}
// Extract container versions from each environment
containerVersions := make(map[string]map[string]string)
for _, resource := range summaryResponse.K8sResourceSummary {
// Parse the YAML for each resource
var yamlData map[string]interface{}
err = yaml.Unmarshal([]byte(resource.ResourceYaml), &yamlData)
if err != nil {
continue // Skip if we can't parse this resource
}
// Extract containers for this environment
envContainers := make(map[string]string)
// Check for spec.template.spec.containers (Deployment/StatefulSet)
if spec, ok := yamlData["spec"].(map[string]interface{}); ok {
if template, ok := spec["template"].(map[string]interface{}); ok {
if templateSpec, ok := template["spec"].(map[string]interface{}); ok {
extractContainers(templateSpec, envContainers)
}
}
// Also check spec.containers directly (DaemonSet)
extractContainers(spec, envContainers)
}
if len(envContainers) > 0 {
containerVersions[resource.Environment] = envContainers
}
}
response := GetVersionForServiceResponse{
ContainerVersions: containerVersions,
}
jsonResponse, err := json.Marshal(response)
if err != nil {
return nil, fmt.Errorf("error marshaling response: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(string(jsonResponse))), nil
}
func extractContainers(spec map[string]interface{}, containerVersions map[string]string) {
if containers, ok := spec["containers"].([]interface{}); ok {
for _, container := range containers {
if containerMap, ok := container.(map[string]interface{}); ok {
containerName, nameOk := containerMap["name"].(string)
image, imageOk := containerMap["image"].(string)
if nameOk && imageOk {
containerVersions[containerName] = image
}
}
}
}
// Also check for init containers
if initContainers, ok := spec["initContainers"].([]interface{}); ok {
for _, container := range initContainers {
if containerMap, ok := container.(map[string]interface{}); ok {
containerName, nameOk := containerMap["name"].(string)
image, imageOk := containerMap["image"].(string)
if nameOk && imageOk {
containerVersions["init-"+containerName] = image
}
}
}
}
}
```
--------------------------------------------------------------------------------
/tools/get_trace_metric.go:
--------------------------------------------------------------------------------
```go
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 GetTraceMetricHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the trace timeseries data for. e.g. if you want to get the trace timeseries data 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"`
ServiceNames []string `json:"serviceNames" jsonschema:"description=Service names to return the trace timeseries data for"`
Filters map[string][]string `json:"filters" jsonschema:"description=The filters to apply to the traces. it is a map of filter keys to array values where array values are ORed.e.g. key for service name is service.name"`
ExcludeFilters map[string][]string `json:"excludeFilters" jsonschema:"description=The exclude filters to exclude/eliminate the traces. Traces matching the exclude traces will not be returned. it is a map of filter keys to array values where array values are ORed.e.g. key for service name is service.name"`
Regexes []string `json:"regexes" jsonschema:"description=The regexes to apply to the trace's endpoints. Traces with endpoints matching regexes will be returned"`
ExcludeRegexes []string `json:"excludeRegexes" jsonschema:"description=The regexes to exclude from the trace's endpoints. Traces with endpoints matching regexes will be excluded"`
Splits []string `json:"splits" jsonschema:"description=The splits to apply to trace timeseries data. e.g. if you want to split the trace timeseries data by service name you would set splits as ['service.name']. This is useful for seeing a breakdown of the trace timeseries data by an attribute"`
Functions []model.MetricFunction `json:"functions" jsonschema:"description=The functions to apply to the traces. Available functions are monotonicDifference which will calculate the difference between the current and previous value of the metric (negative values will be set to 0) and valueDifference which will calculate the difference between the current and previous value of the metric or MathExpression e.g. a / 60"`
Aggregate string `json:"aggregate" jsonschema:"required,description=The aggregation to apply to the metrics. Possible values are: count / p50 / p90 / p95 / p99 / totalSize / responseSize / requestSize. The aggregation will be applied to every datapoint bucket. For example if the bucket size is 1 minute and the aggregation is count then the count of all datapoints in a minute will be returned"`
Environments []string `json:"environments" jsonschema:"description=The environments to get traces from. If empty traces from all environments will be returned"`
}
func GetTraceMetricHandler(ctx context.Context, arguments GetTraceMetricHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
request := model.GetTraceMetricRequest{
StartTime: startTime,
EndTime: endTime,
ServiceNames: arguments.ServiceNames,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: arguments.Regexes,
ExcludeRegexes: arguments.ExcludeRegexes,
Splits: arguments.Splits,
Functions: arguments.Functions,
Aggregate: model.Aggregation(arguments.Aggregate),
Environments: arguments.Environments,
}
body, err := getTraceMetricMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting trace metric: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(body)))), nil
}
func getTraceMetricMetoroCall(ctx context.Context, request model.GetTraceMetricRequest) ([]byte, error) {
jsonBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling request: %v", err)
}
resp, err := utils.MakeMetoroAPIRequest("POST", "traceMetric", bytes.NewBuffer(jsonBody), utils.GetAPIRequirementsFromRequest(ctx))
if err != nil {
return nil, fmt.Errorf("error making Metoro call: %v", err)
}
return resp, nil
}
```
--------------------------------------------------------------------------------
/tools/get_logs.go:
--------------------------------------------------------------------------------
```go
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 GetLogsHandlerArgs struct {
TimeConfig utils.TimeConfig `json:"time_config" jsonschema:"required,description=The time period to get the logs for. e.g. if you want the get the logs 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"`
Filters map[string][]string `json:"attributeFilters" jsonschema:"description=You must use get_attribute_keys and get_attribute_values before setting this. Log attributes to restrict the search to. Keys are anded together and values in the keys are ORed. e.g. {service.name: [/k8s/test/test /k8s/test/test2] namespace:[test]} will return all logs emited from (service.name = /k8s/test/test OR /k8s/test/test2) AND (namespace = test). Get the possible filter keys from the get_attribute_keys tool and possible values of a filter key from the get_attribute_values tool. If you are looking to get logs of a certain severity you should look up the log_level filter."`
ExcludeFilters map[string][]string `json:"attributeExcludeFilters" jsonschema:"description=You must use get_attribute_keys and get_attribute_values before setting this.Log attributes to exclude from the search. Keys are anded together and values in the keys are ORed. e.g. {service.name: [/k8s/test/test /k8s/test/test2] namespace:[test]} will return all logs emited from NOT ((service.name = /k8s/test/test OR /k8s/test/test2) AND (namespace = test)). Get the possible filter keys from the get_attribute_keys tool and possible values of a filter key from the get_attribute_values tool. If you are looking to get logs of a certain severity you should look up the log_level filter."`
Regex string `json:"regex" jsonschema:"description=Regex to apply to the log search re2 format. Any match in the log message will cause it to be returned. Use the filters parameter log_level if you want to look for logs of a certain severity"`
Environments []string `json:"environments" jsonschema:"description=The environments to get logs from. If empty logs from all environments will be returned"`
}
func GetLogsHandler(ctx context.Context, arguments GetLogsHandlerArgs) (*mcpgolang.ToolResponse, error) {
startTime, endTime, err := utils.CalculateTimeRange(arguments.TimeConfig)
if err != nil {
return nil, fmt.Errorf("error calculating time range: %v", err)
}
var regexes = []string{}
if arguments.Regex != "" {
regexes = append(regexes, arguments.Regex)
}
err = CheckAttributes(ctx, model.Logs, arguments.Filters, arguments.ExcludeFilters, []string{}, nil)
if err != nil {
return nil, err
}
limit := 20
request := model.GetLogsRequest{
StartTime: startTime,
EndTime: endTime,
Filters: arguments.Filters,
ExcludeFilters: arguments.ExcludeFilters,
Regexes: regexes,
Environments: arguments.Environments,
ExportLimit: &limit,
}
resp, err := getLogsMetoroCall(ctx, request)
if err != nil {
return nil, fmt.Errorf("error getting logs: %v", err)
}
respTrimmed, err := trimLogsResponse(resp)
if err != nil {
return nil, fmt.Errorf("error trimming logs: %v", err)
}
return mcpgolang.NewToolResponse(mcpgolang.NewTextContent(fmt.Sprintf("%s", string(respTrimmed)))), nil
}
func getLogsMetoroCall(ctx context.Context, request model.GetLogsRequest) ([]byte, error) {
requestBody, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("error marshaling logs request: %v", err)
}
return utils.MakeMetoroAPIRequest("POST", "logs", bytes.NewBuffer(requestBody), utils.GetAPIRequirementsFromRequest(ctx))
}
func trimLogsResponse(response []byte) ([]byte, error) {
var logsResponse model.GetLogsResponse
err := json.Unmarshal(response, &logsResponse)
if err != nil {
return nil, fmt.Errorf("error unmarshaling logs response: %v", err)
}
// Trim every log entry to only include the first 2000 characters of the message
// This is to prevent excessively long log messages from blowing up the context.
logLineLengthLimit := 2000
for i := range logsResponse.Logs {
if len(logsResponse.Logs[i].Message) > logLineLengthLimit {
logsResponse.Logs[i].Message = logsResponse.Logs[i].Message[:logLineLengthLimit]
}
}
return json.Marshal(logsResponse)
}
```
--------------------------------------------------------------------------------
/model/model_operator_config.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"bytes"
"encoding/json"
"fmt"
)
// checks if the OperatorConfig type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &OperatorConfig{}
// OperatorConfig struct for OperatorConfig
type OperatorConfig struct {
Operator OperatorType `json:"operator"`
// Threshold value for comparison
Threshold float64 `json:"threshold"`
}
type _OperatorConfig OperatorConfig
// NewOperatorConfig instantiates a new OperatorConfig object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewOperatorConfig(operator OperatorType, threshold float64) *OperatorConfig {
this := OperatorConfig{}
this.Operator = operator
this.Threshold = threshold
return &this
}
// NewOperatorConfigWithDefaults instantiates a new OperatorConfig object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewOperatorConfigWithDefaults() *OperatorConfig {
this := OperatorConfig{}
return &this
}
// GetOperator returns the Operator field value
func (o *OperatorConfig) GetOperator() OperatorType {
if o == nil {
var ret OperatorType
return ret
}
return o.Operator
}
// GetOperatorOk returns a tuple with the Operator field value
// and a boolean to check if the value has been set.
func (o *OperatorConfig) GetOperatorOk() (*OperatorType, bool) {
if o == nil {
return nil, false
}
return &o.Operator, true
}
// SetOperator sets field value
func (o *OperatorConfig) SetOperator(v OperatorType) {
o.Operator = v
}
// GetThreshold returns the Threshold field value
func (o *OperatorConfig) GetThreshold() float64 {
if o == nil {
var ret float64
return ret
}
return o.Threshold
}
// GetThresholdOk returns a tuple with the Threshold field value
// and a boolean to check if the value has been set.
func (o *OperatorConfig) GetThresholdOk() (*float64, bool) {
if o == nil {
return nil, false
}
return &o.Threshold, true
}
// SetThreshold sets field value
func (o *OperatorConfig) SetThreshold(v float64) {
o.Threshold = v
}
func (o OperatorConfig) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o OperatorConfig) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["operator"] = o.Operator
toSerialize["threshold"] = o.Threshold
return toSerialize, nil
}
func (o *OperatorConfig) UnmarshalJSON(data []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
requiredProperties := []string{
"operator",
"threshold",
}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
if err != nil {
return err
}
for _, requiredProperty := range requiredProperties {
if _, exists := allProperties[requiredProperty]; !exists {
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
varOperatorConfig := _OperatorConfig{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varOperatorConfig)
if err != nil {
return err
}
*o = OperatorConfig(varOperatorConfig)
return err
}
type NullableOperatorConfig struct {
value *OperatorConfig
isSet bool
}
func (v NullableOperatorConfig) Get() *OperatorConfig {
return v.value
}
func (v *NullableOperatorConfig) Set(val *OperatorConfig) {
v.value = val
v.isSet = true
}
func (v NullableOperatorConfig) IsSet() bool {
return v.isSet
}
func (v *NullableOperatorConfig) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableOperatorConfig(val *OperatorConfig) *NullableOperatorConfig {
return &NullableOperatorConfig{value: val, isSet: true}
}
func (v NullableOperatorConfig) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableOperatorConfig) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_timeseries_specifier_logs.go:
--------------------------------------------------------------------------------
```go
/*
Metoro Alerts API
API for managing alerts in the Metoro observability platform.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the TimeseriesSpecifierLogs type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &TimeseriesSpecifierLogs{}
// TimeseriesSpecifierLogs Configuration for a logs timeseries
type TimeseriesSpecifierLogs struct {
// Regular expressions to match logs
Regexes []string `json:"regexes,omitempty"`
// Regular expressions to exclude logs
ExcludeRegexes []string `json:"excludeRegexes,omitempty"`
}
// NewTimeseriesSpecifierLogs instantiates a new TimeseriesSpecifierLogs object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewTimeseriesSpecifierLogs() *TimeseriesSpecifierLogs {
this := TimeseriesSpecifierLogs{}
return &this
}
// NewTimeseriesSpecifierLogsWithDefaults instantiates a new TimeseriesSpecifierLogs object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewTimeseriesSpecifierLogsWithDefaults() *TimeseriesSpecifierLogs {
this := TimeseriesSpecifierLogs{}
return &this
}
// GetRegexes returns the Regexes field value if set, zero value otherwise.
func (o *TimeseriesSpecifierLogs) GetRegexes() []string {
if o == nil || IsNil(o.Regexes) {
var ret []string
return ret
}
return o.Regexes
}
// GetRegexesOk returns a tuple with the Regexes field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *TimeseriesSpecifierLogs) GetRegexesOk() ([]string, bool) {
if o == nil || IsNil(o.Regexes) {
return nil, false
}
return o.Regexes, true
}
// HasRegexes returns a boolean if a field has been set.
func (o *TimeseriesSpecifierLogs) HasRegexes() bool {
if o != nil && !IsNil(o.Regexes) {
return true
}
return false
}
// SetRegexes gets a reference to the given []string and assigns it to the Regexes field.
func (o *TimeseriesSpecifierLogs) SetRegexes(v []string) {
o.Regexes = v
}
// GetExcludeRegexes returns the ExcludeRegexes field value if set, zero value otherwise.
func (o *TimeseriesSpecifierLogs) GetExcludeRegexes() []string {
if o == nil || IsNil(o.ExcludeRegexes) {
var ret []string
return ret
}
return o.ExcludeRegexes
}
// GetExcludeRegexesOk returns a tuple with the ExcludeRegexes field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *TimeseriesSpecifierLogs) GetExcludeRegexesOk() ([]string, bool) {
if o == nil || IsNil(o.ExcludeRegexes) {
return nil, false
}
return o.ExcludeRegexes, true
}
// HasExcludeRegexes returns a boolean if a field has been set.
func (o *TimeseriesSpecifierLogs) HasExcludeRegexes() bool {
if o != nil && !IsNil(o.ExcludeRegexes) {
return true
}
return false
}
// SetExcludeRegexes gets a reference to the given []string and assigns it to the ExcludeRegexes field.
func (o *TimeseriesSpecifierLogs) SetExcludeRegexes(v []string) {
o.ExcludeRegexes = v
}
func (o TimeseriesSpecifierLogs) MarshalJSON() ([]byte, error) {
toSerialize,err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o TimeseriesSpecifierLogs) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.Regexes) {
toSerialize["regexes"] = o.Regexes
}
if !IsNil(o.ExcludeRegexes) {
toSerialize["excludeRegexes"] = o.ExcludeRegexes
}
return toSerialize, nil
}
type NullableTimeseriesSpecifierLogs struct {
value *TimeseriesSpecifierLogs
isSet bool
}
func (v NullableTimeseriesSpecifierLogs) Get() *TimeseriesSpecifierLogs {
return v.value
}
func (v *NullableTimeseriesSpecifierLogs) Set(val *TimeseriesSpecifierLogs) {
v.value = val
v.isSet = true
}
func (v NullableTimeseriesSpecifierLogs) IsSet() bool {
return v.isSet
}
func (v *NullableTimeseriesSpecifierLogs) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimeseriesSpecifierLogs(val *TimeseriesSpecifierLogs) *NullableTimeseriesSpecifierLogs {
return &NullableTimeseriesSpecifierLogs{value: val, isSet: true}
}
func (v NullableTimeseriesSpecifierLogs) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimeseriesSpecifierLogs) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_action_pager_duty_destination.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the ActionPagerDutyDestination type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &ActionPagerDutyDestination{}
// ActionPagerDutyDestination struct for ActionPagerDutyDestination
type ActionPagerDutyDestination struct {
// PagerDuty service ID
ServiceId *string `json:"serviceId,omitempty"`
// PagerDuty service name
ServiceName *string `json:"serviceName,omitempty"`
}
// NewActionPagerDutyDestination instantiates a new ActionPagerDutyDestination object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewActionPagerDutyDestination() *ActionPagerDutyDestination {
this := ActionPagerDutyDestination{}
return &this
}
// NewActionPagerDutyDestinationWithDefaults instantiates a new ActionPagerDutyDestination object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewActionPagerDutyDestinationWithDefaults() *ActionPagerDutyDestination {
this := ActionPagerDutyDestination{}
return &this
}
// GetServiceId returns the ServiceId field value if set, zero value otherwise.
func (o *ActionPagerDutyDestination) GetServiceId() string {
if o == nil || IsNil(o.ServiceId) {
var ret string
return ret
}
return *o.ServiceId
}
// GetServiceIdOk returns a tuple with the ServiceId field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ActionPagerDutyDestination) GetServiceIdOk() (*string, bool) {
if o == nil || IsNil(o.ServiceId) {
return nil, false
}
return o.ServiceId, true
}
// HasServiceId returns a boolean if a field has been set.
func (o *ActionPagerDutyDestination) HasServiceId() bool {
if o != nil && !IsNil(o.ServiceId) {
return true
}
return false
}
// SetServiceId gets a reference to the given string and assigns it to the ServiceId field.
func (o *ActionPagerDutyDestination) SetServiceId(v string) {
o.ServiceId = &v
}
// GetServiceName returns the ServiceName field value if set, zero value otherwise.
func (o *ActionPagerDutyDestination) GetServiceName() string {
if o == nil || IsNil(o.ServiceName) {
var ret string
return ret
}
return *o.ServiceName
}
// GetServiceNameOk returns a tuple with the ServiceName field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ActionPagerDutyDestination) GetServiceNameOk() (*string, bool) {
if o == nil || IsNil(o.ServiceName) {
return nil, false
}
return o.ServiceName, true
}
// HasServiceName returns a boolean if a field has been set.
func (o *ActionPagerDutyDestination) HasServiceName() bool {
if o != nil && !IsNil(o.ServiceName) {
return true
}
return false
}
// SetServiceName gets a reference to the given string and assigns it to the ServiceName field.
func (o *ActionPagerDutyDestination) SetServiceName(v string) {
o.ServiceName = &v
}
func (o ActionPagerDutyDestination) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o ActionPagerDutyDestination) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.ServiceId) {
toSerialize["serviceId"] = o.ServiceId
}
if !IsNil(o.ServiceName) {
toSerialize["serviceName"] = o.ServiceName
}
return toSerialize, nil
}
type NullableActionPagerDutyDestination struct {
value *ActionPagerDutyDestination
isSet bool
}
func (v NullableActionPagerDutyDestination) Get() *ActionPagerDutyDestination {
return v.value
}
func (v *NullableActionPagerDutyDestination) Set(val *ActionPagerDutyDestination) {
v.value = val
v.isSet = true
}
func (v NullableActionPagerDutyDestination) IsSet() bool {
return v.isSet
}
func (v *NullableActionPagerDutyDestination) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableActionPagerDutyDestination(val *ActionPagerDutyDestination) *NullableActionPagerDutyDestination {
return &NullableActionPagerDutyDestination{value: val, isSet: true}
}
func (v NullableActionPagerDutyDestination) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableActionPagerDutyDestination) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_timeseries_specifier_traces.go:
--------------------------------------------------------------------------------
```go
/*
Metoro Alerts API
API for managing alerts in the Metoro observability platform.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the TimeseriesSpecifierTraces type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &TimeseriesSpecifierTraces{}
// TimeseriesSpecifierTraces Configuration for a traces timeseries
type TimeseriesSpecifierTraces struct {
// Regular expressions to match traces
Regexes []string `json:"regexes,omitempty"`
// Regular expressions to exclude traces
ExcludeRegexes []string `json:"excludeRegexes,omitempty"`
}
// NewTimeseriesSpecifierTraces instantiates a new TimeseriesSpecifierTraces object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewTimeseriesSpecifierTraces() *TimeseriesSpecifierTraces {
this := TimeseriesSpecifierTraces{}
return &this
}
// NewTimeseriesSpecifierTracesWithDefaults instantiates a new TimeseriesSpecifierTraces object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewTimeseriesSpecifierTracesWithDefaults() *TimeseriesSpecifierTraces {
this := TimeseriesSpecifierTraces{}
return &this
}
// GetRegexes returns the Regexes field value if set, zero value otherwise.
func (o *TimeseriesSpecifierTraces) GetRegexes() []string {
if o == nil || IsNil(o.Regexes) {
var ret []string
return ret
}
return o.Regexes
}
// GetRegexesOk returns a tuple with the Regexes field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *TimeseriesSpecifierTraces) GetRegexesOk() ([]string, bool) {
if o == nil || IsNil(o.Regexes) {
return nil, false
}
return o.Regexes, true
}
// HasRegexes returns a boolean if a field has been set.
func (o *TimeseriesSpecifierTraces) HasRegexes() bool {
if o != nil && !IsNil(o.Regexes) {
return true
}
return false
}
// SetRegexes gets a reference to the given []string and assigns it to the Regexes field.
func (o *TimeseriesSpecifierTraces) SetRegexes(v []string) {
o.Regexes = v
}
// GetExcludeRegexes returns the ExcludeRegexes field value if set, zero value otherwise.
func (o *TimeseriesSpecifierTraces) GetExcludeRegexes() []string {
if o == nil || IsNil(o.ExcludeRegexes) {
var ret []string
return ret
}
return o.ExcludeRegexes
}
// GetExcludeRegexesOk returns a tuple with the ExcludeRegexes field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *TimeseriesSpecifierTraces) GetExcludeRegexesOk() ([]string, bool) {
if o == nil || IsNil(o.ExcludeRegexes) {
return nil, false
}
return o.ExcludeRegexes, true
}
// HasExcludeRegexes returns a boolean if a field has been set.
func (o *TimeseriesSpecifierTraces) HasExcludeRegexes() bool {
if o != nil && !IsNil(o.ExcludeRegexes) {
return true
}
return false
}
// SetExcludeRegexes gets a reference to the given []string and assigns it to the ExcludeRegexes field.
func (o *TimeseriesSpecifierTraces) SetExcludeRegexes(v []string) {
o.ExcludeRegexes = v
}
func (o TimeseriesSpecifierTraces) MarshalJSON() ([]byte, error) {
toSerialize,err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o TimeseriesSpecifierTraces) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.Regexes) {
toSerialize["regexes"] = o.Regexes
}
if !IsNil(o.ExcludeRegexes) {
toSerialize["excludeRegexes"] = o.ExcludeRegexes
}
return toSerialize, nil
}
type NullableTimeseriesSpecifierTraces struct {
value *TimeseriesSpecifierTraces
isSet bool
}
func (v NullableTimeseriesSpecifierTraces) Get() *TimeseriesSpecifierTraces {
return v.value
}
func (v *NullableTimeseriesSpecifierTraces) Set(val *TimeseriesSpecifierTraces) {
v.value = val
v.isSet = true
}
func (v NullableTimeseriesSpecifierTraces) IsSet() bool {
return v.isSet
}
func (v *NullableTimeseriesSpecifierTraces) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimeseriesSpecifierTraces(val *TimeseriesSpecifierTraces) *NullableTimeseriesSpecifierTraces {
return &NullableTimeseriesSpecifierTraces{value: val, isSet: true}
}
func (v NullableTimeseriesSpecifierTraces) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimeseriesSpecifierTraces) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_action_email_destination.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the ActionEmailDestination type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &ActionEmailDestination{}
// ActionEmailDestination struct for ActionEmailDestination
type ActionEmailDestination struct {
// Whether to notify the email recipients when the alert is resolved
NotifyOnResolve *bool `json:"notifyOnResolve,omitempty"`
// Email addresses to send alert to
Emails []string `json:"emails,omitempty"`
}
// NewActionEmailDestination instantiates a new ActionEmailDestination object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewActionEmailDestination() *ActionEmailDestination {
this := ActionEmailDestination{}
var notifyOnResolve bool = false
this.NotifyOnResolve = ¬ifyOnResolve
return &this
}
// NewActionEmailDestinationWithDefaults instantiates a new ActionEmailDestination object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewActionEmailDestinationWithDefaults() *ActionEmailDestination {
this := ActionEmailDestination{}
var notifyOnResolve bool = false
this.NotifyOnResolve = ¬ifyOnResolve
return &this
}
// GetNotifyOnResolve returns the NotifyOnResolve field value if set, zero value otherwise.
func (o *ActionEmailDestination) GetNotifyOnResolve() bool {
if o == nil || IsNil(o.NotifyOnResolve) {
var ret bool
return ret
}
return *o.NotifyOnResolve
}
// GetNotifyOnResolveOk returns a tuple with the NotifyOnResolve field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ActionEmailDestination) GetNotifyOnResolveOk() (*bool, bool) {
if o == nil || IsNil(o.NotifyOnResolve) {
return nil, false
}
return o.NotifyOnResolve, true
}
// HasNotifyOnResolve returns a boolean if a field has been set.
func (o *ActionEmailDestination) HasNotifyOnResolve() bool {
if o != nil && !IsNil(o.NotifyOnResolve) {
return true
}
return false
}
// SetNotifyOnResolve gets a reference to the given bool and assigns it to the NotifyOnResolve field.
func (o *ActionEmailDestination) SetNotifyOnResolve(v bool) {
o.NotifyOnResolve = &v
}
// GetEmails returns the Emails field value if set, zero value otherwise.
func (o *ActionEmailDestination) GetEmails() []string {
if o == nil || IsNil(o.Emails) {
var ret []string
return ret
}
return o.Emails
}
// GetEmailsOk returns a tuple with the Emails field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ActionEmailDestination) GetEmailsOk() ([]string, bool) {
if o == nil || IsNil(o.Emails) {
return nil, false
}
return o.Emails, true
}
// HasEmails returns a boolean if a field has been set.
func (o *ActionEmailDestination) HasEmails() bool {
if o != nil && !IsNil(o.Emails) {
return true
}
return false
}
// SetEmails gets a reference to the given []string and assigns it to the Emails field.
func (o *ActionEmailDestination) SetEmails(v []string) {
o.Emails = v
}
func (o ActionEmailDestination) MarshalJSON() ([]byte, error) {
toSerialize,err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o ActionEmailDestination) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.NotifyOnResolve) {
toSerialize["notifyOnResolve"] = o.NotifyOnResolve
}
if !IsNil(o.Emails) {
toSerialize["emails"] = o.Emails
}
return toSerialize, nil
}
type NullableActionEmailDestination struct {
value *ActionEmailDestination
isSet bool
}
func (v NullableActionEmailDestination) Get() *ActionEmailDestination {
return v.value
}
func (v *NullableActionEmailDestination) Set(val *ActionEmailDestination) {
v.value = val
v.isSet = true
}
func (v NullableActionEmailDestination) IsSet() bool {
return v.isSet
}
func (v *NullableActionEmailDestination) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableActionEmailDestination(val *ActionEmailDestination) *NullableActionEmailDestination {
return &NullableActionEmailDestination{value: val, isSet: true}
}
func (v NullableActionEmailDestination) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableActionEmailDestination) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_action_slack_destination.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"encoding/json"
)
// checks if the ActionSlackDestination type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &ActionSlackDestination{}
// ActionSlackDestination struct for ActionSlackDestination
type ActionSlackDestination struct {
// Slack channel to send alert to
Channel *string `json:"channel,omitempty"`
// Whether to notify the channel when the alert is resolved
NotifyOnResolve *bool `json:"notifyOnResolve,omitempty"`
}
// NewActionSlackDestination instantiates a new ActionSlackDestination object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewActionSlackDestination() *ActionSlackDestination {
this := ActionSlackDestination{}
var notifyOnResolve bool = false
this.NotifyOnResolve = ¬ifyOnResolve
return &this
}
// NewActionSlackDestinationWithDefaults instantiates a new ActionSlackDestination object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewActionSlackDestinationWithDefaults() *ActionSlackDestination {
this := ActionSlackDestination{}
var notifyOnResolve bool = false
this.NotifyOnResolve = ¬ifyOnResolve
return &this
}
// GetChannel returns the Channel field value if set, zero value otherwise.
func (o *ActionSlackDestination) GetChannel() string {
if o == nil || IsNil(o.Channel) {
var ret string
return ret
}
return *o.Channel
}
// GetChannelOk returns a tuple with the Channel field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ActionSlackDestination) GetChannelOk() (*string, bool) {
if o == nil || IsNil(o.Channel) {
return nil, false
}
return o.Channel, true
}
// HasChannel returns a boolean if a field has been set.
func (o *ActionSlackDestination) HasChannel() bool {
if o != nil && !IsNil(o.Channel) {
return true
}
return false
}
// SetChannel gets a reference to the given string and assigns it to the Channel field.
func (o *ActionSlackDestination) SetChannel(v string) {
o.Channel = &v
}
// GetNotifyOnResolve returns the NotifyOnResolve field value if set, zero value otherwise.
func (o *ActionSlackDestination) GetNotifyOnResolve() bool {
if o == nil || IsNil(o.NotifyOnResolve) {
var ret bool
return ret
}
return *o.NotifyOnResolve
}
// GetNotifyOnResolveOk returns a tuple with the NotifyOnResolve field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *ActionSlackDestination) GetNotifyOnResolveOk() (*bool, bool) {
if o == nil || IsNil(o.NotifyOnResolve) {
return nil, false
}
return o.NotifyOnResolve, true
}
// HasNotifyOnResolve returns a boolean if a field has been set.
func (o *ActionSlackDestination) HasNotifyOnResolve() bool {
if o != nil && !IsNil(o.NotifyOnResolve) {
return true
}
return false
}
// SetNotifyOnResolve gets a reference to the given bool and assigns it to the NotifyOnResolve field.
func (o *ActionSlackDestination) SetNotifyOnResolve(v bool) {
o.NotifyOnResolve = &v
}
func (o ActionSlackDestination) MarshalJSON() ([]byte, error) {
toSerialize,err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o ActionSlackDestination) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
if !IsNil(o.Channel) {
toSerialize["channel"] = o.Channel
}
if !IsNil(o.NotifyOnResolve) {
toSerialize["notifyOnResolve"] = o.NotifyOnResolve
}
return toSerialize, nil
}
type NullableActionSlackDestination struct {
value *ActionSlackDestination
isSet bool
}
func (v NullableActionSlackDestination) Get() *ActionSlackDestination {
return v.value
}
func (v *NullableActionSlackDestination) Set(val *ActionSlackDestination) {
v.value = val
v.isSet = true
}
func (v NullableActionSlackDestination) IsSet() bool {
return v.isSet
}
func (v *NullableActionSlackDestination) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableActionSlackDestination(val *ActionSlackDestination) *NullableActionSlackDestination {
return &NullableActionSlackDestination{value: val, isSet: true}
}
func (v NullableActionSlackDestination) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableActionSlackDestination) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_metoro_ql_timeseries.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"bytes"
"encoding/json"
"fmt"
)
// checks if the MetoroQlTimeseries type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &MetoroQlTimeseries{}
// MetoroQlTimeseries struct for MetoroQlTimeseries
type MetoroQlTimeseries struct {
// MetoroQL query to use for the timeseries.
Query string `json:"query"`
// The size of each bucket to aggregate data into in seconds. For example, if the bucket size is 60, the data will be aggregated into 1 minute buckets.
BucketSize int64 `json:"bucketSize"`
}
type _MetoroQlTimeseries MetoroQlTimeseries
// NewMetoroQlTimeseries instantiates a new MetoroQlTimeseries object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewMetoroQlTimeseries(query string, bucketSize int64) *MetoroQlTimeseries {
this := MetoroQlTimeseries{}
this.Query = query
this.BucketSize = bucketSize
return &this
}
// NewMetoroQlTimeseriesWithDefaults instantiates a new MetoroQlTimeseries object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewMetoroQlTimeseriesWithDefaults() *MetoroQlTimeseries {
this := MetoroQlTimeseries{}
return &this
}
// GetQuery returns the Query field value
func (o *MetoroQlTimeseries) GetQuery() string {
if o == nil {
var ret string
return ret
}
return o.Query
}
// GetQueryOk returns a tuple with the Query field value
// and a boolean to check if the value has been set.
func (o *MetoroQlTimeseries) GetQueryOk() (*string, bool) {
if o == nil {
return nil, false
}
return &o.Query, true
}
// SetQuery sets field value
func (o *MetoroQlTimeseries) SetQuery(v string) {
o.Query = v
}
// GetBucketSize returns the BucketSize field value
func (o *MetoroQlTimeseries) GetBucketSize() int64 {
if o == nil {
var ret int64
return ret
}
return o.BucketSize
}
// GetBucketSizeOk returns a tuple with the BucketSize field value
// and a boolean to check if the value has been set.
func (o *MetoroQlTimeseries) GetBucketSizeOk() (*int64, bool) {
if o == nil {
return nil, false
}
return &o.BucketSize, true
}
// SetBucketSize sets field value
func (o *MetoroQlTimeseries) SetBucketSize(v int64) {
o.BucketSize = v
}
func (o MetoroQlTimeseries) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o MetoroQlTimeseries) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["query"] = o.Query
toSerialize["bucketSize"] = o.BucketSize
return toSerialize, nil
}
func (o *MetoroQlTimeseries) UnmarshalJSON(data []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
requiredProperties := []string{
"query",
"bucketSize",
}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
if err != nil {
return err
}
for _, requiredProperty := range requiredProperties {
if _, exists := allProperties[requiredProperty]; !exists {
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
varMetoroQlTimeseries := _MetoroQlTimeseries{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varMetoroQlTimeseries)
if err != nil {
return err
}
*o = MetoroQlTimeseries(varMetoroQlTimeseries)
return err
}
type NullableMetoroQlTimeseries struct {
value *MetoroQlTimeseries
isSet bool
}
func (v NullableMetoroQlTimeseries) Get() *MetoroQlTimeseries {
return v.value
}
func (v *NullableMetoroQlTimeseries) Set(val *MetoroQlTimeseries) {
v.value = val
v.isSet = true
}
func (v NullableMetoroQlTimeseries) IsSet() bool {
return v.isSet
}
func (v *NullableMetoroQlTimeseries) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableMetoroQlTimeseries(val *MetoroQlTimeseries) *NullableMetoroQlTimeseries {
return &NullableMetoroQlTimeseries{value: val, isSet: true}
}
func (v NullableMetoroQlTimeseries) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableMetoroQlTimeseries) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_timeseries_config.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"bytes"
"encoding/json"
"fmt"
)
// checks if the TimeseriesConfig type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &TimeseriesConfig{}
// TimeseriesConfig struct for TimeseriesConfig
type TimeseriesConfig struct {
Expression ExpressionConfig `json:"expression"`
// Rules for evaluating the metrics and triggering alerts
EvaluationRules []Condition `json:"evaluationRules"`
}
type _TimeseriesConfig TimeseriesConfig
// NewTimeseriesConfig instantiates a new TimeseriesConfig object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewTimeseriesConfig(expression ExpressionConfig, evaluationRules []Condition) *TimeseriesConfig {
this := TimeseriesConfig{}
this.Expression = expression
this.EvaluationRules = evaluationRules
return &this
}
// NewTimeseriesConfigWithDefaults instantiates a new TimeseriesConfig object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewTimeseriesConfigWithDefaults() *TimeseriesConfig {
this := TimeseriesConfig{}
return &this
}
// GetExpression returns the Expression field value
func (o *TimeseriesConfig) GetExpression() ExpressionConfig {
if o == nil {
var ret ExpressionConfig
return ret
}
return o.Expression
}
// GetExpressionOk returns a tuple with the Expression field value
// and a boolean to check if the value has been set.
func (o *TimeseriesConfig) GetExpressionOk() (*ExpressionConfig, bool) {
if o == nil {
return nil, false
}
return &o.Expression, true
}
// SetExpression sets field value
func (o *TimeseriesConfig) SetExpression(v ExpressionConfig) {
o.Expression = v
}
// GetEvaluationRules returns the EvaluationRules field value
func (o *TimeseriesConfig) GetEvaluationRules() []Condition {
if o == nil {
var ret []Condition
return ret
}
return o.EvaluationRules
}
// GetEvaluationRulesOk returns a tuple with the EvaluationRules field value
// and a boolean to check if the value has been set.
func (o *TimeseriesConfig) GetEvaluationRulesOk() ([]Condition, bool) {
if o == nil {
return nil, false
}
return o.EvaluationRules, true
}
// SetEvaluationRules sets field value
func (o *TimeseriesConfig) SetEvaluationRules(v []Condition) {
o.EvaluationRules = v
}
func (o TimeseriesConfig) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o TimeseriesConfig) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["expression"] = o.Expression
toSerialize["evaluationRules"] = o.EvaluationRules
return toSerialize, nil
}
func (o *TimeseriesConfig) UnmarshalJSON(data []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
requiredProperties := []string{
"expression",
"evaluationRules",
}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
if err != nil {
return err
}
for _, requiredProperty := range requiredProperties {
if _, exists := allProperties[requiredProperty]; !exists {
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
varTimeseriesConfig := _TimeseriesConfig{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varTimeseriesConfig)
if err != nil {
return err
}
*o = TimeseriesConfig(varTimeseriesConfig)
return err
}
type NullableTimeseriesConfig struct {
value *TimeseriesConfig
isSet bool
}
func (v NullableTimeseriesConfig) Get() *TimeseriesConfig {
return v.value
}
func (v *NullableTimeseriesConfig) Set(val *TimeseriesConfig) {
v.value = val
v.isSet = true
}
func (v NullableTimeseriesConfig) IsSet() bool {
return v.isSet
}
func (v *NullableTimeseriesConfig) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimeseriesConfig(val *TimeseriesConfig) *NullableTimeseriesConfig {
return &NullableTimeseriesConfig{value: val, isSet: true}
}
func (v NullableTimeseriesConfig) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimeseriesConfig) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_static_condition.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"bytes"
"encoding/json"
"fmt"
)
// checks if the StaticCondition type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &StaticCondition{}
// StaticCondition struct for StaticCondition
type StaticCondition struct {
// List of operator conditions that must be met
Operators []OperatorConfig `json:"operators"`
PersistenceSettings PersistenceSettings `json:"persistenceSettings"`
}
type _StaticCondition StaticCondition
// NewStaticCondition instantiates a new StaticCondition object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewStaticCondition(operators []OperatorConfig, persistenceSettings PersistenceSettings) *StaticCondition {
this := StaticCondition{}
this.Operators = operators
this.PersistenceSettings = persistenceSettings
return &this
}
// NewStaticConditionWithDefaults instantiates a new StaticCondition object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewStaticConditionWithDefaults() *StaticCondition {
this := StaticCondition{}
return &this
}
// GetOperators returns the Operators field value
func (o *StaticCondition) GetOperators() []OperatorConfig {
if o == nil {
var ret []OperatorConfig
return ret
}
return o.Operators
}
// GetOperatorsOk returns a tuple with the Operators field value
// and a boolean to check if the value has been set.
func (o *StaticCondition) GetOperatorsOk() ([]OperatorConfig, bool) {
if o == nil {
return nil, false
}
return o.Operators, true
}
// SetOperators sets field value
func (o *StaticCondition) SetOperators(v []OperatorConfig) {
o.Operators = v
}
// GetPersistenceSettings returns the PersistenceSettings field value
func (o *StaticCondition) GetPersistenceSettings() PersistenceSettings {
if o == nil {
var ret PersistenceSettings
return ret
}
return o.PersistenceSettings
}
// GetPersistenceSettingsOk returns a tuple with the PersistenceSettings field value
// and a boolean to check if the value has been set.
func (o *StaticCondition) GetPersistenceSettingsOk() (*PersistenceSettings, bool) {
if o == nil {
return nil, false
}
return &o.PersistenceSettings, true
}
// SetPersistenceSettings sets field value
func (o *StaticCondition) SetPersistenceSettings(v PersistenceSettings) {
o.PersistenceSettings = v
}
func (o StaticCondition) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o StaticCondition) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["operators"] = o.Operators
toSerialize["persistenceSettings"] = o.PersistenceSettings
return toSerialize, nil
}
func (o *StaticCondition) UnmarshalJSON(data []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
requiredProperties := []string{
"operators",
"persistenceSettings",
}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
if err != nil {
return err
}
for _, requiredProperty := range requiredProperties {
if _, exists := allProperties[requiredProperty]; !exists {
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
varStaticCondition := _StaticCondition{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varStaticCondition)
if err != nil {
return err
}
*o = StaticCondition(varStaticCondition)
return err
}
type NullableStaticCondition struct {
value *StaticCondition
isSet bool
}
func (v NullableStaticCondition) Get() *StaticCondition {
return v.value
}
func (v *NullableStaticCondition) Set(val *StaticCondition) {
v.value = val
v.isSet = true
}
func (v NullableStaticCondition) IsSet() bool {
return v.isSet
}
func (v *NullableStaticCondition) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableStaticCondition(val *StaticCondition) *NullableStaticCondition {
return &NullableStaticCondition{value: val, isSet: true}
}
func (v NullableStaticCondition) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableStaticCondition) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```
--------------------------------------------------------------------------------
/model/model_alert.go:
--------------------------------------------------------------------------------
```go
/*
Metoro API
API for managing Metoro environments, alerts, and dashboards.
API version: 1.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package model
import (
"bytes"
"encoding/json"
"fmt"
)
// checks if the Alert type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &Alert{}
// Alert struct for Alert
type Alert struct {
Metadata MetadataObject `json:"metadata"`
Type *AlertType `json:"type,omitempty"`
Timeseries TimeseriesConfig `json:"timeseries"`
}
type _Alert Alert
// NewAlert instantiates a new Alert object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewAlert(metadata MetadataObject, timeseries TimeseriesConfig) *Alert {
this := Alert{}
this.Metadata = metadata
this.Timeseries = timeseries
return &this
}
// NewAlertWithDefaults instantiates a new Alert object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewAlertWithDefaults() *Alert {
this := Alert{}
return &this
}
// GetMetadata returns the Metadata field value
func (o *Alert) GetMetadata() MetadataObject {
if o == nil {
var ret MetadataObject
return ret
}
return o.Metadata
}
// GetMetadataOk returns a tuple with the Metadata field value
// and a boolean to check if the value has been set.
func (o *Alert) GetMetadataOk() (*MetadataObject, bool) {
if o == nil {
return nil, false
}
return &o.Metadata, true
}
// SetMetadata sets field value
func (o *Alert) SetMetadata(v MetadataObject) {
o.Metadata = v
}
// GetType returns the Type field value if set, zero value otherwise.
func (o *Alert) GetType() AlertType {
if o == nil || IsNil(o.Type) {
var ret AlertType
return ret
}
return *o.Type
}
// GetTypeOk returns a tuple with the Type field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *Alert) GetTypeOk() (*AlertType, bool) {
if o == nil || IsNil(o.Type) {
return nil, false
}
return o.Type, true
}
// HasType returns a boolean if a field has been set.
func (o *Alert) HasType() bool {
if o != nil && !IsNil(o.Type) {
return true
}
return false
}
// SetType gets a reference to the given AlertType and assigns it to the Type field.
func (o *Alert) SetType(v AlertType) {
o.Type = &v
}
// GetTimeseries returns the Timeseries field value
func (o *Alert) GetTimeseries() TimeseriesConfig {
if o == nil {
var ret TimeseriesConfig
return ret
}
return o.Timeseries
}
// GetTimeseriesOk returns a tuple with the Timeseries field value
// and a boolean to check if the value has been set.
func (o *Alert) GetTimeseriesOk() (*TimeseriesConfig, bool) {
if o == nil {
return nil, false
}
return &o.Timeseries, true
}
// SetTimeseries sets field value
func (o *Alert) SetTimeseries(v TimeseriesConfig) {
o.Timeseries = v
}
func (o Alert) MarshalJSON() ([]byte, error) {
toSerialize, err := o.ToMap()
if err != nil {
return []byte{}, err
}
return json.Marshal(toSerialize)
}
func (o Alert) ToMap() (map[string]interface{}, error) {
toSerialize := map[string]interface{}{}
toSerialize["metadata"] = o.Metadata
if !IsNil(o.Type) {
toSerialize["type"] = o.Type
}
toSerialize["timeseries"] = o.Timeseries
return toSerialize, nil
}
func (o *Alert) UnmarshalJSON(data []byte) (err error) {
// This validates that all required properties are included in the JSON object
// by unmarshalling the object into a generic map with string keys and checking
// that every required field exists as a key in the generic map.
requiredProperties := []string{
"metadata",
"timeseries",
}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
if err != nil {
return err
}
for _, requiredProperty := range requiredProperties {
if _, exists := allProperties[requiredProperty]; !exists {
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
varAlert := _Alert{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
err = decoder.Decode(&varAlert)
if err != nil {
return err
}
*o = Alert(varAlert)
return err
}
type NullableAlert struct {
value *Alert
isSet bool
}
func (v NullableAlert) Get() *Alert {
return v.value
}
func (v *NullableAlert) Set(val *Alert) {
v.value = val
v.isSet = true
}
func (v NullableAlert) IsSet() bool {
return v.isSet
}
func (v *NullableAlert) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableAlert(val *Alert) *NullableAlert {
return &NullableAlert{value: val, isSet: true}
}
func (v NullableAlert) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableAlert) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}
```