Add a metrics provider
The
KeptnMetric
feature works with almost any data platform
but Keptn requires that a metrics provider be defined
for any data platform it uses as a data source.
This guide gives instructions for creating a new metrics provider.
For these instructions,
we define a sample provider called placeholder
.
The steps to create your own metrics provider are:
-
Fork and clone the Keptn repository. For more information, see Fork and clone the repository.
-
Define the Provider Type: In the
metrics-operator/controllers/common/providers/common.go
file, define the constantKeptnPlaceholderProviderType
. In our example we use"placeholder"
. -
Implement the Provider: Create a new folder inside the metrics-operator/controllers/common/providers. Use the provider name as the name of the folder. This name defines the string used to identify this provider in the
spec.type
field of the KeptnMetricsProvider resource. In this example, the folder is namedplaceholder
. Create a new Go package for the placeholder provider in that folder. This package should contain astruct
that implements theKeptnSLIProvider
interface. To fully implement theKeptnSLIProvider
interface, it's necessary to implement the following functions.EvaluateQuery
(Fetches metric values from the provider)- This function fetches metric values based on the provided metric query from the provider. It evaluates the query and returns the metric values along with any additional data if required.
- It takes as input a KeptnMetric and KeptnMetricsProvider
EvaluateQueryForStep
(Fetches metric values with step interval from the provider)- This function fetches metric values with a specified step interval from the placeholder provider. It takes into account the metric query and the step interval provided, executes the query, and returns the metric values along with any additional data if required.
- It takes as input a KeptnMetric and KeptnMetricsProvider
FetchAnalysisValue
(Fetches analysis values from the provider) functions.- This function fetches analysis values based on the provided query and time range from the provider. It evaluates the query within the specified time range and returns the analysis values along with any additional data if required.
- It takes as input an Analysis,
resource that contains a
query
and a KeptnMetricsProvider resource.
You can follow other existing implementations, such as prometheus.go, as an example.
Each of the three functions expects a string containing a float value in it. But for example purposes we returned some of the data accessible in the function.
Below is an example of a placeholder provider implementation.
package placeholder import ( "context" "fmt" "net/http" "time" "github.com/go-logr/logr" metricsapi "github.com/keptn/lifecycle-toolkit/metrics-operator/api/v1" ) type KeptnPlaceholderProvider struct { Log logr.Logger HttpClient http.Client } func (d *KeptnPlaceholderProvider) FetchAnalysisValue(ctx context.Context, query string, analysis metricsapi.Analysis, provider *metricsapi.KeptnMetricsProvider) (string, error) { return fmt.Sprintf("placeholder provider FetchAnalysisValue was called with query %s from %d to %d", query, analysis.GetFrom().Unix(), analysis.GetTo().Unix()), nil } func (d *KeptnPlaceholderProvider) EvaluateQuery(ctx context.Context, metric metricsapi.KeptnMetric, provider metricsapi.KeptnMetricsProvider) (string, []byte, error) { return fmt.Sprintf("placeholder provider EvaluateQuery was called with query %s", metric.Spec.Query), nil, nil } func (d *KeptnPlaceholderProvider) EvaluateQueryForStep(ctx context.Context, metric metricsapi.KeptnMetric, provider metricsapi.KeptnMetricsProvider) ([]string, []byte, error) { fromTime, toTime, stepInterval, err := getTimeRangeForStep(metric) if err != nil { return nil, nil, err } result := fmt.Sprintf("placeholder provider EvaluateQueryForStep was called with query %s from %d to %d at an interval %d", metric.Spec.Query, fromTime, toTime, stepInterval) return []string{result}, nil, nil } func getTimeRangeForStep(metric metricsapi.KeptnMetric) (int64, int64, int64, error) { intervalDuration, err := time.ParseDuration(metric.Spec.Range.Interval) if err != nil { return 0, 0, 0, err } stepDuration, err := time.ParseDuration(metric.Spec.Range.Step) if err != nil { return 0, 0, 0, err } return time.Now().Add(-intervalDuration).Unix(), time.Now().Unix(), stepDuration.Milliseconds(), nil }
Note Refer to the documentation of the KeptnMetric and Analysis resources to understand what data should be retrieved from the methods inputs to compute accurate results.
-
Instantiate the Provider in the
providers.NewProvider
function in themetrics-operator/controllers/common/providers/provider.go
file. add a case for theKeptnPlaceholderProviderType
. Instantiate the placeholder provider struct and return it.// Inside the providers package // NewProvider function func NewProvider(providerType string, log logr.Logger, k8sClient client.Client) (KeptnSLIProvider, error) { switch strings.ToLower(providerType) { case KeptnPlaceholderProviderType: return &placeholder.KeptnPlaceholderProvider{ Log: log, HttpClient: http.Client{}, }, nil // Other cases... } }
-
Update the validation webhook and crd config: To update the validation webhook and crd config of the metrics operator. Add the provider name next to last providers on this line to look like this
// +kubebuilder:validation:Pattern:=cortex|datadog|dql|dynatrace|prometheus|thanos|placeholder
.In the metric-operator directory run
make generate manifests
to update the metrics-operator crd config Then modify the helm chart and the helm chart crd validation to match the update in the metrics-operator crd config -
Add Test Cases:
-
Write a unit test to validate your implementation at the function level. Unit tests ensure that individual functions behave as expected and meet their functional requirements.
-
Include a Chainsaw test to validate the behavior of Kubernetes resources managed by your code. Chainsaw tests simulate real-world scenarios and interactions within a Kubernetes cluster, ensuring the correctness of your Kubernetes configurations and deployments.
Below are the steps for adding an integration test.
- In the directory
test/chainsaw/testmetrics
, create a foldermetrics-provider-placeholder
in our case. - Within the
keptn-metrics-placeholder
folder, create YAML file00-install.yaml
. 00-install.yaml
contains a sample configuration that installs a validKeptnMetricsProvider
in our caseplaceholder
and it also defines a sampleKeptnMetric
configuration representing a valid use case, while.- Create a file named
chainsaw-test.yaml
and define the steps for the integration test in chainsaw-test.yaml.
For more information checkout an already existing integration test
- In the directory
-