Skip to content

Commit a48cde0

Browse files
authored
Fix for sub-span overflow
1 parent e261065 commit a48cde0

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

src/Jaeger/ReporterFactory/JaegerHttpReporterFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function createReporter() : ReporterInterface
2929
$client = new HttpAgentClient($protocol);
3030
$this->config->getLogger()->debug('Initializing HTTP Jaeger Tracer with Jaeger.Thrift over Binary protocol');
3131
$sender = new JaegerSender($client, $this->config->getLogger());
32+
$sender->setMaxBufferLength($this->config->getMaxBufferLength());
3233
return new JaegerReporter($sender);
3334
}
3435
}

src/Jaeger/ReporterFactory/JaegerReporterFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function createReporter() : ReporterInterface
3737
$client = new AgentClient($protocol);
3838
$this->config->getLogger()->debug('Initializing UDP Jaeger Tracer with Jaeger.Thrift over Binary protocol');
3939
$sender = new JaegerSender($client, $this->config->getLogger());
40+
$sender->setMaxBufferLength($this->config->getMaxBufferLength());
4041
return new JaegerReporter($sender);
4142
}
4243
}

src/Jaeger/Sender/JaegerSender.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
use Jaeger\Tracer;
1616
use Psr\Log\LoggerInterface;
1717
use Psr\Log\NullLogger;
18+
use Thrift\Protocol\TBinaryProtocol;
19+
use Thrift\Protocol\TCompactProtocol;
20+
use Thrift\Transport\TMemoryBuffer;
1821
use const Jaeger\JAEGER_HOSTNAME_TAG_KEY;
1922

2023
class JaegerSender implements SenderInterface
@@ -44,6 +47,17 @@ class JaegerSender implements SenderInterface
4447
*/
4548
private $mapper;
4649

50+
/**
51+
* @var int
52+
*/
53+
private $jaegerBatchOverheadLength = 512;
54+
55+
/**
56+
* The maximum length of the thrift-objects for a jaeger-batch.
57+
*
58+
* @var int
59+
*/
60+
private $maxBufferLength = 64000;
4761

4862
/**
4963
* @param AgentIf $agentClient
@@ -81,6 +95,11 @@ public function flush(): int
8195
return $count;
8296
}
8397

98+
public function setMaxBufferLength($maxBufferLength)
99+
{
100+
$this->maxBufferLength = $maxBufferLength;
101+
}
102+
84103
/**
85104
* @param JaegerSpan[] $spans
86105
* @return array
@@ -110,6 +129,52 @@ private function send(array $spans)
110129
return ;
111130
}
112131

132+
$chunks = $this->chunkSplit($spans);
133+
foreach ($chunks as $chunk) {
134+
/** @var JaegerThriftSpan[] $chunk */
135+
$this->emitJaegerBatch($chunk);
136+
}
137+
}
138+
139+
/**
140+
* @param JaegerThriftSpan $span
141+
*/
142+
private function getBufferLength($span)
143+
{
144+
$memoryBuffer = new TMemoryBuffer();
145+
$span->write(new TBinaryProtocol($memoryBuffer));
146+
return $memoryBuffer->available();
147+
}
148+
149+
private function chunkSplit(array $spans): array
150+
{
151+
$actualBufferSize = $this->jaegerBatchOverheadLength;
152+
$chunkId = 0;
153+
$chunks = [];
154+
155+
foreach ($spans as $span) {
156+
$spanBufferLength = $this->getBufferLength($span);
157+
if (!empty($chunks[$chunkId]) && ($actualBufferSize + $spanBufferLength) > $this->maxBufferLength) {
158+
// point to next chunk
159+
++$chunkId;
160+
161+
// reset buffer size
162+
$actualBufferSize = $this->jaegerBatchOverheadLength;
163+
}
164+
165+
if (!isset($chunks[$chunkId])) {
166+
$chunks[$chunkId] = [];
167+
}
168+
169+
$chunks[$chunkId][] = $span;
170+
$actualBufferSize += $spanBufferLength;
171+
}
172+
173+
return $chunks;
174+
}
175+
176+
protected function emitJaegerBatch(array $spans)
177+
{
113178
/** @var Tag[] $tags */
114179
$tags = [];
115180

tests/Jaeger/Sender/JaegerThriftSenderTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Jaeger\Tests\Sender;
55

66
use Jaeger\Sender\JaegerSender;
7+
use Jaeger\Sender\UdpSender;
78
use Jaeger\Span;
89
use Jaeger\SpanContext;
910
use Jaeger\Thrift\Agent\AgentClient;
@@ -41,6 +42,7 @@ public function testFlush(): void
4142

4243
$client = $this->createMock(AgentClient::class);
4344
$sender = new JaegerSender($client);
45+
$sender->setMaxBufferLength(64000);
4446

4547
$client
4648
->expects(self::exactly(1))
@@ -56,6 +58,7 @@ public function testFlush(): void
5658
public function testEmitBatch() {
5759
$client = $this->createMock(AgentClient::class);
5860
$sender = new JaegerSender($client);
61+
$sender->setMaxBufferLength(64000);
5962

6063
$span = $this->createMock(Span::class);
6164
$span->method('getOperationName')->willReturn('dummy-operation');
@@ -82,4 +85,42 @@ public function testEmitBatch() {
8285
$sender->append($span);
8386
$this->assertEquals(1, $sender->flush());
8487
}
88+
89+
public function testMaxBufferLength() {
90+
$tracer = $this->createMock(Tracer::class);
91+
$tracer->method('getIpAddress')->willReturn('');
92+
$tracer->method('getServiceName')->willReturn('');
93+
94+
$context = $this->createMock(SpanContext::class);
95+
96+
$span = $this->createMock(Span::class);
97+
$span->method('getOperationName')->willReturn('dummy-operation');
98+
$span->method('getTracer')->willReturn($tracer);
99+
$span->method('getContext')->willReturn($context);
100+
101+
$client = $this->createMock(AgentClient::class);
102+
103+
$mockBuilder = $this->getMockBuilder(JaegerSender::class);
104+
$mockMethods = ['emitJaegerBatch'];
105+
if (method_exists($mockBuilder, "onlyMethods")) {
106+
$mockBuilder = $mockBuilder->onlyMethods($mockMethods);
107+
} else {
108+
$mockBuilder = $mockBuilder->setMethods($mockMethods);
109+
}
110+
$sender = $mockBuilder->setConstructorArgs([$client])->getMock();
111+
$sender->setMaxBufferLength(800);
112+
$sender->expects(self::exactly(2))
113+
->method('emitJaegerBatch')
114+
->withConsecutive(
115+
[self::countOf(2)],
116+
[self::countOf(1)]
117+
);
118+
119+
// jaeger batch overhead parameter = 512
120+
$sender->append($span); // 512 + 143 < 800 - chunk 1
121+
$sender->append($span); // 512 + 143*2 => 798 < 800 - chunk 1
122+
$sender->append($span); // 512 + 143*3 > 800 - chunk 2
123+
124+
self::assertEquals(3, $sender->flush());
125+
}
85126
}

0 commit comments

Comments
 (0)