github.com/kubeshop/testkube@v1.17.23/internal/app/api/metrics/metrics.go (about)

     1  package metrics
     2  
     3  import (
     4  	"fmt"
     5  	"slices"
     6  	"strings"
     7  
     8  	"github.com/prometheus/client_golang/prometheus"
     9  	"github.com/prometheus/client_golang/prometheus/promauto"
    10  
    11  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    12  )
    13  
    14  var testExecutionsCount = promauto.NewCounterVec(prometheus.CounterOpts{
    15  	Name: "testkube_test_executions_count",
    16  	Help: "The total number of test executions",
    17  }, []string{"type", "name", "result", "labels", "test_uri"})
    18  
    19  var testExecutionsDurationMs = promauto.NewSummaryVec(prometheus.SummaryOpts{
    20  	Name:       "testkube_test_executions_duration_ms",
    21  	Help:       "The duration of test executions",
    22  	Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.95: 0.005, 0.99: 0.001},
    23  }, []string{"type", "name", "result", "labels", "test_uri"})
    24  
    25  var testSuiteExecutionsCount = promauto.NewCounterVec(prometheus.CounterOpts{
    26  	Name: "testkube_testsuite_executions_count",
    27  	Help: "The total number of test suite executions",
    28  }, []string{"name", "result", "labels", "testsuite_uri"})
    29  
    30  var testSuiteExecutionsDurationMs = promauto.NewSummaryVec(prometheus.SummaryOpts{
    31  	Name:       "testkube_testsuite_executions_duration_ms",
    32  	Help:       "The duration of test suite executions",
    33  	Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.95: 0.005, 0.99: 0.001},
    34  }, []string{"name", "result", "labels", "testsuite_uri"})
    35  
    36  var testCreationCount = promauto.NewCounterVec(prometheus.CounterOpts{
    37  	Name: "testkube_test_creations_count",
    38  	Help: "The total number of tests created by type events",
    39  }, []string{"type", "result"})
    40  
    41  var testSuiteCreationCount = promauto.NewCounterVec(prometheus.CounterOpts{
    42  	Name: "testkube_testsuite_creations_count",
    43  	Help: "The total number of test suites created events",
    44  }, []string{"result"})
    45  
    46  var testUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    47  	Name: "testkube_test_updates_count",
    48  	Help: "The total number of tests updated by type events",
    49  }, []string{"type", "result"})
    50  
    51  var testSuiteUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    52  	Name: "testkube_testsuite_updates_count",
    53  	Help: "The total number of test suites updated events",
    54  }, []string{"result"})
    55  
    56  var testTriggerCreationCount = promauto.NewCounterVec(prometheus.CounterOpts{
    57  	Name: "testkube_testtrigger_creations_count",
    58  	Help: "The total number of test trigger created events",
    59  }, []string{"result"})
    60  
    61  var testTriggerUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    62  	Name: "testkube_testtriggers_updates_count",
    63  	Help: "The total number of test trigger updated events",
    64  }, []string{"result"})
    65  
    66  var testTriggerDeletesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    67  	Name: "testkube_testtriggers_deletes_count",
    68  	Help: "The total number of test trigger deleted events",
    69  }, []string{"result"})
    70  
    71  var testTriggerBulkUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    72  	Name: "testkube_testtriggers_bulk_updates_count",
    73  	Help: "The total number of test trigger bulk update events",
    74  }, []string{"result"})
    75  
    76  var testTriggerBulkDeletesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    77  	Name: "testkube_testtriggers_bulk_deletes_count",
    78  	Help: "The total number of test trigger bulk delete events",
    79  }, []string{"result"})
    80  
    81  var testAbortCount = promauto.NewCounterVec(prometheus.CounterOpts{
    82  	Name: "testkube_test_aborts_count",
    83  	Help: "The total number of tests aborted by type events",
    84  }, []string{"type", "result"})
    85  
    86  var testWorkflowCreationCount = promauto.NewCounterVec(prometheus.CounterOpts{
    87  	Name: "testkube_testworkflow_creations_count",
    88  	Help: "The total number of test workflow created by type events",
    89  }, []string{"result"})
    90  
    91  var testWorkflowUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    92  	Name: "testkube_testworkflow_updates_count",
    93  	Help: "The total number of test workflow updated by type events",
    94  }, []string{"result"})
    95  
    96  var testWorkflowDeletesCount = promauto.NewCounterVec(prometheus.CounterOpts{
    97  	Name: "testkube_testworkflow_deletes_count",
    98  	Help: "The total number of test workflow deleted events",
    99  }, []string{"result"})
   100  
   101  var testWorkflowTemplateCreationCount = promauto.NewCounterVec(prometheus.CounterOpts{
   102  	Name: "testkube_testworkflowtemplate_creations_count",
   103  	Help: "The total number of test workflow template created by type events",
   104  }, []string{"result"})
   105  
   106  var testWorkflowTemplateUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{
   107  	Name: "testkube_testworkflowtemplate_updates_count",
   108  	Help: "The total number of test workflow template updated by type events",
   109  }, []string{"result"})
   110  
   111  var testWorkflowTemplateDeletesCount = promauto.NewCounterVec(prometheus.CounterOpts{
   112  	Name: "testkube_testworkflowtemplate_deletes_count",
   113  	Help: "The total number of test workflow template deleted events",
   114  }, []string{"result"})
   115  
   116  func NewMetrics() Metrics {
   117  	return Metrics{
   118  		TestExecutionsCount:           testExecutionsCount,
   119  		TestExecutionsDurationMs:      testExecutionsDurationMs,
   120  		TestSuiteExecutionsCount:      testSuiteExecutionsCount,
   121  		TestSuiteExecutionsDurationMs: testSuiteExecutionsDurationMs,
   122  		TestCreations:                 testCreationCount,
   123  		TestSuiteCreations:            testSuiteCreationCount,
   124  		TestUpdates:                   testUpdatesCount,
   125  		TestSuiteUpdates:              testSuiteUpdatesCount,
   126  		TestTriggerCreations:          testTriggerCreationCount,
   127  		TestTriggerUpdates:            testTriggerUpdatesCount,
   128  		TestTriggerDeletes:            testTriggerDeletesCount,
   129  		TestTriggerBulkUpdates:        testTriggerBulkUpdatesCount,
   130  		TestTriggerBulkDeletes:        testTriggerBulkDeletesCount,
   131  		TestAbort:                     testAbortCount,
   132  		TestWorkflowCreations:         testWorkflowCreationCount,
   133  		TestWorkflowUpdates:           testWorkflowUpdatesCount,
   134  		TestWorkflowDeletes:           testWorkflowDeletesCount,
   135  		TestWorkflowTemplateCreations: testWorkflowTemplateCreationCount,
   136  		TestWorkflowTemplateUpdates:   testWorkflowTemplateUpdatesCount,
   137  		TestWorkflowTemplateDeletes:   testWorkflowTemplateDeletesCount,
   138  	}
   139  }
   140  
   141  type Metrics struct {
   142  	TestExecutionsCount           *prometheus.CounterVec
   143  	TestExecutionsDurationMs      *prometheus.SummaryVec
   144  	TestSuiteExecutionsCount      *prometheus.CounterVec
   145  	TestSuiteExecutionsDurationMs *prometheus.SummaryVec
   146  	TestCreations                 *prometheus.CounterVec
   147  	TestSuiteCreations            *prometheus.CounterVec
   148  	TestUpdates                   *prometheus.CounterVec
   149  	TestSuiteUpdates              *prometheus.CounterVec
   150  	TestTriggerCreations          *prometheus.CounterVec
   151  	TestTriggerUpdates            *prometheus.CounterVec
   152  	TestTriggerDeletes            *prometheus.CounterVec
   153  	TestTriggerBulkUpdates        *prometheus.CounterVec
   154  	TestTriggerBulkDeletes        *prometheus.CounterVec
   155  	TestAbort                     *prometheus.CounterVec
   156  	TestWorkflowCreations         *prometheus.CounterVec
   157  	TestWorkflowUpdates           *prometheus.CounterVec
   158  	TestWorkflowDeletes           *prometheus.CounterVec
   159  	TestWorkflowTemplateCreations *prometheus.CounterVec
   160  	TestWorkflowTemplateUpdates   *prometheus.CounterVec
   161  	TestWorkflowTemplateDeletes   *prometheus.CounterVec
   162  }
   163  
   164  func (m Metrics) IncAndObserveExecuteTest(execution testkube.Execution, dashboardURI string) {
   165  	status := ""
   166  	if execution.ExecutionResult != nil && execution.ExecutionResult.Status != nil {
   167  		status = string(*execution.ExecutionResult.Status)
   168  	}
   169  
   170  	var labels []string
   171  	for key, value := range execution.Labels {
   172  		labels = append(labels, fmt.Sprintf("%s=%s", key, value))
   173  	}
   174  
   175  	slices.Sort(labels)
   176  	m.TestExecutionsCount.With(map[string]string{
   177  		"type":     execution.TestType,
   178  		"name":     execution.TestName,
   179  		"result":   status,
   180  		"labels":   strings.Join(labels, ","),
   181  		"test_uri": fmt.Sprintf("%s/tests/%s", dashboardURI, execution.TestName),
   182  	}).Inc()
   183  
   184  	m.TestExecutionsDurationMs.With(map[string]string{
   185  		"type":     execution.TestType,
   186  		"name":     execution.TestName,
   187  		"result":   status,
   188  		"labels":   strings.Join(labels, ","),
   189  		"test_uri": fmt.Sprintf("%s/tests/%s", dashboardURI, execution.TestName),
   190  	}).Observe(float64(execution.DurationMs))
   191  }
   192  
   193  func (m Metrics) IncAndObserveExecuteTestSuite(execution testkube.TestSuiteExecution, dashboardURI string) {
   194  	name := ""
   195  	status := ""
   196  	if execution.TestSuite != nil {
   197  		name = execution.TestSuite.Name
   198  	}
   199  
   200  	if execution.Status != nil {
   201  		status = string(*execution.Status)
   202  	}
   203  
   204  	var labels []string
   205  	for key, value := range execution.Labels {
   206  		labels = append(labels, fmt.Sprintf("%s=%s", key, value))
   207  	}
   208  
   209  	slices.Sort(labels)
   210  	testSuiteName := ""
   211  	if execution.TestSuite != nil {
   212  		testSuiteName = execution.TestSuite.Name
   213  	}
   214  
   215  	m.TestSuiteExecutionsCount.With(map[string]string{
   216  		"name":          name,
   217  		"result":        status,
   218  		"labels":        strings.Join(labels, ","),
   219  		"testsuite_uri": fmt.Sprintf("%s/test-suites/%s", dashboardURI, testSuiteName),
   220  	}).Inc()
   221  
   222  	m.TestSuiteExecutionsDurationMs.With(map[string]string{
   223  		"name":          name,
   224  		"result":        status,
   225  		"labels":        strings.Join(labels, ","),
   226  		"testsuite_uri": fmt.Sprintf("%s/test-suites/%s", dashboardURI, testSuiteName),
   227  	}).Observe(float64(execution.DurationMs))
   228  }
   229  
   230  func (m Metrics) IncUpdateTest(testType string, err error) {
   231  	result := "updated"
   232  	if err != nil {
   233  		result = "error"
   234  	}
   235  
   236  	m.TestUpdates.With(map[string]string{
   237  		"type":   testType,
   238  		"result": result,
   239  	}).Inc()
   240  }
   241  
   242  func (m Metrics) IncUpdateTestSuite(err error) {
   243  	result := "updated"
   244  	if err != nil {
   245  		result = "error"
   246  	}
   247  
   248  	m.TestSuiteUpdates.With(map[string]string{
   249  		"result": result,
   250  	}).Inc()
   251  }
   252  
   253  func (m Metrics) IncCreateTest(testType string, err error) {
   254  	result := "created"
   255  	if err != nil {
   256  		result = "error"
   257  	}
   258  
   259  	m.TestCreations.With(map[string]string{
   260  		"type":   testType,
   261  		"result": result,
   262  	}).Inc()
   263  }
   264  
   265  func (m Metrics) IncCreateTestSuite(err error) {
   266  	result := "created"
   267  	if err != nil {
   268  		result = "error"
   269  	}
   270  
   271  	m.TestSuiteCreations.With(map[string]string{
   272  		"result": result,
   273  	}).Inc()
   274  }
   275  
   276  func (m Metrics) IncCreateTestTrigger(err error) {
   277  	result := "created"
   278  	if err != nil {
   279  		result = "error"
   280  	}
   281  
   282  	m.TestTriggerCreations.With(map[string]string{
   283  		"result": result,
   284  	}).Inc()
   285  }
   286  
   287  func (m Metrics) IncUpdateTestTrigger(err error) {
   288  	result := "updated"
   289  	if err != nil {
   290  		result = "error"
   291  	}
   292  
   293  	m.TestTriggerUpdates.With(map[string]string{
   294  		"result": result,
   295  	}).Inc()
   296  }
   297  
   298  func (m Metrics) IncDeleteTestTrigger(err error) {
   299  	result := "deleted"
   300  	if err != nil {
   301  		result = "error"
   302  	}
   303  
   304  	m.TestTriggerDeletes.With(map[string]string{
   305  		"result": result,
   306  	}).Inc()
   307  }
   308  
   309  func (m Metrics) IncBulkUpdateTestTrigger(err error) {
   310  	result := "bulk_update"
   311  	if err != nil {
   312  		result = "error"
   313  	}
   314  
   315  	m.TestTriggerBulkUpdates.With(map[string]string{
   316  		"result": result,
   317  	}).Inc()
   318  }
   319  
   320  func (m Metrics) IncBulkDeleteTestTrigger(err error) {
   321  	result := "bulk_delete"
   322  	if err != nil {
   323  		result = "error"
   324  	}
   325  
   326  	m.TestTriggerBulkDeletes.With(map[string]string{
   327  		"result": result,
   328  	}).Inc()
   329  }
   330  
   331  func (m Metrics) IncAbortTest(testType string, failed bool) {
   332  	result := "aborted"
   333  	if failed {
   334  		result = "error"
   335  	}
   336  
   337  	m.TestAbort.With(map[string]string{
   338  		"type":   testType,
   339  		"result": result,
   340  	}).Inc()
   341  }
   342  
   343  func (m Metrics) IncCreateTestWorkflow(err error) {
   344  	result := "created"
   345  	if err != nil {
   346  		result = "error"
   347  	}
   348  
   349  	m.TestWorkflowCreations.With(map[string]string{
   350  		"result": result,
   351  	}).Inc()
   352  }
   353  
   354  func (m Metrics) IncUpdateTestWorkflow(err error) {
   355  	result := "updated"
   356  	if err != nil {
   357  		result = "error"
   358  	}
   359  
   360  	m.TestWorkflowUpdates.With(map[string]string{
   361  		"result": result,
   362  	}).Inc()
   363  }
   364  
   365  func (m Metrics) IncDeleteTestWorkflow(err error) {
   366  	result := "deleted"
   367  	if err != nil {
   368  		result = "error"
   369  	}
   370  
   371  	m.TestWorkflowDeletes.With(map[string]string{
   372  		"result": result,
   373  	}).Inc()
   374  }
   375  
   376  func (m Metrics) IncCreateTestWorkflowTemplate(err error) {
   377  	result := "created"
   378  	if err != nil {
   379  		result = "error"
   380  	}
   381  
   382  	m.TestWorkflowTemplateCreations.With(map[string]string{
   383  		"result": result,
   384  	}).Inc()
   385  }
   386  
   387  func (m Metrics) IncUpdateTestWorkflowTemplate(err error) {
   388  	result := "updated"
   389  	if err != nil {
   390  		result = "error"
   391  	}
   392  
   393  	m.TestWorkflowTemplateUpdates.With(map[string]string{
   394  		"result": result,
   395  	}).Inc()
   396  }
   397  
   398  func (m Metrics) IncDeleteTestWorkflowTemplate(err error) {
   399  	result := "deleted"
   400  	if err != nil {
   401  		result = "error"
   402  	}
   403  
   404  	m.TestWorkflowTemplateDeletes.With(map[string]string{
   405  		"result": result,
   406  	}).Inc()
   407  }