Skip to content

Commit 4c0ea5c

Browse files
shivanthzenbogdandrutujmacd
authored
MemoryLimiter extension as an http/grpc middleware (#14071)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description This PR augments the memorylimiter extension to be an HTTP/GRPC middleware. The extension can be used as an HTTP/GRPC middleware once this is merged. Example: ``` receivers: otlp: protocols: grpc: middlewares: - id: memory_limiter http: middlewares: - id: memory_limiter extensions: memory_limiter: check_interval: 1s limit_percentage: 1 spike_limit_percentage: 0.05 .......... ``` <!-- Issue number if applicable --> #### Link to tracking issue Fixes #9591 Fixes #14081 <!--Describe what testing was performed and which tests were added.--> #### Testing Setup a minimal collector to test that the middleware is indeed ratelimiting while the memory usage is closer to limit. ``` receivers: otlp: protocols: grpc: middlewares: - id: memory_limiter http: middlewares: - id: memory_limiter processors: exporters: debug: verbosity: detailed sampling_initial: 5 sampling_thereafter: 200 use_internal_logger: false extensions: memory_limiter: check_interval: 1s limit_percentage: 1 # this is the minimum possible, since it's an integer. spike_limit_percentage: 0.05 service: extensions: - memory_limiter pipelines: metrics: receivers: [otlp] processors: [] exporters: [debug] traces: receivers: [otlp] processors: [] exporters: [debug] logs: receivers: [otlp] processors: [] exporters: [debug] telemetry: logs: level: debug development: false disable_caller: false disable_stacktrace: false ``` #### Documentation Updated the readme for memory limiter extension. --------- Co-authored-by: Bogdan Drutu <[email protected]> Co-authored-by: Joshua MacDonald <[email protected]>
1 parent b31ddb9 commit 4c0ea5c

File tree

6 files changed

+101
-2
lines changed

6 files changed

+101
-2
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
7+
component: extension/memory_limiter
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: The memorylimiter extension can be used as an HTTP/GRPC middleware.
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [14081]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: [user]

cmd/otelcorecol/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ require (
112112
go.opentelemetry.io/collector/exporter/xexporter v0.141.0 // indirect
113113
go.opentelemetry.io/collector/extension/extensionauth v1.47.0 // indirect
114114
go.opentelemetry.io/collector/extension/extensioncapabilities v0.141.0 // indirect
115-
go.opentelemetry.io/collector/extension/extensionmiddleware v0.141.0 // indirect
115+
go.opentelemetry.io/collector/extension/extensionmiddleware v1.45.0 // indirect
116116
go.opentelemetry.io/collector/extension/extensiontest v0.141.0 // indirect
117117
go.opentelemetry.io/collector/extension/xextension v0.141.0 // indirect
118118
go.opentelemetry.io/collector/featuregate v1.47.0 // indirect

extension/memorylimiterextension/README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@ The memory limiter extension is used to prevent out of memory situations on
1414
the collector. The extension will potentially replace the Memory Limiter Processor.
1515
It provides better guarantees from running out of memory as it will be used by the
1616
receivers to reject requests before converting them into OTLP. All the configurations
17-
are the same as Memory Limiter Processor. The extension is under development and does nothing.
17+
are the same as Memory Limiter Processor.
18+
19+
20+
This extension can be used as an extension for all HTTP and gRPC receivers that
21+
are configured through the standard `confighttp` and `configgrpc` libraries. For
22+
example, to configure this extension in the OTLP receiver:
23+
24+
```
25+
receivers:
26+
otlp:
27+
protocols:
28+
grpc:
29+
middlewares:
30+
- id: memory_limiter
31+
http:
32+
middlewares:
33+
- id: memory_limiter
34+
35+
extensions:
36+
memory_limiter:
37+
check_interval: 1s
38+
limit_percentage: 1
39+
spike_limit_percentage: 0.05
40+
```
1841

1942
see [memorylimiterprocessor](../../processor/memorylimiterprocessor/README.md) for additional details

extension/memorylimiterextension/go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ require (
88
go.opentelemetry.io/collector/component/componenttest v0.141.0
99
go.opentelemetry.io/collector/confmap v1.47.0
1010
go.opentelemetry.io/collector/extension v1.47.0
11+
go.opentelemetry.io/collector/extension/extensionmiddleware v1.45.0
1112
go.opentelemetry.io/collector/extension/extensiontest v0.141.0
1213
go.opentelemetry.io/collector/internal/memorylimiter v0.141.0
1314
go.uber.org/goleak v1.3.0
1415
go.uber.org/zap v1.27.1
16+
google.golang.org/grpc v1.77.0
1517
)
1618

1719
require (
@@ -50,7 +52,11 @@ require (
5052
go.opentelemetry.io/otel/trace v1.39.0 // indirect
5153
go.uber.org/multierr v1.11.0 // indirect
5254
go.yaml.in/yaml/v3 v3.0.4 // indirect
55+
golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect
5356
golang.org/x/sys v0.39.0 // indirect
57+
golang.org/x/text v0.30.0 // indirect
58+
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
59+
google.golang.org/protobuf v1.36.10 // indirect
5460
gopkg.in/yaml.v3 v3.0.1 // indirect
5561
)
5662

@@ -71,3 +77,5 @@ replace go.opentelemetry.io/collector/extension/extensiontest => ../../extension
7177
replace go.opentelemetry.io/collector/featuregate => ../../featuregate
7278

7379
replace go.opentelemetry.io/collector/internal/testutil => ../../internal/testutil
80+
81+
replace go.opentelemetry.io/collector/extension/extensionmiddleware => ../../extension/extensionmiddleware

extension/memorylimiterextension/go.sum

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extension/memorylimiterextension/memorylimiter.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@ package memorylimiterextension // import "go.opentelemetry.io/collector/extensio
55

66
import (
77
"context"
8+
"net/http"
89

910
"go.uber.org/zap"
11+
"google.golang.org/grpc"
12+
"google.golang.org/grpc/codes"
13+
"google.golang.org/grpc/status"
1014

1115
"go.opentelemetry.io/collector/component"
16+
"go.opentelemetry.io/collector/extension/extensionmiddleware"
1217
"go.opentelemetry.io/collector/internal/memorylimiter"
1318
)
1419

20+
var (
21+
_ extensionmiddleware.GRPCServer = (*memoryLimiterExtension)(nil)
22+
_ extensionmiddleware.HTTPServer = (*memoryLimiterExtension)(nil)
23+
)
24+
1525
type memoryLimiterExtension struct {
1626
memLimiter *memorylimiter.MemoryLimiter
1727
}
@@ -38,3 +48,24 @@ func (ml *memoryLimiterExtension) Shutdown(ctx context.Context) error {
3848
func (ml *memoryLimiterExtension) MustRefuse() bool {
3949
return ml.memLimiter.MustRefuse()
4050
}
51+
52+
func (ml *memoryLimiterExtension) GetHTTPHandler(base http.Handler) (http.Handler, error) {
53+
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
54+
if ml.MustRefuse() {
55+
http.Error(resp, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
56+
return
57+
}
58+
base.ServeHTTP(resp, req)
59+
}), nil
60+
}
61+
62+
func (ml *memoryLimiterExtension) GetGRPCServerOptions() ([]grpc.ServerOption, error) {
63+
return []grpc.ServerOption{grpc.UnaryInterceptor(
64+
func(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
65+
if ml.MustRefuse() {
66+
return nil, status.Errorf(codes.ResourceExhausted, "RESOURCE_EXHAUSTED")
67+
}
68+
return handler(ctx, req)
69+
},
70+
)}, nil
71+
}

0 commit comments

Comments
 (0)