Skip to content

Commit

Permalink
Add Metrics for TektonChains
Browse files Browse the repository at this point in the history
Added Metrics `chains_reconciled` which tells us
what type of storage, signer and format is being
used during chains installation.
This metrics is use for telemetry.
  • Loading branch information
khrm authored and tekton-robot committed Sep 4, 2023
1 parent cb803c4 commit a05c420
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 1 deletion.
6 changes: 6 additions & 0 deletions pkg/reconciler/kubernetes/tektonchain/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,19 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro
logger.Fatal(err)
}

metrics, err := NewRecorder()
if err != nil {
logger.Fatal(err)
}

c := &Reconciler{
operatorClientSet: operatorclient.Get(ctx),
extension: generator(ctx),
manifest: manifest,
pipelineInformer: tektonPipelineinformer.Get(ctx),
operatorVersion: operatorVer,
chainVersion: chainVer,
recorder: metrics,
}
impl := tektonChainreconciler.NewImpl(ctx, c)

Expand Down
191 changes: 191 additions & 0 deletions pkg/reconciler/kubernetes/tektonchain/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
Copyright 2023 The Tekton 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 tektonchain

import (
"context"
"fmt"
"time"

"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"go.uber.org/zap"
"knative.dev/pkg/metrics"
)

var (
rReconcileCount = stats.Float64("chains_reconciled",
"metrics of chains reconciled with labels",
stats.UnitDimensionless)
)

// Recorder holds keys for Tekton metrics
type Recorder struct {
initialized bool
version tag.Key
taskrunFormat tag.Key
taskrunStorage tag.Key
taskrunSigner tag.Key
pipelinerunFormat tag.Key
pipelinerunStorage tag.Key
pipelinerunSigner tag.Key
ociFormat tag.Key
ociStorage tag.Key
ociSigner tag.Key

ReportingPeriod time.Duration
}

// NewRecorder creates a new metrics recorder instance
// to log the PipelineRun related metrics
func NewRecorder() (*Recorder, error) {
r := &Recorder{
initialized: true,

// Default to 30s intervals.
ReportingPeriod: 30 * time.Second,
}

version, err := tag.NewKey("version")
if err != nil {
return nil, err
}
r.version = version

taskrunFormat, err := tag.NewKey("taskrun_format")
if err != nil {
return nil, err
}
r.taskrunFormat = taskrunFormat

taskrunStorage, err := tag.NewKey("taskrun_storage")
if err != nil {
return nil, err
}
r.taskrunStorage = taskrunStorage

taskrunSigner, err := tag.NewKey("taskrun_signer")
if err != nil {
return nil, err
}
r.taskrunSigner = taskrunSigner

pipelinerunFormat, err := tag.NewKey("pipelinerun_format")
if err != nil {
return nil, err
}
r.pipelinerunFormat = pipelinerunFormat

pipelinerunStorage, err := tag.NewKey("pipelinerun_storage")
if err != nil {
return nil, err
}
r.pipelinerunStorage = pipelinerunStorage

pipelinerunSigner, err := tag.NewKey("pipelinerun_signer")
if err != nil {
return nil, err
}
r.pipelinerunSigner = pipelinerunSigner

ociFormat, err := tag.NewKey("oci_format")
if err != nil {
return nil, err
}
r.ociFormat = ociFormat

ociStorage, err := tag.NewKey("oci_storage")
if err != nil {
return nil, err
}
r.ociStorage = ociStorage

ociSigner, err := tag.NewKey("oci_signer")
if err != nil {
return nil, err
}
r.ociSigner = ociSigner

err = view.Register(
&view.View{
Description: rReconcileCount.Description(),
Measure: rReconcileCount,
Aggregation: view.Count(),
TagKeys: []tag.Key{r.version,
r.taskrunFormat, r.taskrunStorage, r.taskrunSigner,
r.pipelinerunFormat, r.pipelinerunStorage, r.pipelinerunSigner,
r.ociFormat, r.ociStorage, r.ociSigner},
},
)

if err != nil {
r.initialized = false
return r, err
}

return r, nil
}

// Logs when chains is reconciled with version and
// config labels.
func (r *Recorder) Count(version string, spec v1alpha1.TektonChainSpec) error {
if !r.initialized {
return fmt.Errorf(
"ignoring the metrics recording for pipelinee failed to initialize the metrics recorder")
}

var taskrunStorage, pipelinerunStorage, ociStorage string
if spec.ArtifactsTaskRunStorage != nil {
taskrunStorage = *spec.ArtifactsTaskRunStorage
}
if spec.ArtifactsPipelineRunStorage != nil {
pipelinerunStorage = *spec.ArtifactsPipelineRunStorage
}
if spec.ArtifactsOCIStorage != nil {
ociStorage = *spec.ArtifactsOCIStorage
}

ctx, err := tag.New(
context.Background(),
tag.Insert(r.version, version),
tag.Insert(r.taskrunFormat, spec.ArtifactsTaskRunFormat),
tag.Insert(r.taskrunStorage, taskrunStorage),
tag.Insert(r.taskrunSigner, spec.ArtifactsTaskRunSigner),
tag.Insert(r.pipelinerunFormat, spec.ArtifactsPipelineRunFormat),
tag.Insert(r.pipelinerunStorage, pipelinerunStorage),
tag.Insert(r.pipelinerunSigner, spec.ArtifactsPipelineRunSigner),
tag.Insert(r.ociFormat, spec.ArtifactsOCIFormat),
tag.Insert(r.ociStorage, ociStorage),
tag.Insert(r.ociSigner, spec.ArtifactsOCISigner),
)

if err != nil {
return err
}

metrics.Record(ctx, rReconcileCount.M(1))
return nil
}

func (m *Recorder) LogMetrics(version string, spec v1alpha1.TektonChainSpec, logger *zap.SugaredLogger) {
err := m.Count(version, spec)
if err != nil {
logger.Warnf("%v: Failed to log the metrics : %v", v1alpha1.KindTektonResult, err)
}
}
6 changes: 5 additions & 1 deletion pkg/reconciler/kubernetes/tektonchain/tektonchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ type Reconciler struct {
// pipelineInformer provides access to a shared informer and lister for
// TektonPipelines
pipelineInformer pipelineinformer.TektonPipelineInformer
// Metrics Recorder
recorder *Recorder
}

// Check that our Reconciler implements controller.Reconciler
Expand Down Expand Up @@ -99,7 +101,10 @@ var (
// ReconcileKind compares the actual state with the desired, and attempts to
// converge the two.
func (r *Reconciler) ReconcileKind(ctx context.Context, tc *v1alpha1.TektonChain) pkgreconciler.Event {

logger := logging.FromContext(ctx)
defer r.recorder.LogMetrics(r.chainVersion, tc.Spec, logger)

tc.Status.InitializeConditions()
tc.Status.ObservedGeneration = tc.Generation

Expand Down Expand Up @@ -302,7 +307,6 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tc *v1alpha1.TektonChain
if err != nil {
return err
}

return r.updateTektonChainStatus(tc, createdIs)
}

Expand Down

0 comments on commit a05c420

Please sign in to comment.