-
Notifications
You must be signed in to change notification settings - Fork 592
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
base: main
Are you sure you want to change the base?
Conversation
Skipping CI for Draft Pull Request. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Leo6Leo 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 |
pkg/broker/filter/filter_handler.go
Outdated
if errors.Is(err, auth.ErrNoJWTTokenFound) { | ||
_ = h.reporter.ReportUnauthenticatedRequest(&ReportArgs{ |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 🤔
/cc @creydr Am I on the right track? I am only doing broker filter for now, just in case my approach is wrong. |
pkg/auth/token_verifier.go
Outdated
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
eventing/pkg/reconciler/testing/v1/broker.go
Lines 35 to 44 in 825202f
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) | |
} |
type BrokerOption func(*v1.Broker)
)? This allows us to add options, without the need to update the packages immediately which use the NewOIDCTokenVerifier
.
Codecov ReportAttention: Patch coverage is
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. |
@@ -147,11 +148,12 @@ func main() { | |||
} | |||
|
|||
reporter := filter.NewStatsReporter(env.ContainerName, kmeta.ChildName(env.PodName, uuid.New().String())) | |||
authReporter := filter.NewAuthStatsReporterAdapter(reporter) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
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. |
This Pull Request is stale because it has been open for 90 days with |
Fixes #7877
Proposed Changes
Pre-review Checklist
Release Note
Docs