Skip to content

Commit ef9726b

Browse files
authored
Jaeger Thrift over Binary protocol implementation (UDP 6832 & Http 14268 support ) (#99)
1 parent 845dd1f commit ef9726b

17 files changed

+817
-39
lines changed

README.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Build Status](https://github.com/jonahgeorge/jaeger-client-php/workflows/Test/badge.svg) [![PHP version][packagist-img]][packagist]
1+
![Build Status](https://github.com/jonahgeorge/jaeger-client-php/workflows/Test/badge.svg) [![PHP version][packagist-img]][packagist]
22

33
# Jaeger Bindings for PHP OpenTracing API
44

@@ -93,6 +93,74 @@ Cache component is passed to `Jaeger\Config` trough its constructor.
9393
]
9494
],
9595
```
96+
## Dispatch mode
97+
98+
The library supports 3 ways of sending data to Jaeger Agent:
99+
100+
1. `Zipkin.thrift` over Compact protocol (socket - UDP) - default
101+
2. `Jaeger.thrift` over Binary protocol (socket - UDP)
102+
2. `Jaeger.thrift` over Binary protocol (HTTP)
103+
104+
If you want to enable "`Jaeger.thrift` over Binary protocol" one or other, than
105+
you need to set `dispatch_mode` config option or `JAEGER_DISPATCH_MODE` env
106+
variable.
107+
108+
Allowed values for `dispatch_mode` are:
109+
- `jaeger_over_binary_udp`
110+
- `jaeger_over_binary_http`
111+
- `zipkin_over_compact_udp`
112+
113+
There are 3 constants available, so it is better to use them:
114+
```php
115+
class Config
116+
{
117+
const ZIPKIN_OVER_COMPACT_UDP = "zipkin_over_compact_udp";
118+
const JAEGER_OVER_BINARY_UDP = "jaeger_over_binary_udp";
119+
const JAEGER_OVER_BINARY_HTTP = "jaeger_over_binary_http";
120+
...
121+
}
122+
```
123+
124+
A possible config with custom `dispatch_mode` can look like this:
125+
```php
126+
// config.php
127+
128+
use Jaeger\Config;
129+
130+
return [
131+
'sampler' => [
132+
'type' => Jaeger\SAMPLER_TYPE_CONST,
133+
'param' => true,
134+
],
135+
'logging' => true,
136+
"tags" => [
137+
// process. prefix works only with JAEGER_OVER_HTTP, JAEGER_OVER_BINARY
138+
// otherwise it will be shown as simple global tag
139+
"process.process-tag-key-1" => "process-value-1", // all tags with `process.` prefix goes to process section
140+
"process.process-tag-key-2" => "process-value-2", // all tags with `process.` prefix goes to process section
141+
"global-tag-key-1" => "global-tag-value-1", // this tag will be appended to all spans
142+
"global-tag-key-2" => "global-tag-value-2", // this tag will be appended to all spans
143+
],
144+
"local_agent" => [
145+
"reporting_host" => "localhost",
146+
// You can override port by setting local_agent.reporting_port value
147+
"reporting_port" => 6832
148+
],
149+
// Different ways to send data to Jaeger. Config::ZIPKIN_OVER_COMPACT - default):
150+
'dispatch_mode' => Config::JAEGER_OVER_BINARY_UDP,
151+
];
152+
```
153+
The full example you can see at `examples` directory.
154+
155+
By default, for each `dispatch_mode` there is default `reporting_port` config value. Table with
156+
default values you can see below:
157+
158+
`dispatch_mode` | default `reporting_port`
159+
------------------------ | ----------------
160+
ZIPKIN_OVER_COMPACT_UDP | 5775
161+
JAEGER_OVER_BINARY_UDP | 6832
162+
JAEGER_OVER_BINARY_HTTP | 14268
163+
96164

97165
## Testing
98166

examples/config.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use Jaeger\Config;
4+
5+
return [
6+
'sampler' => [
7+
'type' => Jaeger\SAMPLER_TYPE_CONST,
8+
'param' => true,
9+
],
10+
'logging' => true,
11+
"tags" => [
12+
// process. prefix works only with JAEGER_OVER_HTTP, JAEGER_OVER_BINARY
13+
// otherwise it will be shown as simple global tag
14+
"process.process-tag-key-1" => "process-value-1", // all tags with `process.` prefix goes to process section
15+
"process.process-tag-key-2" => "process-value-2", // all tags with `process.` prefix goes to process section
16+
"global-tag-key-1" => "global-tag-value-1", // this tag will be appended to all spans
17+
"global-tag-key-2" => "global-tag-value-2", // this tag will be appended to all spans
18+
],
19+
"local_agent" => [
20+
"reporting_host" => "localhost",
21+
// You can override port by setting local_agent.reporting_port value
22+
// "reporting_port" => 6832
23+
],
24+
// Different ways to send data to Jaeger. Config::ZIPKIN_OVER_COMPACT - default):
25+
'dispatch_mode' => Config::JAEGER_OVER_BINARY_UDP,
26+
];

examples/jaeger.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
require_once __DIR__.'/../vendor/autoload.php';
4+
5+
use Jaeger\Config;
6+
use OpenTracing\GlobalTracer;
7+
8+
$config = new Config(
9+
require_once __DIR__.'/config.php',
10+
'your-app-name'
11+
);
12+
13+
$config->initializeTracer();
14+
15+
$tracer = GlobalTracer::get();
16+
17+
$scope = $tracer->startActiveSpan('JaegerSpan', []);
18+
$scope->getSpan()->setTag("tag1", "value1");
19+
$scope->getSpan()->setTag("tag2", "value2");
20+
$scope->getSpan()->setTag("tag3", "value2");
21+
$scope->getSpan()->log([
22+
"key1" => "value1",
23+
"key2" => 2,
24+
"key3" => true
25+
]);
26+
27+
$scope->getSpan()->addBaggageItem("baggage-item1", "baggage-value1");
28+
$scope->getSpan()->addBaggageItem("baggage-item2", "baggage-value2");
29+
$scope->getSpan()->addBaggageItem("baggage-item3", "baggage-value3");
30+
31+
$nestedSpanScope = $tracer->startActiveSpan("Nested1");
32+
$nestedSpanScope->getSpan()->setTag("tag1", "value1");
33+
$nestedSpanScope->getSpan()->setTag("tag2", "value2");
34+
$nestedSpanScope->getSpan()->setTag("tag3", "value2");
35+
$nestedSpanScope->getSpan()->log([
36+
"key1" => "value1",
37+
"key2" => 2,
38+
"key3" => true
39+
]);
40+
41+
$nestedSpanScope->getSpan()->addBaggageItem("baggage-item1", "baggage-value1");
42+
$nestedSpanScope->getSpan()->addBaggageItem("baggage-item2", "baggage-value2");
43+
$nestedSpanScope->getSpan()->addBaggageItem("baggage-item3", "baggage-value3");
44+
45+
sleep(1);
46+
47+
$nestedSpanScope->close();
48+
49+
sleep(1);
50+
$scope->close();
51+
$tracer->flush();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Jaeger\AgentClient;
4+
5+
class HttpAgentClient implements \Jaeger\Thrift\Agent\AgentIf
6+
{
7+
protected $input_ = null;
8+
protected $output_ = null;
9+
10+
protected $seqid_ = 0;
11+
12+
public function __construct($input, $output = null)
13+
{
14+
$this->input_ = $input;
15+
$this->output_ = $output ? $output : $input;
16+
}
17+
18+
public function emitZipkinBatch(array $spans)
19+
{
20+
}
21+
22+
public function emitBatch(\Jaeger\Thrift\Batch $batch)
23+
{
24+
$batch->write($this->output_);
25+
$this->output_->getTransport()->flush();
26+
}
27+
}

src/Jaeger/Config.php

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,34 @@
55
use Exception;
66
use Jaeger\Reporter\CompositeReporter;
77
use Jaeger\Reporter\LoggingReporter;
8-
use Jaeger\Reporter\RemoteReporter;
98
use Jaeger\Reporter\ReporterInterface;
9+
use Jaeger\ReporterFactory\JaegerHttpReporterFactory;
10+
use Jaeger\ReporterFactory\JaegerReporterFactory;
11+
use Jaeger\ReporterFactory\ZipkinReporterFactory;
1012
use Jaeger\Sampler\ConstSampler;
1113
use Jaeger\Sampler\ProbabilisticSampler;
1214
use Jaeger\Sampler\RateLimitingSampler;
1315
use Jaeger\Sampler\SamplerInterface;
14-
use Jaeger\Sender\UdpSender;
15-
use Jaeger\Thrift\Agent\AgentClient;
1616
use Jaeger\Util\RateLimiter;
1717
use OpenTracing\GlobalTracer;
1818
use Psr\Cache\CacheItemPoolInterface;
1919
use Psr\Log\LoggerInterface;
2020
use Psr\Log\NullLogger;
21-
use Thrift\Exception\TTransportException;
22-
use Thrift\Protocol\TCompactProtocol;
23-
use Thrift\Transport\TBufferedTransport;
2421

2522
class Config
2623
{
24+
const ZIPKIN_OVER_COMPACT_UDP = "zipkin_over_compact_udp";
25+
const JAEGER_OVER_BINARY_UDP = "jaeger_over_binary_udp";
26+
const JAEGER_OVER_BINARY_HTTP = "jaeger_over_binary_http";
27+
28+
/**
29+
* @return string[]
30+
*/
31+
public static function getAvailableDispatchModes()
32+
{
33+
return [self::ZIPKIN_OVER_COMPACT_UDP, self::JAEGER_OVER_BINARY_UDP, self::JAEGER_OVER_BINARY_HTTP];
34+
}
35+
2736
/**
2837
* @var array
2938
*/
@@ -44,6 +53,14 @@ class Config
4453
*/
4554
private $logger;
4655

56+
/**
57+
* @return LoggerInterface
58+
*/
59+
public function getLogger()
60+
{
61+
return $this->logger;
62+
}
63+
4764
/**
4865
* @var CacheItemPoolInterface
4966
*/
@@ -67,6 +84,10 @@ public function __construct(
6784

6885
$this->setConfigFromEnv();
6986

87+
if (empty($this->config["dispatch_mode"])) {
88+
$this->config["dispatch_mode"] = self::ZIPKIN_OVER_COMPACT_UDP;
89+
}
90+
7091
$this->serviceName = $this->config['service_name'] ?? $serviceName;
7192
if ($this->serviceName === null) {
7293
throw new Exception('service_name required in the config or param.');
@@ -90,6 +111,7 @@ public function initializeTracer()
90111
$reporter = $this->getReporter();
91112
$sampler = $this->getSampler();
92113

114+
93115
$tracer = $this->createTracer($reporter, $sampler);
94116

95117
$this->initializeGlobalTracer($tracer);
@@ -148,8 +170,25 @@ private function getLogging(): bool
148170
*/
149171
private function getReporter(): ReporterInterface
150172
{
151-
$channel = $this->getLocalAgentSender();
152-
$reporter = new RemoteReporter($channel);
173+
switch ($this->config["dispatch_mode"]) {
174+
case self::JAEGER_OVER_BINARY_UDP:
175+
$reporter = (new JaegerReporterFactory($this))->createReporter();
176+
break;
177+
case self::ZIPKIN_OVER_COMPACT_UDP:
178+
$reporter = (new ZipkinReporterFactory($this))->createReporter();
179+
break;
180+
case self::JAEGER_OVER_BINARY_HTTP:
181+
$reporter = (new JaegerHttpReporterFactory($this))->createReporter();
182+
break;
183+
default:
184+
throw new \RuntimeException(
185+
sprintf(
186+
"Unsupported `dispatch_mode` value: %s. Allowed values are: %s",
187+
$this->config["dispatch_mode"],
188+
implode(", ", Config::getAvailableDispatchModes())
189+
)
190+
);
191+
}
153192

154193
if ($this->getLogging()) {
155194
$reporter = new CompositeReporter($reporter, new LoggingReporter($this->logger));
@@ -193,56 +232,43 @@ private function getSampler(): SamplerInterface
193232
throw new Exception('Unknown sampler type ' . $samplerType);
194233
}
195234

196-
/**
197-
* @return UdpSender
198-
*/
199-
private function getLocalAgentSender(): UdpSender
200-
{
201-
$udp = new ThriftUdpTransport(
202-
$this->getLocalAgentReportingHost(),
203-
$this->getLocalAgentReportingPort(),
204-
$this->logger
205-
);
206-
207-
$transport = new TBufferedTransport($udp, $this->getMaxBufferLength(), $this->getMaxBufferLength());
208-
try {
209-
$transport->open();
210-
} catch (TTransportException $e) {
211-
$this->logger->warning($e->getMessage());
212-
}
213-
214-
$protocol = new TCompactProtocol($transport);
215-
$client = new AgentClient($protocol);
216-
217-
$this->logger->debug('Initializing Jaeger Tracer with UDP reporter');
218-
219-
return new UdpSender($client, $this->getMaxBufferLength(), $this->logger);
220-
}
221-
222235
/**
223236
* The UDP max buffer length.
224237
*
225238
* @return int
226239
*/
227-
private function getMaxBufferLength(): int
240+
public function getMaxBufferLength(): int
228241
{
229242
return (int)($this->config['max_buffer_length'] ?? 64000);
230243
}
231244

232245
/**
233246
* @return string
234247
*/
235-
private function getLocalAgentReportingHost(): string
248+
public function getLocalAgentReportingHost(): string
236249
{
237250
return $this->getLocalAgentGroup()['reporting_host'] ?? DEFAULT_REPORTING_HOST;
238251
}
239252

240253
/**
241254
* @return int
242255
*/
243-
private function getLocalAgentReportingPort(): int
256+
public function getLocalAgentReportingPort(): int
244257
{
245-
return (int)($this->getLocalAgentGroup()['reporting_port'] ?? DEFAULT_REPORTING_PORT);
258+
$port = $this->getLocalAgentGroup()['reporting_port'] ?? null;
259+
if (empty($this->getLocalAgentGroup()['reporting_port'])) {
260+
switch ($this->config['dispatch_mode']) {
261+
case self::JAEGER_OVER_BINARY_UDP:
262+
$port = DEFAULT_JAEGER_UDP_BINARY_REPORTING_PORT;
263+
break;
264+
case self::JAEGER_OVER_BINARY_HTTP:
265+
$port = DEFAULT_JAEGER_HTTP_BINARY_REPORTING_PORT;
266+
break;
267+
default:
268+
$port = DEFAULT_ZIPKIN_UDP_COMPACT_REPORTING_PORT;
269+
}
270+
}
271+
return (int)$port;
246272
}
247273

248274
/**
@@ -312,6 +338,10 @@ private function setConfigFromEnv()
312338
$this->config['tags'] = $_ENV['JAEGER_TAGS'];
313339
}
314340

341+
if (isset($_ENV['JAEGER_DISPATCH_MODE']) && !isset($this->config['dispatch_mode'])) {
342+
$this->config['dispatch_mode'] = $_ENV['JAEGER_DISPATCH_MODE'];
343+
}
344+
315345
// reporting
316346
if (isset($_ENV['JAEGER_AGENT_HOST']) && !isset($this->config['local_agent']['reporting_host'])) {
317347
$this->config['local_agent']['reporting_host'] = $_ENV['JAEGER_AGENT_HOST'];

src/Jaeger/Constants.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,13 @@
8282

8383
const DEFAULT_REPORTING_HOST = 'localhost';
8484

85+
/** @deprecated */
8586
const DEFAULT_REPORTING_PORT = 5775;
8687

88+
const DEFAULT_ZIPKIN_UDP_COMPACT_REPORTING_PORT = 5775;
89+
const DEFAULT_JAEGER_UDP_BINARY_REPORTING_PORT = 6832;
90+
const DEFAULT_JAEGER_HTTP_BINARY_REPORTING_PORT = 14268;
91+
8792
const DEFAULT_SAMPLING_PORT = 5778;
8893

8994
const LOCAL_AGENT_DEFAULT_ENABLED = true;

0 commit comments

Comments
 (0)