Skip to content

Commit d4eae9d

Browse files
committed
add namespace attribute
1 parent 1f30a50 commit d4eae9d

File tree

4 files changed

+116
-26
lines changed

4 files changed

+116
-26
lines changed

src/Tracing/Cache/TraceableCacheAdapterForV3WithNamespace.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ final class TraceableCacheAdapterForV3WithNamespace implements AdapterInterface,
2424
*/
2525
use TraceableCacheAdapterTrait;
2626

27+
/**
28+
* @var string|null
29+
*/
30+
private $namespace;
31+
2732
/**
2833
* @param HubInterface $hub The current hub
2934
* @param AdapterInterface $decoratedAdapter The decorated cache adapter
@@ -54,6 +59,9 @@ public function withSubNamespace(string $namespace): static
5459

5560
$clone = clone $this;
5661
$clone->decoratedAdapter = $this->decoratedAdapter->withSubNamespace($namespace);
62+
$clone->namespace = null === $this->namespace
63+
? $namespace
64+
: \sprintf('%s.%s', $this->namespace, $namespace);
5765

5866
return $clone;
5967
}

src/Tracing/Cache/TraceableCacheAdapterTrait.php

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,23 @@ private function traceFunction(string $spanOperation, \Closure $callback, ?strin
200200
try {
201201
$result = $callback();
202202

203-
// Necessary for static analysis. Otherwise, the TResult type is assumed to be CacheItemInterface.
204-
if (!$result instanceof CacheItemInterface) {
205-
return $result;
203+
$data = [];
204+
205+
if ($result instanceof CacheItemInterface) {
206+
$data['cache.hit'] = $result->isHit();
207+
if ($result->isHit()) {
208+
$data['cache.item_size'] = static::getCacheItemSize($result->get());
209+
}
210+
}
211+
212+
$namespace = $this->getCacheNamespace();
213+
if (null !== $namespace) {
214+
$data['cache.namespace'] = $namespace;
206215
}
207216

208-
$data = ['cache.hit' => $result->isHit()];
209-
if ($result->isHit()) {
210-
$data['cache.item_size'] = static::getCacheItemSize($result->get());
217+
if ([] !== $data) {
218+
$span->setData($data);
211219
}
212-
$span->setData($data);
213220

214221
return $result;
215222
} finally {
@@ -282,10 +289,15 @@ private function traceGet(string $key, callable $callback, ?float $beta = null,
282289

283290
$now = microtime(true);
284291

285-
$getSpan->setData([
292+
$getData = [
286293
'cache.hit' => !$wasMiss,
287294
'cache.item_size' => self::getCacheItemSize($value),
288-
]);
295+
];
296+
$namespace = $this->getCacheNamespace();
297+
if (null !== $namespace) {
298+
$getData['cache.namespace'] = $namespace;
299+
}
300+
$getSpan->setData($getData);
289301

290302
// If we got a timestamp here we know that we missed
291303
if (null !== $saveStartTimestamp) {
@@ -296,9 +308,13 @@ private function traceGet(string $key, callable $callback, ?float $beta = null,
296308
->setDescription(urldecode($key));
297309
$saveSpan = $parentSpan->startChild($saveContext);
298310
$saveSpan->setStartTimestamp($saveStartTimestamp);
299-
$saveSpan->setData([
311+
$saveData = [
300312
'cache.item_size' => self::getCacheItemSize($value),
301-
]);
313+
];
314+
if (null !== $namespace) {
315+
$saveData['cache.namespace'] = $namespace;
316+
}
317+
$saveSpan->setData($saveData);
302318
$saveSpan->finish($now);
303319
} else {
304320
$getSpan->finish();
@@ -343,4 +359,16 @@ private function setCallbackWrapper(callable $callback, string $key): callable
343359
return $callback($this->decoratedAdapter->getItem($key));
344360
};
345361
}
362+
363+
/**
364+
* @return string|null
365+
*/
366+
protected function getCacheNamespace(): ?string
367+
{
368+
if (!\property_exists($this, 'namespace')) {
369+
return null;
370+
}
371+
372+
return $this->namespace;
373+
}
346374
}

src/Tracing/Cache/TraceableTagAwareCacheAdapterForV3WithNamespace.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ final class TraceableTagAwareCacheAdapterForV3WithNamespace implements TagAwareA
2424
*/
2525
use TraceableCacheAdapterTrait;
2626

27+
/**
28+
* @var string|null
29+
*/
30+
private $namespace;
31+
2732
/**
2833
* @param HubInterface $hub The current hub
2934
* @param TagAwareAdapterInterface $decoratedAdapter The decorated cache adapter
@@ -62,6 +67,9 @@ public function withSubNamespace(string $namespace): static
6267

6368
$clone = clone $this;
6469
$clone->decoratedAdapter = $this->decoratedAdapter->withSubNamespace($namespace);
70+
$clone->namespace = null === $this->namespace
71+
? $namespace
72+
: \sprintf('%s.%s', $this->namespace, $namespace);
6573

6674
return $clone;
6775
}

tests/Tracing/Cache/TraceableTagAwareCacheAdapterTest.php

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,11 @@
99
use Sentry\Tracing\Transaction;
1010
use Sentry\Tracing\TransactionContext;
1111
use Symfony\Component\Cache\Adapter\AdapterInterface;
12+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
13+
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
1214
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
1315
use Symfony\Contracts\Cache\NamespacedPoolInterface;
1416

15-
if (interface_exists(NamespacedPoolInterface::class)) {
16-
interface TagAwareNamespacedPoolInterface extends TagAwareAdapterInterface, NamespacedPoolInterface
17-
{
18-
}
19-
}
20-
2117
/**
2218
* @phpstan-extends AbstractTraceableCacheAdapterTest<TraceableTagAwareCacheAdapter, TagAwareAdapterInterface>
2319
*/
@@ -71,14 +67,8 @@ public function testWithSubNamespaceReturnsNamespacedAdapter(): void
7167
$this->markTestSkipped('Namespaced caches are not supported by this Symfony version.');
7268
}
7369

74-
$decoratedAdapter = $this->createMock(TagAwareNamespacedPoolInterface::class);
75-
$namespacedAdapter = $this->createMock(TagAwareNamespacedPoolInterface::class);
76-
77-
$decoratedAdapter
78-
->expects($this->once())
79-
->method('withSubNamespace')
80-
->with('foo')
81-
->willReturn($namespacedAdapter);
70+
$decoratedAdapter = new TagAwareAdapter(new ArrayAdapter(), new ArrayAdapter());
71+
$namespacedAdapter = $decoratedAdapter->withSubNamespace('foo');
8272

8373
$adapter = new TraceableTagAwareCacheAdapterForV3WithNamespace($this->hub, $decoratedAdapter);
8474

@@ -90,7 +80,63 @@ public function testWithSubNamespaceReturnsNamespacedAdapter(): void
9080
$ref = new \ReflectionProperty($result, 'decoratedAdapter');
9181
$ref->setAccessible(true);
9282

93-
$this->assertSame($namespacedAdapter, $ref->getValue($result));
83+
$this->assertEquals($namespacedAdapter, $ref->getValue($result));
84+
}
85+
86+
public function testNamespaceIsAddedToSpanData(): void
87+
{
88+
if (!interface_exists(NamespacedPoolInterface::class)) {
89+
$this->markTestSkipped('Namespaced caches are not supported by this Symfony version.');
90+
}
91+
92+
$transaction = new Transaction(new TransactionContext(), $this->hub);
93+
$transaction->initSpanRecorder();
94+
95+
$this->hub->expects($this->any())
96+
->method('getSpan')
97+
->willReturn($transaction);
98+
99+
$decoratedAdapter = new TagAwareAdapter(new ArrayAdapter(), new ArrayAdapter());
100+
$adapter = new TraceableTagAwareCacheAdapterForV3WithNamespace($this->hub, $decoratedAdapter);
101+
102+
$namespaced = $adapter->withSubNamespace('foo')->withSubNamespace('bar');
103+
104+
$namespaced->delete('example');
105+
$this->assertNotNull($transaction->getSpanRecorder());
106+
107+
$spans = $transaction->getSpanRecorder()->getSpans();
108+
109+
$this->assertCount(2, $spans);
110+
$this->assertSame('cache.remove', $spans[1]->getOp());
111+
$this->assertSame('foo.bar', $spans[1]->getData()['cache.namespace']);
112+
}
113+
114+
public function testSingleNamespaceIsAddedToSpanData(): void
115+
{
116+
if (!interface_exists(NamespacedPoolInterface::class)) {
117+
$this->markTestSkipped('Namespaced caches are not supported by this Symfony version.');
118+
}
119+
120+
$transaction = new Transaction(new TransactionContext(), $this->hub);
121+
$transaction->initSpanRecorder();
122+
123+
$this->hub->expects($this->any())
124+
->method('getSpan')
125+
->willReturn($transaction);
126+
127+
$decoratedAdapter = new TagAwareAdapter(new ArrayAdapter(), new ArrayAdapter());
128+
$adapter = new TraceableTagAwareCacheAdapterForV3WithNamespace($this->hub, $decoratedAdapter);
129+
130+
$namespaced = $adapter->withSubNamespace('foo');
131+
132+
$namespaced->delete('example');
133+
$this->assertNotNull($transaction->getSpanRecorder());
134+
135+
$spans = $transaction->getSpanRecorder()->getSpans();
136+
137+
$this->assertCount(2, $spans);
138+
$this->assertSame('cache.remove', $spans[1]->getOp());
139+
$this->assertSame('foo', $spans[1]->getData()['cache.namespace']);
94140
}
95141

96142
/**

0 commit comments

Comments
 (0)