lib

package
v0.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 4, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Example

This example shows a basic usage of sloth library by exposing sloth SLO generation functionality as a rest HTTP API.

package main

import (
	"fmt"
	"io"
	"net/http"

	sloth "github.com/slok/sloth/pkg/lib"
)

func main() {
	// Check with `curl -XPOST http://127.0.0.1:8080/sloth/generate -d "$(cat ./examples/getting-started.yml)"`.

	gen, err := sloth.NewPrometheusSLOGenerator(sloth.PrometheusSLOGeneratorConfig{
		ExtraLabels: map[string]string{"source": "slothlib-example"},
	})
	if err != nil {
		panic(fmt.Errorf("could not create SLO generator: %w", err))
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /sloth/generate", func(w http.ResponseWriter, r *http.Request) {
		// Get body from request.
		body, err := io.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "failed to read request body", http.StatusBadRequest)
			return
		}
		defer r.Body.Close()

		// Generate SLOs.
		result, err := gen.GenerateFromRaw(r.Context(), body)
		if err != nil {
			http.Error(w, fmt.Sprintf("could not generate SLOs: %v", err), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusOK)
		err = gen.WriteResultAsPrometheusStd(r.Context(), *result, w)
		if err != nil {
			http.Error(w, fmt.Sprintf("could not write result: %v", err), http.StatusInternalServerError)
			return
		}
	})

	httpServer := &http.Server{Addr: ":8080", Handler: mux}

	fmt.Println("Starting server at :8080")

	err = httpServer.ListenAndServe()
	if err != nil {
		panic(err)
	}
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CallerAgent

type CallerAgent string

CallerAgent is the agent calling the library.

const (
	// CallerAgentCLI is the caller agent when using sloth as CLI.
	CallerAgentCLI CallerAgent = "cli"
	// CallerAgentCLI is the caller agent when using sloth as API.
	CallerAgentAPI CallerAgent = "api"
)

type PrometheusSLOGenerator

type PrometheusSLOGenerator struct {
	// contains filtered or unexported fields
}

PrometheusSLOGenerator is a Prometheus SLO rules generator from the Sloth supported SLO definitions.

func (PrometheusSLOGenerator) GenerateFromK8sV1

GenerateFromK8sV1 generates SLO rules from a Kubernetes Sloth CR SLO definition spec struct.

Example
package main

import (
	"context"
	"os"

	"github.com/slok/sloth/pkg/common/model"
	slotk8sv1 "github.com/slok/sloth/pkg/kubernetes/api/sloth/v1"
	"github.com/slok/sloth/pkg/lib"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func main() {
	sloSpec := slotk8sv1.PrometheusServiceLevel{
		ObjectMeta: metav1.ObjectMeta{
			Name: "test01",
			Labels: map[string]string{
				"prometheus": "default",
			},
		},
		Spec: slotk8sv1.PrometheusServiceLevelSpec{
			Service: "svc01",
			Labels: map[string]string{
				"globalk1": "globalv1",
			},
			SLOs: []slotk8sv1.SLO{
				{
					Name:      "slo01",
					Objective: 99.9,
					Labels: map[string]string{
						"slo01k1": "slo01v1",
					},
					SLI: slotk8sv1.SLI{Events: &slotk8sv1.SLIEvents{
						ErrorQuery: `sum(rate(http_request_duration_seconds_count{job="myservice",code=~"(5..|429)"}[{{.window}}]))`,
						TotalQuery: `sum(rate(http_request_duration_seconds_count{job="myservice"}[{{.window}}]))`,
					}},
					Alerting: slotk8sv1.Alerting{
						Name: "myServiceAlert",
						Labels: map[string]string{
							"alert01k1": "alert01v1",
						},
						Annotations: map[string]string{
							"alert02k1": "alert02v1",
						},
						PageAlert:   slotk8sv1.Alert{},
						TicketAlert: slotk8sv1.Alert{},
					},
				},
			},
		},
	}

	ctx := context.Background()

	gen, err := lib.NewPrometheusSLOGenerator(lib.PrometheusSLOGeneratorConfig{
		ExtraLabels: map[string]string{"source": "slothlib-example"},
	})
	if err != nil {
		panic(err)
	}

	// Generate SLO and write result.
	slo, err := gen.GenerateFromK8sV1(ctx, sloSpec)
	if err != nil {
		panic(err)
	}

	kmeta := model.K8sMeta{
		Name:      "sloth-slo-gen-" + sloSpec.ObjectMeta.Name,
		Namespace: sloSpec.ObjectMeta.Namespace,
	}
	err = gen.WriteResultAsK8sPrometheusOperator(ctx, kmeta, *slo, os.Stdout)
	if err != nil {
		panic(err)
	}
}

func (PrometheusSLOGenerator) GenerateFromOpenSLOV1Alpha

func (p PrometheusSLOGenerator) GenerateFromOpenSLOV1Alpha(ctx context.Context, spec openslov1alpha.SLO) (*model.PromSLOGroupResult, error)

GenerateFromOpenSLOV1Alpha generates SLO rules from an OpenSLO SLO definition spec struct.

func (PrometheusSLOGenerator) GenerateFromRaw

func (p PrometheusSLOGenerator) GenerateFromRaw(ctx context.Context, data []byte) (*model.PromSLOGroupResult, error)

GenerateFromRaw generates SLO rules from raw data, it will infer what type of SLO spec receives. This method is the most generic one as the user doesn't need to know what type of SLO spec is using. For more custom programmatic usage use the other Go struct API spec generators.

Example
package main

import (
	"context"
	"os"

	"github.com/slok/sloth/pkg/lib"
)

func main() {
	sloSpec := []byte(`
---
version: "prometheus/v1"
service: "myservice"
labels:
  owner: "myteam"
  repo: "myorg/myservice"
  tier: "2"
slos:
  # We allow failing (5xx and 429) 1 request every 1000 requests (99.9%).
  - name: "requests-availability"
    objective: 99.9
    description: "Common SLO based on availability for HTTP request responses."
    labels:
      category: availability
    sli:
      events:
        error_query: sum(rate(http_request_duration_seconds_count{job="myservice",code=~"(5..|429)"}[{{.window}}]))
        total_query: sum(rate(http_request_duration_seconds_count{job="myservice"}[{{.window}}]))
    alerting:
      name: "MyServiceHighErrorRate"
      labels:
        category: "availability"
      annotations:
        # Overwrite default Sloth SLO alert summmary on ticket and page alerts.
        summary: "High error rate on 'myservice' requests responses"
      page_alert:
        labels:
          severity: "pageteam"
          routing_key: "myteam"
      ticket_alert:
        labels:
          severity: "slack"
          slack_channel: "#alerts-myteam"
`)

	ctx := context.Background()

	gen, err := lib.NewPrometheusSLOGenerator(lib.PrometheusSLOGeneratorConfig{
		ExtraLabels: map[string]string{"source": "slothlib-example"},
	})
	if err != nil {
		panic(err)
	}

	// Generate SLO and write result.
	slo, err := gen.GenerateFromRaw(ctx, sloSpec)
	if err != nil {
		panic(err)
	}

	err = gen.WriteResultAsPrometheusStd(ctx, *slo, os.Stdout)
	if err != nil {
		panic(err)
	}
}

func (PrometheusSLOGenerator) GenerateFromSlothV1

GenerateFromSlothV1 generates SLOs from a Sloth Prometheus SLO definition spec struct.

Example
package main

import (
	"context"
	"os"

	"github.com/slok/sloth/pkg/lib"

	slothprometheusv1 "github.com/slok/sloth/pkg/prometheus/api/v1"
)

func main() {
	sloSpec := slothprometheusv1.Spec{
		Service: "myservice",
		Labels: map[string]string{
			"owner": "myteam",
			"repo":  "myorg/myservice",
			"tier":  "2",
		},
		SLOs: []slothprometheusv1.SLO{
			{
				Name:        "requests-availability",
				Objective:   99.9,
				Description: "Common SLO based on availability for HTTP request responses.",
				SLI: slothprometheusv1.SLI{
					Events: &slothprometheusv1.SLIEvents{
						ErrorQuery: `sum(rate(http_request_duration_seconds_count{job="myservice",code=~"(5..|429)"}[{{.window}}]))`,
						TotalQuery: `sum(rate(http_request_duration_seconds_count{job="myservice"}[{{.window}}]))`,
					},
				},
				Alerting: slothprometheusv1.Alerting{
					Name:        "MyServiceHighErrorRate",
					Labels:      map[string]string{"category": "availability"},
					Annotations: map[string]string{"summary": "High error rate on 'myservice' requests responses"},
					PageAlert: slothprometheusv1.Alert{
						Labels: map[string]string{
							"severity":    "page",
							"routing_key": "myteam",
						},
					},
					TicketAlert: slothprometheusv1.Alert{
						Labels: map[string]string{
							"severity":      "slack",
							"slack_channel": "#alerts-myteam",
						},
					},
				},
			},
		},
	}

	ctx := context.Background()

	gen, err := lib.NewPrometheusSLOGenerator(lib.PrometheusSLOGeneratorConfig{
		ExtraLabels: map[string]string{"source": "slothlib-example"},
	})
	if err != nil {
		panic(err)
	}

	// Generate SLO and write result.
	slo, err := gen.GenerateFromSlothV1(ctx, sloSpec)
	if err != nil {
		panic(err)
	}

	err = gen.WriteResultAsPrometheusStd(ctx, *slo, os.Stdout)
	if err != nil {
		panic(err)
	}
}

func (PrometheusSLOGenerator) WriteResultAsK8sObjects added in v0.16.0

func (p PrometheusSLOGenerator) WriteResultAsK8sObjects(ctx context.Context, k8sTransformerPluginID string, k8sMeta model.K8sMeta, slo model.PromSLOGroupResult, w io.Writer) error

WriteResultAsK8sObjects writes the SLO results into the writer as Kubernetes objects using a custom K8s transformer plugin.

func (PrometheusSLOGenerator) WriteResultAsK8sPrometheusOperator

func (p PrometheusSLOGenerator) WriteResultAsK8sPrometheusOperator(ctx context.Context, k8sMeta model.K8sMeta, slo model.PromSLOGroupResult, w io.Writer) error

WriteResultAsK8sPrometheusOperator writes the SLO results into the writer as a Prometheus Operator CRD file. More information in: https://prometheus-operator.dev/docs/api-reference/api/#monitoring.coreos.com/v1.PrometheusRule.

func (PrometheusSLOGenerator) WriteResultAsPrometheusStd

func (p PrometheusSLOGenerator) WriteResultAsPrometheusStd(ctx context.Context, slo model.PromSLOGroupResult, w io.Writer) error

WriteResultAsPrometheusStd writes the SLO results into the writer as a Prometheus standard rules file. More information in:

type PrometheusSLOGeneratorConfig

type PrometheusSLOGeneratorConfig struct {
	// WindowsFS is the FS where custom SLO definition period windows exist (When not set default Sloth windows will be used).
	WindowsFS fs.FS
	// PluginsFS are the FSs where custom SLO and SLI plugins exist.
	PluginsFS []fs.FS
	// StrictPlugins makes the plugin loader fail when a plugin can't be loaded.
	StrictPlugins bool
	// DefaultSLOPeriod is the default SLO period to use when not specified in the SLO definition.
	DefaultSLOPeriod time.Duration
	// DisableDefaultPlugins disables the default SLO plugins, normally used along with custom SLO plugins to fully customize Sloth behavior.
	DisableDefaultPlugins bool
	// CMDSLOPlugins are SLO plugins defined at app level, in other words, they will be executed on all SLOs unless these override the SLO plugin chain.
	CMDSLOPlugins []model.PromSLOPluginMetadata
	// ExtraLabels are labels that will be added to all SLOs.
	ExtraLabels map[string]string
	// CallerAgent is the agent calling the library (The identity or form of calling it).
	CallerAgent CallerAgent
	// Logger is the logger to use for the library.
	Logger log.Logger
}

PrometheusSLOGenerator is the configuration for the Prometheus SLO generator.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL