-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add in some basic metrics to track rule/entity evaluations to the engine. Note that the metrics for alerts and remediations are not wired in yet since they depend on some changes which will be added in the next PR. I have taken a different approach to handling noop metrics than is used in the codebase so far: instead of defining an interface and separate real vs noop implementations, I have decided to make use of the noop metrics handling built into otel: there is now a metrics meter factory with alternative implementation for noop vs "real" metrics. Any part of the code which needs to create metrics can use the factory without caring whether the metrics are actually exported or not. Relates to: #3556
- Loading branch information
Showing
11 changed files
with
232 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright 2023 Stacklok, Inc. | ||
// | ||
// 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 engine | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/google/uuid" | ||
"go.opentelemetry.io/otel/attribute" | ||
"go.opentelemetry.io/otel/metric" | ||
|
||
"github.com/stacklok/minder/internal/db" | ||
"github.com/stacklok/minder/internal/metrics/meters" | ||
) | ||
|
||
// ExecutorMetrics encapsulates metrics operations for the executor | ||
type ExecutorMetrics struct { | ||
evalCounter metric.Int64Counter | ||
remediationCounter metric.Int64Counter | ||
alertCounter metric.Int64Counter | ||
} | ||
|
||
// NewExecutorMetrics instantiates the ExecutorMetrics struct. | ||
func NewExecutorMetrics(meterFactory meters.MeterFactory) (*ExecutorMetrics, error) { | ||
meter := meterFactory.Build("executor") | ||
evalCounter, err := meter.Int64Counter("eval.status", | ||
metric.WithDescription("Number of rule evaluation statuses"), | ||
metric.WithUnit("evaluations")) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create eval counter: %w", err) | ||
} | ||
|
||
remediationCounter, err := meter.Int64Counter("eval.remediation", | ||
metric.WithDescription("Number of remediation statuses"), | ||
metric.WithUnit("evaluations")) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create remediation counter: %w", err) | ||
} | ||
|
||
alertCounter, err := meter.Int64Counter("eval.alert", | ||
metric.WithDescription("Number of alert statuses"), | ||
metric.WithUnit("evaluations")) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create alert counter: %w", err) | ||
} | ||
|
||
return &ExecutorMetrics{ | ||
evalCounter: evalCounter, | ||
remediationCounter: remediationCounter, | ||
alertCounter: alertCounter, | ||
}, nil | ||
} | ||
|
||
// CountEvalStatus counts evaluation events by status. | ||
func (e *ExecutorMetrics) CountEvalStatus( | ||
ctx context.Context, | ||
status db.EvalStatusTypes, | ||
profileID uuid.UUID, | ||
projectID uuid.UUID, | ||
entityID uuid.UUID, | ||
entityType db.Entities, | ||
) { | ||
e.evalCounter.Add(ctx, 1, metric.WithAttributes( | ||
attribute.String("profile_id", profileID.String()), | ||
attribute.String("project_id", projectID.String()), | ||
attribute.String("entity_id", entityID.String()), | ||
attribute.String("entity_type", string(entityType)), | ||
attribute.String("status", string(status)), | ||
)) | ||
} | ||
|
||
// CountRemediationStatus counts remediation events by status. | ||
func (e *ExecutorMetrics) CountRemediationStatus( | ||
ctx context.Context, | ||
status string, | ||
evalID uuid.UUID, | ||
projectID uuid.UUID, | ||
) { | ||
e.evalCounter.Add(ctx, 1, metric.WithAttributes( | ||
attribute.String("profile_id", evalID.String()), | ||
attribute.String("project_id", projectID.String()), | ||
attribute.String("status", status), | ||
)) | ||
} | ||
|
||
// CountAlertStatus counts alert events by status. | ||
func (e *ExecutorMetrics) CountAlertStatus( | ||
ctx context.Context, | ||
status string, | ||
evalID uuid.UUID, | ||
projectID uuid.UUID, | ||
) { | ||
e.evalCounter.Add(ctx, 1, metric.WithAttributes( | ||
attribute.String("profile_id", evalID.String()), | ||
attribute.String("project_id", projectID.String()), | ||
attribute.String("status", status), | ||
)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright 2024 Stacklok, Inc. | ||
// | ||
// 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 entities contains logic relating to entity management | ||
package entities | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/google/uuid" | ||
|
||
"github.com/stacklok/minder/internal/db" | ||
) | ||
|
||
// EntityFromIDs takes the IDs of the three known entity types and | ||
// returns a single ID along with the type of the entity. | ||
// This assumes that exactly one of the IDs is not equal to uuid.Nil | ||
func EntityFromIDs( | ||
repositoryID uuid.UUID, | ||
artifactID uuid.UUID, | ||
pullRequestID uuid.UUID, | ||
) (uuid.UUID, db.Entities, error) { | ||
if repositoryID != uuid.Nil && artifactID == uuid.Nil && pullRequestID == uuid.Nil { | ||
return repositoryID, db.EntitiesRepository, nil | ||
} | ||
if repositoryID == uuid.Nil && artifactID != uuid.Nil && pullRequestID == uuid.Nil { | ||
return artifactID, db.EntitiesArtifact, nil | ||
} | ||
if repositoryID == uuid.Nil && artifactID == uuid.Nil && pullRequestID != uuid.Nil { | ||
return pullRequestID, db.EntitiesPullRequest, nil | ||
} | ||
return uuid.Nil, "", fmt.Errorf("unexpected combination of IDs: %s %s %s", repositoryID, artifactID, pullRequestID) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright 2024 Stacklok, Inc. | ||
// | ||
// 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 meters contains the OpenTelemetry meter factories. | ||
package meters | ||
|
||
import ( | ||
"go.opentelemetry.io/otel" | ||
"go.opentelemetry.io/otel/metric" | ||
"go.opentelemetry.io/otel/metric/noop" | ||
) | ||
|
||
// MeterFactory is an interface which hides the details of creating an | ||
// OpenTelemetry metrics meter. This is used to select between a real exporter | ||
// or noop for testing. | ||
type MeterFactory interface { | ||
// Build creates a meter with the specified name. | ||
Build(name string) metric.Meter | ||
} | ||
|
||
// ExportingMeterFactory uses the "real" OpenTelemetry metric meter | ||
type ExportingMeterFactory struct{} | ||
|
||
// Build creates a meter with the specified name. | ||
func (_ *ExportingMeterFactory) Build(name string) metric.Meter { | ||
return otel.Meter(name) | ||
} | ||
|
||
// NoopMeterFactory returns a noop metrics meter | ||
type NoopMeterFactory struct{} | ||
|
||
// Build returns a noop meter implementation. | ||
func (_ *NoopMeterFactory) Build(_ string) metric.Meter { | ||
return noop.Meter{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters