Skip to content

Commit 2a0d0e3

Browse files
Merge pull request #43 from dapr/fix/tracing
Fix distributed tracing
2 parents f24925e + 50a2e73 commit 2a0d0e3

File tree

4 files changed

+80
-47
lines changed

4 files changed

+80
-47
lines changed

src/config.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Dapr\Deserialization\DeserializationConfig;
1515
use Dapr\Deserialization\Deserializer;
1616
use Dapr\Deserialization\IDeserializer;
17+
use Dapr\DistributedTracing\ActiveTrace;
1718
use Dapr\PubSub\Publish;
1819
use Dapr\PubSub\Subscriptions;
1920
use Dapr\PubSub\Topic;
@@ -24,6 +25,7 @@
2425
use Dapr\State\IManageState;
2526
use Dapr\State\StateManager;
2627
use Dapr\State\TransactionalState;
28+
use DI\Container;
2729
use FastRoute\DataGenerator\GroupCountBased;
2830
use FastRoute\RouteCollector;
2931
use FastRoute\RouteParser\Std;
@@ -32,12 +34,14 @@
3234
use Monolog\Processor\PsrLogMessageProcessor;
3335
use Nyholm\Psr7\Factory\Psr17Factory;
3436
use Nyholm\Psr7Server\ServerRequestCreator;
37+
use Psr\Http\Message\RequestInterface;
3538
use Psr\Log\LoggerInterface;
3639
use Psr\Log\LogLevel;
3740

3841
use function DI\autowire;
3942
use function DI\create;
4043
use function DI\env;
44+
use function DI\factory;
4145
use function DI\get;
4246

4347
return [
@@ -63,6 +67,13 @@
6367
),
6468

6569
// SDK wiring
70+
ActiveTrace::class => factory(
71+
fn(Container $container) => ActiveTrace::get_from_request(
72+
$container->get(
73+
RequestInterface::class
74+
)
75+
)
76+
),
6677
ActorConfig::class => autowire()
6778
->constructorParameter('actor_name_to_type', get('dapr.actors'))
6879
->constructorParameter('idle_timeout', get('dapr.actors.idle_timeout'))

src/lib/App.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Dapr\Actors\IActor;
99
use Dapr\Actors\Reminder;
1010
use Dapr\Deserialization\InvokerParameterResolver;
11+
use Dapr\DistributedTracing\ActiveTrace;
1112
use Dapr\exceptions\Http\NotFound;
1213
use Dapr\PubSub\Subscriptions;
1314
use Dapr\Serialization\ISerializer;
@@ -176,7 +177,7 @@ public function start(?ServerRequestInterface $request = null): void
176177
)->withHeader('Content-Type', 'application/json');
177178
$this->logger->critical('Failed due to {exception}', ['exception' => $exception]);
178179
}
179-
$this->emitter->emit($response);
180+
$this->emitter->emit(ActiveTrace::decorate_response($this->container->get(ActiveTrace::class), $response));
180181
}
181182

182183
/**

src/lib/DaprClient.php

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Dapr;
44

55
use Dapr\Deserialization\IDeserializer;
6+
use Dapr\DistributedTracing\ActiveTrace;
67
use Dapr\exceptions\DaprException;
78
use JetBrains\PhpStorm\Pure;
89
use Psr\Log\LoggerInterface;
@@ -13,15 +14,14 @@
1314
*/
1415
class DaprClient
1516
{
16-
private static array $trace;
17-
private static bool $added_trace = false;
1817
// temp hack to allow custom headers
1918
private static DaprClient $client;
2019
public array $extra_headers = [];
2120

2221
public function __construct(
2322
protected LoggerInterface $logger,
2423
protected IDeserializer $deserializer,
24+
protected ActiveTrace|null $trace,
2525
protected string $port
2626
) {
2727
self::$client = $this;
@@ -63,7 +63,6 @@ public function get(string $url, ?array $params = null): DaprResponse
6363
$return->headers,
6464
fn($carry, $item) => str_starts_with($item, 'etag:') ? str_replace('etag: ', '', $item) : $carry
6565
);
66-
self::detect_trace_from_response($return);
6766

6867
$this->logger->debug('Got response: {response}', ['response' => $return]);
6968

@@ -106,48 +105,12 @@ public function get(string $url, ?array $params = null): DaprResponse
106105

107106
private function get_headers(): array
108107
{
109-
return array_merge(["Accept: application/json"], self::detect_trace(), $this->extra_headers);
110-
}
111-
112-
private function detect_trace(): array
113-
{
114-
if (isset(self::$trace)) {
115-
return self::$trace;
116-
}
117-
118-
$existing_headers = getallheaders();
119-
self::$trace = isset($existing_headers['Traceparent']) ? ['Traceparent: '.$existing_headers['Traceparent']] : [];
120-
121-
if ( ! self::$added_trace && isset($existing_headers['Traceparent'])) {
122-
header('Traceparent: '.$existing_headers['Traceparent']);
123-
self::$added_trace = true;
124-
}
125-
126-
return self::$trace;
127-
}
128-
129-
/**
130-
* @param DaprResponse $response
131-
*/
132-
private function detect_trace_from_response(DaprResponse $response): void
133-
{
134-
if (isset(self::$trace)) {
135-
return;
136-
}
108+
$trace = $this->trace ? [
109+
'tracestate: '.$this->trace->trace_state,
110+
'traceparent: '.$this->trace->trace_parent,
111+
] : [];
137112

138-
$header = array_filter(
139-
$response->headers,
140-
function ($ii) {
141-
return str_starts_with($ii, 'Traceparent:');
142-
}
143-
);
144-
if ( ! empty($header)) {
145-
self::$trace = $header;
146-
if ( ! self::$added_trace) {
147-
header('Traceparent: '.$header[0]);
148-
self::$added_trace = true;
149-
}
150-
}
113+
return array_merge(["Accept: application/json"], $trace, $this->extra_headers);
151114
}
152115

153116
/**
@@ -180,7 +143,6 @@ public function post(string $url, mixed $data, ?array $params = null): DaprRespo
180143
$response->data = json_decode($response->data, true);
181144
$response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
182145
$response->headers = explode("\r\n", curl_getinfo($curl, CURLINFO_HEADER_OUT));
183-
self::detect_trace_from_response($response);
184146
$this->logger->debug('Got response: {r}', ['r' => $response]);
185147

186148
if ($this->deserializer->is_exception($response->data)) {
@@ -226,7 +188,6 @@ public function delete(string $url, ?array $params = []): DaprResponse
226188
$response->data = json_decode(curl_exec($curl), true);
227189
$response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
228190
$response->headers = explode("\r\n", curl_getinfo($curl, CURLINFO_HEADER_OUT));
229-
self::detect_trace_from_response($response);
230191

231192
$this->logger->debug('Got response: {r}', ['r' => $response]);
232193

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Dapr\DistributedTracing;
4+
5+
use Psr\Http\Message\RequestInterface;
6+
use Psr\Http\Message\ResponseInterface;
7+
8+
/**
9+
* Class ActiveTrace
10+
* @package Dapr\DistributedTracing
11+
*/
12+
class ActiveTrace
13+
{
14+
/**
15+
* ActiveTrace constructor.
16+
*
17+
* @param string $trace_parent
18+
* @param string|null $trace_state
19+
*/
20+
private function __construct(public string $trace_parent, public string|null $trace_state)
21+
{
22+
}
23+
24+
/**
25+
* @param ActiveTrace|null $trace
26+
* @param ResponseInterface $response
27+
*
28+
* @return ResponseInterface
29+
*/
30+
public static function decorate_response(ActiveTrace|null $trace, ResponseInterface $response)
31+
{
32+
if ($trace === null) {
33+
return $response;
34+
}
35+
if ($trace->trace_state) {
36+
return $response
37+
->withHeader('traceparent', $trace->trace_parent)
38+
->withHeader('tracestate', $trace->trace_state);
39+
}
40+
41+
return $response->withHeader('traceparent', $trace->trace_parent);
42+
}
43+
44+
/**
45+
* @param RequestInterface $request
46+
*
47+
* @return ActiveTrace|null
48+
*/
49+
public static function get_from_request(RequestInterface $request): ActiveTrace|null
50+
{
51+
if ($request->hasHeader('traceparent')) {
52+
return new ActiveTrace(
53+
$request->getHeader('traceparent')[0],
54+
$request->hasHeader('tracestate') ? $request->getHeader('tracestate')[0] : null
55+
);
56+
}
57+
58+
return null;
59+
}
60+
}

0 commit comments

Comments
 (0)