Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add metrics for OIDC #8015

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft

Conversation

Leo6Leo
Copy link
Member

@Leo6Leo Leo6Leo commented Jun 20, 2024

Fixes #7877

Proposed Changes

  • Adding the Unauthenticate request count to broker filter ingress, introduce the new report methods in its the stats_reporter

Pre-review Checklist

  • At least 80% unit test coverage
  • E2E tests for any new behavior
  • Docs PR for any user-facing impact
  • Spec PR for any new API feature
  • Conformance test for any change to the spec

Release Note


Docs

Copy link

knative-prow bot commented Jun 20, 2024

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@knative-prow knative-prow bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 20, 2024
Copy link

knative-prow bot commented Jun 20, 2024

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Leo6Leo
Once this PR has been reviewed and has the lgtm label, please assign creydr for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-prow knative-prow bot requested review from aliok and matzew June 20, 2024 05:04
@knative-prow knative-prow bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jun 20, 2024
@Leo6Leo Leo6Leo changed the title Add metrics for OIDC [WIP] Add metrics for OIDC Jun 20, 2024
Comment on lines 213 to 214
if errors.Is(err, auth.ErrNoJWTTokenFound) {
_ = h.reporter.ReportUnauthenticatedRequest(&ReportArgs{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you think the way here to distinguish these 2 different scenario? Are there any better approach you would recommend? @creydr

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can work. You could also think about passing the reporter to the tokenVerifier, so this reports the metrics on each request and not only do this in the caller 🤔

@Leo6Leo
Copy link
Member Author

Leo6Leo commented Jun 20, 2024

/cc @creydr Am I on the right track? I am only doing broker filter for now, just in case my approach is wrong.

@knative-prow knative-prow bot requested a review from creydr June 20, 2024 05:08
Comment on lines 62 to 66
func NewOIDCTokenVerifier(ctx context.Context, statsReporter filter.StatsReporter) *OIDCTokenVerifier {
tokenHandler := &OIDCTokenVerifier{
logger: logging.FromContext(ctx).With("component", "oidc-token-handler"),
restConfig: injection.GetConfig(ctx),
logger: logging.FromContext(ctx).With("component", "oidc-token-handler"),
restConfig: injection.GetConfig(ctx),
statsReporter: statsReporter,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this looks good? @creydr By passing the statsReporter to the verifier, and pass the reportArgs when verifying happens.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this an optional argument (e.g. by using a configuration-option function as we do for example in

func NewBroker(name, namespace string, o ...BrokerOption) *v1.Broker {
b := &v1.Broker{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
},
}
for _, opt := range o {
opt(b)
}
with type BrokerOption func(*v1.Broker))? This allows us to add options, without the need to update the packages immediately which use the NewOIDCTokenVerifier.

Copy link

codecov bot commented Jun 24, 2024

Codecov Report

Attention: Patch coverage is 15.18987% with 67 lines in your changes missing coverage. Please review.

Project coverage is 67.50%. Comparing base (825202f) to head (82f8327).
Report is 23 commits behind head on main.

Files Patch % Lines
pkg/broker/filter/filter_handler.go 0.00% 30 Missing ⚠️
pkg/broker/filter/stats_reporter.go 50.00% 12 Missing ⚠️
pkg/auth/token_verifier.go 0.00% 11 Missing ⚠️
pkg/broker/ingress/ingress_handler.go 0.00% 5 Missing ⚠️
pkg/channel/event_receiver.go 0.00% 5 Missing ⚠️
cmd/broker/filter/main.go 0.00% 2 Missing ⚠️
cmd/jobsink/main.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8015      +/-   ##
==========================================
- Coverage   67.79%   67.50%   -0.29%     
==========================================
  Files         363      364       +1     
  Lines       16899    17113     +214     
==========================================
+ Hits        11456    11552      +96     
- Misses       4735     4841     +106     
- Partials      708      720      +12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -147,11 +148,12 @@ func main() {
}

reporter := filter.NewStatsReporter(env.ContainerName, kmeta.ChildName(env.PodName, uuid.New().String()))
authReporter := filter.NewAuthStatsReporterAdapter(reporter)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating an interface to avoid import cycle.

Before this, it is stuck with a import cycle between auth and filter packages. The auth code needs filter's stats reporting, but filter is already using auth stuff. To fix this I created a simple interface in auth that just covers the stats we need. Then making an adapter in filter to bridge the gap. Is this a good approach to solve this problem?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is not only relevant to broker-filters anymore, should we move this StatsReporter to a dedicated package and make it more generic? E.g. pkg/metrics?
(This could also help to remove the import cycle.)

Then you could also change the ReportArgs to an interface (which has the method generateTag()) to have component specific args. E.g. from a Trigger (which would to the same as the current reporter.generateTag(), or then for a Channel, etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for example:

type ReportArgs interface { //TODO: find a better name
    generateTag(tags ...tag.Mutator) (context.Context, error)
}

and then for example for the broker/trigger:

type BrokerArgs struct {
	ns            string
	trigger       string
	broker        string
	filterType    string
	requestType   string
	requestScheme string
}

func (args *BrokerArgs) generateTag(tags ...tag.Mutator) (context.Context, error) {
	ctx := metricskey.WithResource(emptyContext, resource.Resource{
		Type: eventingmetrics.ResourceTypeKnativeTrigger,
		Labels: map[string]string{
			eventingmetrics.LabelNamespaceName: args.ns,
			eventingmetrics.LabelBrokerName:    args.broker,
			eventingmetrics.LabelTriggerName:   args.trigger,
		},
	})
	// Note that filterType and filterSource can be empty strings, so they need a special treatment.
	ctx, err := tag.New(
		ctx,
		append(tags,
			tag.Insert(triggerFilterTypeKey, valueOrAny(args.filterType)),
			tag.Insert(triggerFilterRequestTypeKey, args.requestType),
			tag.Insert(triggerFilterRequestSchemeKey, args.requestScheme),
		)...)
	return ctx, err
}

And then we call this e.g. in ReportEventCount():

func (r *reporter) ReportEventCount(args ReportArgs, responseCode int) error {
	ctx, err := args.generateTag(
		tag.Insert(responseCodeKey, strconv.Itoa(responseCode)),
		tag.Insert(responseCodeClassKey, metrics.ResponseCodeClass(responseCode)))
	if err != nil {
		return err
	}
	metrics.Record(ctx, eventCountM.M(1))
	return nil
}

and use it

reportArgs := &BrokerArgs{
	Ns:          broker.Namespace,
	Broker:      broker.Name,
	RequestType: "broker_ingress",
}

err = h.tokenVerifier.VerifyJWTFromRequest(ctx, request, broker.Status.Address.Audience, writer, reportArgs)

@knative-prow-robot knative-prow-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 4, 2024
@knative-prow-robot
Copy link
Contributor

PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add metrics for OIDC
3 participants