From ae0ba6ed26889add2e9e6c1be6e6c12e7cc98e9e Mon Sep 17 00:00:00 2001 From: kristinaspring Date: Thu, 9 May 2019 12:41:03 -0700 Subject: [PATCH] Added metrics for bascule (#405) * Added metrics for bascule * Small Fixes * removed json tags * added nil check * updated glide --- basculechecks/metricListener.go | 82 +++++++++++++++++++++++++++++++++ basculechecks/metrics.go | 59 ++++++++++++++++++++++++ basculechecks/metrics_test.go | 17 +++++++ glide.lock | 8 ++-- glide.yaml | 2 + 5 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 basculechecks/metricListener.go create mode 100644 basculechecks/metrics.go create mode 100644 basculechecks/metrics_test.go diff --git a/basculechecks/metricListener.go b/basculechecks/metricListener.go new file mode 100644 index 00000000..862a2cf3 --- /dev/null +++ b/basculechecks/metricListener.go @@ -0,0 +1,82 @@ +package basculechecks + +import ( + "time" + + "github.com/Comcast/comcast-bascule/bascule" + "github.com/Comcast/comcast-bascule/bascule/basculehttp" + "github.com/SermoDigital/jose/jwt" +) + +type MetricListener struct { + expLeeway time.Duration + nbfLeeway time.Duration + measures *JWTValidationMeasures +} + +func (m *MetricListener) OnAuthenticated(auth bascule.Authentication) { + now := time.Now() + + if m.measures == nil { + return // measure tools are not defined, skip + } + + if auth.Token == nil { + return + } + + c, ok := auth.Token.Attributes().Get("claims") + if !ok { + return // if there aren't any claims, skip + } + claims, ok := c.(jwt.Claims) + if !ok { + return // if claims aren't what we expect, skip + } + + //how far did we land from the NBF (in seconds): ie. -1 means 1 sec before, 1 means 1 sec after + if nbf, nbfPresent := claims.NotBefore(); nbfPresent { + nbf = nbf.Add(-m.nbfLeeway) + offsetToNBF := now.Sub(nbf).Seconds() + m.measures.NBFHistogram.Observe(offsetToNBF) + } + + //how far did we land from the EXP (in seconds): ie. -1 means 1 sec before, 1 means 1 sec after + if exp, expPresent := claims.Expiration(); expPresent { + exp = exp.Add(m.expLeeway) + offsetToEXP := now.Sub(exp).Seconds() + m.measures.ExpHistogram.Observe(offsetToEXP) + } +} + +func (m *MetricListener) OnErrorResponse(e basculehttp.ErrorResponseReason, _ error) { + if m.measures == nil { + return + } + m.measures.ValidationReason.With(ReasonLabel, e.String()).Add(1) +} + +type Option func(m *MetricListener) + +func WithExpLeeway(e time.Duration) Option { + return func(m *MetricListener) { + m.expLeeway = e + } +} + +func WithNbfLeeway(n time.Duration) Option { + return func(m *MetricListener) { + m.nbfLeeway = n + } +} + +func NewMetricListener(m *JWTValidationMeasures, options ...Option) *MetricListener { + listener := MetricListener{ + measures: m, + } + + for _, o := range options { + o(&listener) + } + return &listener +} diff --git a/basculechecks/metrics.go b/basculechecks/metrics.go new file mode 100644 index 00000000..d8a5ebd0 --- /dev/null +++ b/basculechecks/metrics.go @@ -0,0 +1,59 @@ +package basculechecks + +import ( + "github.com/Comcast/webpa-common/xmetrics" + "github.com/go-kit/kit/metrics" + gokitprometheus "github.com/go-kit/kit/metrics/prometheus" +) + +//Names for our metrics +const ( + JWTValidationReasonCounter = "jwt_validation_reason" + NBFHistogram = "jwt_from_nbf_seconds" + EXPHistogram = "jwt_from_exp_seconds" +) + +// labels +const ( + ReasonLabel = "reason" +) + +//Metrics returns the Metrics relevant to this package +func Metrics() []xmetrics.Metric { + return []xmetrics.Metric{ + xmetrics.Metric{ + Name: JWTValidationReasonCounter, + Type: xmetrics.CounterType, + Help: "Counter for validation resolutions per reason", + LabelNames: []string{ReasonLabel}, + }, + xmetrics.Metric{ + Name: NBFHistogram, + Type: xmetrics.HistogramType, + Help: "Difference (in seconds) between time of JWT validation and nbf (including leeway)", + Buckets: []float64{-61, -11, -2, -1, 0, 9, 60}, // defines the upper inclusive (<=) bounds + }, + xmetrics.Metric{ + Name: EXPHistogram, + Type: xmetrics.HistogramType, + Help: "Difference (in seconds) between time of JWT validation and exp (including leeway)", + Buckets: []float64{-61, -11, -2, -1, 0, 9, 60}, + }, + } +} + +//JWTValidationMeasures describes the defined metrics that will be used by clients +type JWTValidationMeasures struct { + NBFHistogram *gokitprometheus.Histogram + ExpHistogram *gokitprometheus.Histogram + ValidationReason metrics.Counter +} + +//NewJWTValidationMeasures realizes desired metrics +func NewJWTValidationMeasures(r xmetrics.Registry) *JWTValidationMeasures { + return &JWTValidationMeasures{ + NBFHistogram: gokitprometheus.NewHistogram(r.NewHistogramVec(NBFHistogram)), + ExpHistogram: gokitprometheus.NewHistogram(r.NewHistogramVec(EXPHistogram)), + ValidationReason: r.NewCounter(JWTValidationReasonCounter), + } +} diff --git a/basculechecks/metrics_test.go b/basculechecks/metrics_test.go new file mode 100644 index 00000000..395e1eee --- /dev/null +++ b/basculechecks/metrics_test.go @@ -0,0 +1,17 @@ +package basculechecks + +import ( + "testing" + + "github.com/Comcast/webpa-common/xmetrics" + "github.com/stretchr/testify/assert" +) + +func newTestJWTValidationMeasure() *JWTValidationMeasures { + return NewJWTValidationMeasures(xmetrics.MustNewRegistry(nil, Metrics)) +} + +func TestSimpleRun(t *testing.T) { + assert := assert.New(t) + assert.NotNil(newTestJWTValidationMeasure()) +} diff --git a/glide.lock b/glide.lock index 574f7f79..3fc1aad2 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 84b449a3e91a0a407971a51280c26c3424575ac3027d6fd27dca9da7aeff3d93 -updated: 2019-04-29T14:45:02.618881-07:00 +hash: 4d5e3d41486de857b378cad488dbb9f68c6ea974cc7fa9df3a05e103c35d2a9a +updated: 2019-05-09T12:35:59.911709-07:00 imports: - name: github.com/armon/go-metrics version: f0300d1749da6fa982027e449ec0c7a145510c3c @@ -44,9 +44,11 @@ imports: - name: github.com/cenk/backoff version: 2ea60e5f094469f9e65adb9cd103795b73ae743e - name: github.com/Comcast/comcast-bascule - version: 53d4ab33154832b26e4767505ff3bc3c44c52f38 + version: d07d9e49941c9a0998295574bf6b885148666742 subpackages: - bascule + - bascule/basculehttp + - bascule/key - name: github.com/davecgh/go-spew version: 346938d642f2ec3594ed81d874461961cd0faa76 subpackages: diff --git a/glide.yaml b/glide.yaml index db58834f..c1eb8401 100644 --- a/glide.yaml +++ b/glide.yaml @@ -65,3 +65,5 @@ import: version: v0.9.2 - package: github.com/miekg/dns version: v1.0.12 +- package: github.com/Comcast/comcast-bascule + version: v0.2.5