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

otelgrpc: Add Filter for stats handler #5196

Merged
merged 23 commits into from May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3203812
otelgrpc: Add filter for stats handler
ymtdzzz Mar 3, 2024
93304ee
Add entries to CHANGELOG
ymtdzzz Mar 3, 2024
6da878b
fix CHANGELOG
ymtdzzz Mar 5, 2024
b2268ee
Merge branch 'main' into grpc-stats-filter
ymtdzzz Mar 5, 2024
a67ce81
keep Deprecated comment of `WithInterceptorFilter`
ymtdzzz Mar 6, 2024
bdd913c
deprecate `InterceptorFilter` type
ymtdzzz Mar 6, 2024
f17ccf9
Merge branch 'main' into grpc-stats-filter
ymtdzzz May 6, 2024
0f3cda4
Merge branch 'main' into grpc-stats-filter
dashpole May 6, 2024
24f7819
change the location of `gctx.record` nil check location to reduce hea…
ymtdzzz May 7, 2024
c517508
add documentation for filters and interceptor packages
ymtdzzz May 7, 2024
9e67c22
Merge branch 'main' into grpc-stats-filter
ymtdzzz May 7, 2024
733f3be
fix the location of entries in CHANGELOG
ymtdzzz May 8, 2024
94aa442
Merge branch 'open-telemetry:main' into grpc-stats-filter
ymtdzzz May 8, 2024
02f36b3
more reasonable doc comment for interceptor package
ymtdzzz May 8, 2024
e523a2d
more reasonable doc comment for interceptor package
ymtdzzz May 8, 2024
28f6c1c
Use more appropriate word in the comment of InterceptorFilter
ymtdzzz May 8, 2024
a779640
more reasonable doc comment for filters package
ymtdzzz May 8, 2024
ebabbaa
fix the comment of `Filter`
ymtdzzz May 8, 2024
28a27de
Clearly describe the effects of the change
ymtdzzz May 8, 2024
79cf21a
Merge branch 'main' into grpc-stats-filter
pellared May 8, 2024
d22a1c9
add tests for `stats_handler.go`
ymtdzzz May 9, 2024
a7b6221
Merge branch 'main' into grpc-stats-filter
ymtdzzz May 9, 2024
95bca4e
Merge branch 'main' into grpc-stats-filter
MrAlias May 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `prometheus` and `none` are supported values. You can specify multiple producers separated by a comma.
- Add `WithFallbackMetricProducer` option that adds a fallback if the `OTEL_METRICS_PRODUCERS` is not set or empty.
- The `go.opentelemetry.io/contrib/processors/baggage/baggagetrace` module. This module provides a Baggage Span Processor. (#5404)
- Add gRPC trace `Filter` for stats handler to `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#5196)

### Changed

- The gRPC trace `Filter` for interceptor is renamed to `InterceptorFilter`. (#5196)
- The gRPC trace filter functions `Any`, `All`, `None`, `Not`, `MethodName`, `MethodPrefix`, `FullMethodName`, `ServiceName`, `ServicePrefix` and `HealthCheck` for interceptor are moved to `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters/interceptor`.
With this change, the filters in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc` are now working for stats handler. (#5196)

### Deprecated
pellared marked this conversation as resolved.
Show resolved Hide resolved

- The `InterceptorFilter` type in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc` is deprecated. (#5196)

## [1.26.0/0.51.0/0.20.0/0.6.0/0.1.0] - 2024-04-24

Expand Down
45 changes: 35 additions & 10 deletions instrumentation/google.golang.org/grpc/otelgrpc/config.go
Expand Up @@ -4,6 +4,8 @@
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"

import (
"google.golang.org/grpc/stats"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
Expand All @@ -20,18 +22,26 @@
GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
)

// Filter is a predicate used to determine whether a given request in
// interceptor info should be traced. A Filter must return true if
// InterceptorFilter is a predicate used to determine whether a given request in
// interceptor info should be instrumented. A InterceptorFilter must return true if
// the request should be traced.
type Filter func(*InterceptorInfo) bool
//
// Deprecated: Use stats handlers instead.
type InterceptorFilter func(*InterceptorInfo) bool
dashpole marked this conversation as resolved.
Show resolved Hide resolved

// Filter is a predicate used to determine whether a given request in
// should be instrumented by the attatched RPC tag info.
// A Filter must return true if the request should be instrumented.
type Filter func(*stats.RPCTagInfo) bool

// config is a group of options for this instrumentation.
type config struct {
Filter Filter
Propagators propagation.TextMapPropagator
TracerProvider trace.TracerProvider
MeterProvider metric.MeterProvider
SpanStartOptions []trace.SpanStartOption
Filter Filter
InterceptorFilter InterceptorFilter
Propagators propagation.TextMapPropagator
TracerProvider trace.TracerProvider
MeterProvider metric.MeterProvider
SpanStartOptions []trace.SpanStartOption

ReceivedEvent bool
SentEvent bool
Expand Down Expand Up @@ -152,15 +162,30 @@
// WithInterceptorFilter returns an Option to use the request filter.
//
// Deprecated: Use stats handlers instead.
func WithInterceptorFilter(f Filter) Option {
func WithInterceptorFilter(f InterceptorFilter) Option {

Check warning on line 165 in instrumentation/google.golang.org/grpc/otelgrpc/config.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/google.golang.org/grpc/otelgrpc/config.go#L165

Added line #L165 was not covered by tests
dashpole marked this conversation as resolved.
Show resolved Hide resolved
return interceptorFilterOption{f: f}
}

type interceptorFilterOption struct {
f Filter
f InterceptorFilter
}

func (o interceptorFilterOption) apply(c *config) {
if o.f != nil {
c.InterceptorFilter = o.f

Check warning on line 175 in instrumentation/google.golang.org/grpc/otelgrpc/config.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/google.golang.org/grpc/otelgrpc/config.go#L174-L175

Added lines #L174 - L175 were not covered by tests
}
}

// WithFilter returns an Option to use the request filter.
func WithFilter(f Filter) Option {
return filterOption{f: f}

Check warning on line 181 in instrumentation/google.golang.org/grpc/otelgrpc/config.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/google.golang.org/grpc/otelgrpc/config.go#L180-L181

Added lines #L180 - L181 were not covered by tests
}

type filterOption struct {
f Filter
}

func (o filterOption) apply(c *config) {

Check warning on line 188 in instrumentation/google.golang.org/grpc/otelgrpc/config.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/google.golang.org/grpc/otelgrpc/config.go#L188

Added line #L188 was not covered by tests
if o.f != nil {
c.Filter = o.f
}
Expand Down
@@ -1,12 +1,16 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Package filters provides a set of filters useful with the
// [otelgrpc.WithFilter] option to control which inbound requests are instrumented.
package filters // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters"

import (
"path"
"strings"

"google.golang.org/grpc/stats"

"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
)

Expand All @@ -19,20 +23,8 @@ type gRPCPath struct {
// and returns as gRPCPath object that has divided service and method names
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
// If name is not FullMethod, returned gRPCPath has empty service field.
func splitFullMethod(i *otelgrpc.InterceptorInfo) gRPCPath {
var name string
switch i.Type {
case otelgrpc.UnaryServer:
name = i.UnaryServerInfo.FullMethod
case otelgrpc.StreamServer:
name = i.StreamServerInfo.FullMethod
case otelgrpc.UnaryClient, otelgrpc.StreamClient:
name = i.Method
default:
name = i.Method
}

s, m := path.Split(name)
func splitFullMethod(i *stats.RPCTagInfo) gRPCPath {
s, m := path.Split(i.FullMethodName)
if s != "" {
s = path.Clean(s)
s = strings.TrimLeft(s, "/")
Expand All @@ -47,7 +39,7 @@ func splitFullMethod(i *otelgrpc.InterceptorInfo) gRPCPath {
// Any takes a list of Filters and returns a Filter that
// returns true if any Filter in the list returns true.
func Any(fs ...otelgrpc.Filter) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
for _, f := range fs {
if f(i) {
return true
Expand All @@ -60,7 +52,7 @@ func Any(fs ...otelgrpc.Filter) otelgrpc.Filter {
// All takes a list of Filters and returns a Filter that
// returns true only if all Filters in the list return true.
func All(fs ...otelgrpc.Filter) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
for _, f := range fs {
if !f(i) {
return false
Expand All @@ -78,15 +70,15 @@ func None(fs ...otelgrpc.Filter) otelgrpc.Filter {

// Not provides a convenience mechanism for inverting a Filter.
func Not(f otelgrpc.Filter) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
return !f(i)
}
}

// MethodName returns a Filter that returns true if the request's
// method name matches the provided string n.
func MethodName(n string) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
p := splitFullMethod(i)
return p.method == n
}
Expand All @@ -95,7 +87,7 @@ func MethodName(n string) otelgrpc.Filter {
// MethodPrefix returns a Filter that returns true if the request's
// method starts with the provided string pre.
func MethodPrefix(pre string) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
p := splitFullMethod(i)
return strings.HasPrefix(p.method, pre)
}
Expand All @@ -105,26 +97,15 @@ func MethodPrefix(pre string) otelgrpc.Filter {
// full RPC method string, i.e. /package.service/method, starts with
// the provided string n.
func FullMethodName(n string) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
var fm string
switch i.Type {
case otelgrpc.UnaryClient, otelgrpc.StreamClient:
fm = i.Method
case otelgrpc.UnaryServer:
fm = i.UnaryServerInfo.FullMethod
case otelgrpc.StreamServer:
fm = i.StreamServerInfo.FullMethod
default:
fm = i.Method
}
return fm == n
return func(i *stats.RPCTagInfo) bool {
return i.FullMethodName == n
}
}

// ServiceName returns a Filter that returns true if the request's
// service name, i.e. package.service, matches s.
func ServiceName(s string) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
p := splitFullMethod(i)
return p.service == s
}
Expand All @@ -133,7 +114,7 @@ func ServiceName(s string) otelgrpc.Filter {
// ServicePrefix returns a Filter that returns true if the request's
// service name, i.e. package.service, starts with the provided string pre.
func ServicePrefix(pre string) otelgrpc.Filter {
return func(i *otelgrpc.InterceptorInfo) bool {
return func(i *stats.RPCTagInfo) bool {
p := splitFullMethod(i)
return strings.HasPrefix(p.service, pre)
}
Expand Down