grpc

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// StateClosed admits all RPCs; failures are counted.
	StateClosed = CircuitState(resilience.StateClosed)
	// StateOpen rejects all RPCs immediately with codes.Unavailable until the
	// cooldown elapses, then transitions to StateHalfOpen.
	StateOpen = CircuitState(resilience.StateOpen)
	// StateHalfOpen admits a limited number of trial RPCs; success closes the
	// breaker, failure re-opens it.
	StateHalfOpen = CircuitState(resilience.StateHalfOpen)
)

The public states are derived from the shared core so the two enumerations can never silently drift out of order.

Variables

This section is empty.

Functions

func CircuitBreakerInterceptor

func CircuitBreakerInterceptor(log *slog.Logger, cfg CircuitBreakerConfig) grpc.UnaryClientInterceptor

CircuitBreakerInterceptor returns a unary client interceptor that opens when a downstream is consistently failing and rejects calls with codes.Unavailable while open, avoiding wasted calls against a service known to be down. Install it via grpc.WithChainUnaryInterceptor.

func CircuitBreakerStreamInterceptor

func CircuitBreakerStreamInterceptor(log *slog.Logger, cfg CircuitBreakerConfig) grpc.StreamClientInterceptor

CircuitBreakerStreamInterceptor returns a stream client interceptor with the same breaker semantics. Successful stream ESTABLISHMENT is the breaker verdict for the call (in HalfOpen it is the trial verdict, releasing the trial slot immediately) — a long-lived or abandoned stream therefore never holds the half-open trial slot for its lifetime. The ClientStream is still wrapped so per-message errors (a RecvMsg/SendMsg that returns a classified failure) count against the breaker's Closed-state failure threshold and can re-trip it; a clean io.EOF reports nothing further.

func OTelClientHandler

func OTelClientHandler(opts ...otelgrpc.Option) grpc.DialOption

OTelClientHandler returns a grpc.DialOption that instruments a client connection with OpenTelemetry: a client span per RPC, and — using the global propagator — the trace context injected into the outgoing metadata, so a downstream gRPC server continues the same trace rather than starting a new one. It reads the globally-installed providers (see telemetry.Setup) and is a noop until those are installed. The gateway applies it by default, so a REST request and the gRPC call it proxies land in one trace.

func OTelStatsHandler

func OTelStatsHandler(opts ...otelgrpc.Option) grpc.ServerOption

OTelStatsHandler returns a grpc.ServerOption that installs OpenTelemetry instrumentation for every RPC — server spans and the standard server metrics (rpc.server.*) — reading whichever TracerProvider and MeterProvider are installed as the OTel globals (see telemetry.Setup). It is a stats handler rather than an interceptor because that is the instrumentation the OTel gRPC contrib library ships and the shape the semantic conventions are defined against.

Pass it to Register alongside any other server options:

grpc.RegisterFromContainable(ctx, "grpc", controller, cfg, log, grpc.OTelStatsHandler())

func PeerKey

func PeerKey(ctx context.Context, _ string) string

PeerKey is a ready-made KeyFunc keying on the RPC peer address. RPCs with no resolvable peer share a single bucket under the empty key.

Types

type CircuitBreakerConfig

type CircuitBreakerConfig struct {
	// FailureThreshold is the number of consecutive failures (in Closed) that
	// trips the breaker open. Must be >= 1. Default: 5.
	FailureThreshold int `mapstructure:"failure_threshold" yaml:"failure_threshold" json:"failure_threshold"`
	// Cooldown is how long the breaker stays Open before a trial. Default: 30s.
	Cooldown time.Duration `mapstructure:"cooldown" yaml:"cooldown" json:"cooldown"`
	// HalfOpenMaxRequests is the number of trial RPCs allowed in HalfOpen.
	// Must be >= 1. Default: 1.
	HalfOpenMaxRequests int `mapstructure:"half_open_max_requests" yaml:"half_open_max_requests" json:"half_open_max_requests"`

	// IsFailure classifies an RPC outcome. When nil, the default treats
	// Unavailable and DeadlineExceeded as failures and every other code
	// (including OK and ResourceExhausted) as a success.
	//
	// ResourceExhausted is deliberately NOT a failure: like an HTTP 429 it means
	// "you are being rate-limited", which is the retry/backoff layer's concern,
	// not a signal that the downstream is unhealthy. Counting it would let a
	// server's own rate limiter trip its callers' breakers. Supply a custom
	// IsFailure to change this.
	IsFailure func(err error) bool `mapstructure:"-" yaml:"-" json:"-"`

	// OnStateChange is invoked on every state transition. Optional; transitions
	// are also logged via the constructor's logger.
	OnStateChange func(from, to CircuitState) `mapstructure:"-" yaml:"-" json:"-"`
}

CircuitBreakerConfig configures the client-side circuit breaker for gRPC.

func DefaultCircuitBreakerConfig

func DefaultCircuitBreakerConfig() CircuitBreakerConfig

DefaultCircuitBreakerConfig returns: threshold 5, cooldown 30s, half-open trial 1, default Unavailable/DeadlineExceeded failure classification.

func MergeCircuitBreakerConfig

func MergeCircuitBreakerConfig(base, override CircuitBreakerConfig, fields CircuitBreakerConfigOverrides) CircuitBreakerConfig

MergeCircuitBreakerConfig applies explicitly supplied typed override values to base while leaving code-only function fields under caller control.

type CircuitBreakerConfigOverrides

type CircuitBreakerConfigOverrides struct {
	FailureThreshold    bool
	Cooldown            bool
	HalfOpenMaxRequests bool
}

CircuitBreakerConfigOverrides records which typed circuit breaker config fields were explicitly supplied by an adapter.

type CircuitState

type CircuitState int

CircuitState is the client circuit breaker's state.

func (CircuitState) String

func (s CircuitState) String() string

String renders the state for logging.

type GRPCLoggingOption

type GRPCLoggingOption func(*grpcLoggingConfig)

GRPCLoggingOption configures gRPC transport logging behaviour.

func WithGRPCLogLevel

func WithGRPCLogLevel(level slog.Level) GRPCLoggingOption

WithGRPCLogLevel sets the log level for successful RPCs. Errors always log at slog.LevelError.

func WithGRPCPathFilter

func WithGRPCPathFilter(methods ...string) GRPCLoggingOption

WithGRPCPathFilter excludes RPCs matching the given full method names from logging.

func WithoutGRPCLatency

func WithoutGRPCLatency() GRPCLoggingOption

WithoutGRPCLatency disables the "latency" field.

type Interceptor

type Interceptor struct {
	Unary  grpc.UnaryServerInterceptor
	Stream grpc.StreamServerInterceptor
}

Interceptor groups a paired unary and stream interceptor. Either field may be nil if the interceptor only applies to one RPC type.

func LoggingInterceptor

func LoggingInterceptor(l *slog.Logger, opts ...GRPCLoggingOption) Interceptor

LoggingInterceptor returns an Interceptor (unary + stream) that logs each completed RPC.

func RateLimitInterceptor

func RateLimitInterceptor(log *slog.Logger, cfg RateLimitConfig) Interceptor

RateLimitInterceptor returns an Interceptor (unary + stream) that admits RPCs under a token-bucket limiter and rejects excess with codes.ResourceExhausted. It composes into any InterceptorChain. Per-method or per-client scoping is achieved by setting KeyFunc (e.g. PeerKey, or a func keying on fullMethod).

Like the HTTP limiter, admission is non-blocking (Allow, not Wait): ingress must reject excess, never queue it, or a flood would exhaust memory.

type InterceptorChain

type InterceptorChain struct {
	// contains filtered or unexported fields
}

InterceptorChain composes zero or more gRPC interceptors into ordered slices suitable for grpc.ChainUnaryInterceptor and grpc.ChainStreamInterceptor.

func NewInterceptorChain

func NewInterceptorChain(interceptors ...Interceptor) InterceptorChain

NewInterceptorChain creates a new interceptor chain. Each Interceptor argument provides a unary interceptor, a stream interceptor, or both. Nil entries in either field are silently skipped.

func (InterceptorChain) Append

func (c InterceptorChain) Append(interceptors ...Interceptor) InterceptorChain

Append returns a new InterceptorChain with additional interceptors appended. The original chain is not modified.

func (InterceptorChain) ServerOptions

func (c InterceptorChain) ServerOptions() []grpc.ServerOption

ServerOptions returns grpc.ServerOption values that install the chain. This is the primary integration point — pass the result to grpc.NewServer or to NewServer's variadic options.

chain := NewInterceptorChain(logging, recovery)
srv, _ := NewServerFromContainable(cfg, chain.ServerOptions()...)

type RateLimitConfig

type RateLimitConfig struct {
	// RequestsPerSecond is the sustained fill rate. Must be > 0. Default: 50.
	RequestsPerSecond float64 `mapstructure:"requests_per_second" yaml:"requests_per_second" json:"requests_per_second"`
	// Burst is the bucket capacity. Must be >= 1. Default: 100.
	Burst int `mapstructure:"burst" yaml:"burst" json:"burst"`
	// MaxTrackedKeys bounds the per-key bucket store (ignored when KeyFunc is
	// nil). Must be >= 1. Default: 8192.
	MaxTrackedKeys int `mapstructure:"max_tracked_keys" yaml:"max_tracked_keys" json:"max_tracked_keys"`
	// KeyFunc derives the limiter key from the RPC context and full method name,
	// enabling per-client or per-method limiting. When nil, a single global
	// bucket is used. See PeerKey.
	KeyFunc func(ctx context.Context, fullMethod string) string `mapstructure:"-" yaml:"-" json:"-"`
	// OnLimited is invoked when an RPC is rejected. Optional.
	OnLimited func(ctx context.Context, fullMethod string) `mapstructure:"-" yaml:"-" json:"-"`
}

RateLimitConfig configures the server-side token-bucket rate limiter for gRPC ingress, mirroring the HTTP server limiter.

func DefaultRateLimitConfig

func DefaultRateLimitConfig() RateLimitConfig

DefaultRateLimitConfig returns a limiter suitable for a modest management server: 50 rps sustained, burst 100, single global bucket.

func MergeRateLimitConfig

func MergeRateLimitConfig(base, override RateLimitConfig, fields RateLimitConfigOverrides) RateLimitConfig

MergeRateLimitConfig applies explicitly supplied typed override values to base while leaving code-only function fields under caller control.

type RateLimitConfigOverrides

type RateLimitConfigOverrides struct {
	RequestsPerSecond bool
	Burst             bool
	MaxTrackedKeys    bool
}

RateLimitConfigOverrides records which typed rate limit config fields were explicitly supplied by an adapter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL