// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package metricserver

import (
	"gvisor.dev/gvisor/pkg/prometheus"
)

// Metric is a metric exported by the metric server.
type Metric struct {
	prometheus.Metric

	// PerSandbox is true if this metric is exported for each sandbox.
	// If false, it is exported for the metric server itself.
	PerSandbox bool
}

// Metrics generated by the metrics server itself.
var (
	SandboxPresenceMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_presence",
			Type: prometheus.TypeGauge,
			Help: "Boolean metric set to 1 for each known sandbox.",
		},
		PerSandbox: true,
	}
	SandboxRunningMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_running",
			Type: prometheus.TypeGauge,
			Help: "Boolean metric set to 1 for each running sandbox.",
		},
		PerSandbox: true,
	}
	SandboxCheckpointedMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_checkpointed",
			Type: prometheus.TypeGauge,
			Help: "Boolean metric set to 1 for each checkpointed sandbox.",
		},
		PerSandbox: true,
	}
	SandboxRestoredMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_restored",
			Type: prometheus.TypeGauge,
			Help: "Boolean metric set to 1 for each restored sandbox.",
		},
		PerSandbox: true,
	}
	SandboxCPUTimeSavedMSMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_cpu_time_saved_milliseconds",
			Type: prometheus.TypeGauge,
			Help: "CPU time saved for each restored sandbox (in milliseconds).",
		},
		PerSandbox: true,
	}
	SandboxWallTimeSavedMSMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_wall_time_saved_milliseconds",
			Type: prometheus.TypeGauge,
			Help: "Wall time saved for each restored sandbox (in milliseconds).",
		},
		PerSandbox: true,
	}
	SandboxMetadataMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_metadata",
			Type: prometheus.TypeGauge,
			Help: "Key-value pairs about per-sandbox metadata.",
		},
		PerSandbox: true,
	}
	SandboxCapabilitiesMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_capabilities",
			Type: prometheus.TypeGauge,
			Help: "Linux capabilities added within containers of the sandbox.",
		},
		PerSandbox: true,
	}
	SandboxCapabilitiesMetricLabel = "capability"
	SpecMetadataMetric             = Metric{
		Metric: prometheus.Metric{
			Name: "spec_metadata",
			Type: prometheus.TypeGauge,
			Help: "Key-value pairs about OCI spec metadata.",
		},
		PerSandbox: true,
	}
	SandboxCreationMetric = Metric{
		Metric: prometheus.Metric{
			Name: "sandbox_creation_time_seconds",
			Type: prometheus.TypeGauge,
			Help: "When the sandbox was created, as a unix timestamp in seconds.",
		},
		PerSandbox: true,
	}
	MetricServerPresenceMetric = Metric{
		Metric: prometheus.Metric{
			Name: "metric_server_presence",
			Type: prometheus.TypeGauge,
			Help: "Boolean metric always set to 1 for the metric server process.",
		},
		PerSandbox: false,
	}
	NumRunningSandboxesMetric = Metric{
		Metric: prometheus.Metric{
			Name: "num_sandboxes_running",
			Type: prometheus.TypeGauge,
			Help: "Number of sandboxes running at present.",
		},
		PerSandbox: false,
	}
	NumCannotExportSandboxesMetric = Metric{
		Metric: prometheus.Metric{
			Name: "num_sandboxes_broken_metrics",
			Type: prometheus.TypeGauge,
			Help: "Number of sandboxes from which we cannot export metrics.",
		},
		PerSandbox: false,
	}
	NumTotalSandboxesMetric = Metric{
		Metric: prometheus.Metric{
			Name: "num_sandboxes_total",
			Type: prometheus.TypeCounter,
			Help: "Counter of sandboxes that have ever been started.",
		},
		PerSandbox: false,
	}
	NumCheckpointedSandboxesMetric = Metric{
		Metric: prometheus.Metric{
			Name: "num_sandboxes_checkpointed",
			Type: prometheus.TypeCounter,
			Help: "Counter of sandboxes that have been checkpointed.",
		},
		PerSandbox: false,
	}
	NumRestoredSandboxesMetric = Metric{
		Metric: prometheus.Metric{
			Name: "num_sandboxes_restored",
			Type: prometheus.TypeCounter,
			Help: "Counter of sandboxes that have been restored.",
		},
		PerSandbox: false,
	}
	ProcessStartTimeSeconds = Metric{
		Metric:     prometheus.ProcessStartTimeSeconds,
		PerSandbox: false,
	}
)

// Metrics is a list of metrics that the metric server generates.
var Metrics = []*Metric{
	&SandboxPresenceMetric,
	&SandboxRunningMetric,
	&SandboxMetadataMetric,
	&SandboxCheckpointedMetric,
	&SandboxRestoredMetric,
	&SandboxCPUTimeSavedMSMetric,
	&SandboxWallTimeSavedMSMetric,
	&SandboxCapabilitiesMetric,
	&SpecMetadataMetric,
	&SandboxCreationMetric,
	&MetricServerPresenceMetric,
	&NumRunningSandboxesMetric,
	&NumCannotExportSandboxesMetric,
	&NumTotalSandboxesMetric,
	&NumCheckpointedSandboxesMetric,
	&NumRestoredSandboxesMetric,
	&ProcessStartTimeSeconds,
}
