Skip to content

Commit 7060fd9

Browse files
committed
emit header such that we can detect loops in the proxy
1 parent c85dcbe commit 7060fd9

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

exporters/otlp/src/otlp_grpc_forward_proxy.cc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
#include <memory>
55
#include <list>
6+
#include <string>
7+
#include <random>
8+
69
#include <grpcpp/ext/proto_server_reflection_plugin.h>
710

811
#include "opentelemetry/version.h"
@@ -24,6 +27,10 @@ namespace exporter
2427
namespace otlp
2528
{
2629

30+
// Send this header along with unique random number, which we'll reject if received back.
31+
// This is to avoid loops due to misconfugration
32+
static std::string kFwProxyIdHeader{ "otelcpp-otlp-grpc-forward-proxy-id" };
33+
2734
using namespace opentelemetry;
2835

2936
using namespace opentelemetry::exporter::otlp;
@@ -80,6 +87,15 @@ struct OtlpGrpcForwardProxy::Impl
8087
std::unique_ptr<TraceExporterProxy> traceExporterProxy;
8188
std::unique_ptr<MetricExporterProxy> metricExporterProxy;
8289

90+
std::string fw_proxy_id;
91+
92+
bool LoopDetected( const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata ) const
93+
{
94+
const auto key{ grpc::string_ref( kFwProxyIdHeader ) };
95+
const auto it{ client_metadata.find(key) };
96+
return it != client_metadata.cend() && it->second.compare( grpc::string_ref( fw_proxy_id ) ) == 0;
97+
}
98+
8399
Impl(const OtlpGrpcClientOptions&);
84100
#if defined(ENABLE_ASYNC_EXPORT)
85101
bool HandleExportResult(sdk::common::ExportResult result) const;
@@ -93,6 +109,14 @@ OtlpGrpcForwardProxy::Impl::Impl(const OtlpGrpcClientOptions& options)
93109
arenaOptions.initial_block_size = 65536;
94110
arenaOptions.max_block_size = 128 * 1024 * 1024;
95111
client = OtlpGrpcClientFactory::Create(clientOptions);
112+
113+
char buf[32]{};
114+
std::random_device rd;
115+
uint64_t p0 = (uint64_t(rd())<<32) | uint64_t(rd());
116+
uint64_t p1 = (uint64_t(rd())<<32) | uint64_t(rd());
117+
sprintf_s(buf, "%08.8lx%08.8lx", p0, p1);
118+
fw_proxy_id = buf;
119+
96120
}
97121

98122
#if defined(ENABLE_ASYNC_EXPORT)
@@ -168,10 +192,13 @@ grpc::ServerUnaryReactor* OtlpGrpcForwardProxy::Impl::Finish(grpc::CallbackServe
168192
explicit NAME(OtlpGrpcForwardProxy::Impl& impl_): impl(impl_){} \
169193
grpc::ServerUnaryReactor* Export(grpc::CallbackServerContext* cbServerContext, const REQUEST* req, RESPONSE* resp) override { \
170194
auto exportResult{ sdk::common::ExportResult::kFailure }; \
195+
if( impl.LoopDetected(cbServerContext->client_metadata()) ) \
196+
return impl.Finish(cbServerContext, exportResult, grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, "OtlpGrpcForwardProxy detected loop.")); \
171197
if( impl.active ) { \
172198
OTEL_INTERNAL_LOG_DEBUG("[otlp_grpc_forward_proxy] " TEXT " export"); \
173199
auto syncStatus{ grpc::Status(grpc::Status(grpc::StatusCode::DO_NOT_USE, "")) }; \
174200
auto context{ impl.client->MakeClientContext(impl.clientOptions) }; \
201+
context->AddMetadata(kFwProxyIdHeader, impl.fw_proxy_id); \
175202
auto arena{ std::make_unique<google::protobuf::Arena>(impl.arenaOptions) }; \
176203
auto request{ *req }; \
177204
exportResult = impl.client->DelegateAsyncExport( impl.clientOptions, impl.STUB.get(), std::move(context), std::move(arena), std::move(request), \
@@ -193,10 +220,13 @@ grpc::ServerUnaryReactor* OtlpGrpcForwardProxy::Impl::Finish(grpc::CallbackServe
193220
struct OtlpGrpcForwardProxy::Impl::NAME final : public SERVICE::Service { \
194221
OtlpGrpcForwardProxy::Impl& impl; \
195222
explicit NAME(OtlpGrpcForwardProxy::Impl& impl_): impl(impl_){} \
196-
grpc::Status Export(grpc::ServerContext*, const REQUEST* req, RESPONSE* resp) override { \
223+
grpc::Status Export(grpc::ServerContext* serverContext, const REQUEST* req, RESPONSE* resp) override { \
224+
if( impl.LoopDetected(serverContext->client_metadata()) ) \
225+
return grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, "OtlpGrpcForwardProxy detected loop."); \
197226
if( impl.active ) { \
198227
OTEL_INTERNAL_LOG_DEBUG("[otlp_grpc_forward_proxy] " TEXT " export"); \
199228
auto context{ impl.client->MakeClientContext(impl.clientOptions) }; \
229+
context->AddMetadata(kFwProxyIdHeader, impl.fw_proxy_id); \
200230
return impl.STUB->Export( context.get(), *req, resp ); \
201231
} \
202232
return grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, "OtlpGrpcForwardProxy is not active."); \

x/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,8 @@ cc_binary(
6565
"@opentelemetry-proto//:trace_service_grpc_cc",
6666
],
6767
)
68+
69+
cc_binary(
70+
name = "z",
71+
srcs = ["z.cpp"],
72+
)

x/x.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,13 @@ struct proxy_thread
389389

390390
OtlpGrpcClientOptions clientOptions;
391391
clientOptions.endpoint = GetOtlpDefaultGrpcEndpoint();
392-
clientOptions.max_concurrent_requests = 16384;
393-
clientOptions.max_threads = 64;
392+
clientOptions.max_concurrent_requests = 10; //16384;
393+
clientOptions.max_threads = 10;
394394

395395
ctx->proxy = std::make_unique<OtlpGrpcForwardProxy>(clientOptions);
396396
ctx->proxy->SetActive(true);
397397

398-
ctx->proxy->AddListenAddress("127.0.0.1:4317");
398+
ctx->proxy->AddListenAddress("localhost:4317");
399399
proxy->RegisterMetricExporter(OtlpGrpcForwardProxy::ExportMode::AsyncDropOnFull);
400400
proxy->RegisterTraceExporter(OtlpGrpcForwardProxy::ExportMode::AsyncDropOnFull);
401401
proxy->RegisterLogRecordExporter(OtlpGrpcForwardProxy::ExportMode::AsyncDropOnFull);

0 commit comments

Comments
 (0)