4
4
5
5
use Illuminate \Cache \Events ;
6
6
use Illuminate \Contracts \Events \Dispatcher ;
7
+ use Illuminate \Contracts \Session \Session ;
7
8
use Illuminate \Redis \Events as RedisEvents ;
8
9
use Illuminate \Redis \RedisManager ;
9
10
use Illuminate \Support \Str ;
@@ -86,11 +87,13 @@ public function handleCacheEventsForBreadcrumbs(Events\CacheEvent $event): void
86
87
return ;
87
88
}
88
89
90
+ $ displayKey = $ this ->replaceSessionKey ($ event ->key );
91
+
89
92
Integration::addBreadcrumb (new Breadcrumb (
90
93
Breadcrumb::LEVEL_INFO ,
91
94
Breadcrumb::TYPE_DEFAULT ,
92
95
'cache ' ,
93
- "{$ message }: {$ event -> key }" ,
96
+ "{$ message }: {$ displayKey }" ,
94
97
$ event ->tags ? ['tags ' => $ event ->tags ] : []
95
98
));
96
99
}
@@ -109,15 +112,17 @@ public function handleCacheEventsForTracing(Events\CacheEvent $event): void
109
112
: $ event ->keys
110
113
);
111
114
115
+ $ displayKeys = $ this ->replaceSessionKeys ($ keys );
116
+
112
117
$ this ->pushSpan (
113
118
$ parentSpan ->startChild (
114
119
SpanContext::make ()
115
120
->setOp ('cache.get ' )
116
121
->setData ([
117
- 'cache.key ' => $ keys ,
122
+ 'cache.key ' => $ displayKeys ,
118
123
])
119
124
->setOrigin ('auto.cache ' )
120
- ->setDescription (implode (', ' , $ keys ))
125
+ ->setDescription (implode (', ' , $ displayKeys ))
121
126
)
122
127
);
123
128
}
@@ -129,30 +134,34 @@ public function handleCacheEventsForTracing(Events\CacheEvent $event): void
129
134
: $ event ->keys
130
135
);
131
136
137
+ $ displayKeys = $ this ->replaceSessionKeys ($ keys );
138
+
132
139
$ this ->pushSpan (
133
140
$ parentSpan ->startChild (
134
141
SpanContext::make ()
135
142
->setOp ('cache.put ' )
136
143
->setData ([
137
- 'cache.key ' => $ keys ,
144
+ 'cache.key ' => $ displayKeys ,
138
145
'cache.ttl ' => $ event ->seconds ,
139
146
])
140
147
->setOrigin ('auto.cache ' )
141
- ->setDescription (implode (', ' , $ keys ))
148
+ ->setDescription (implode (', ' , $ displayKeys ))
142
149
)
143
150
);
144
151
}
145
152
146
153
if ($ event instanceof Events \ForgettingKey) {
154
+ $ displayKey = $ this ->replaceSessionKey ($ event ->key );
155
+
147
156
$ this ->pushSpan (
148
157
$ parentSpan ->startChild (
149
158
SpanContext::make ()
150
159
->setOp ('cache.remove ' )
151
160
->setData ([
152
- 'cache.key ' => [$ event -> key ],
161
+ 'cache.key ' => [$ displayKey ],
153
162
])
154
163
->setOrigin ('auto.cache ' )
155
- ->setDescription ($ event -> key )
164
+ ->setDescription ($ displayKey )
156
165
)
157
166
);
158
167
}
@@ -177,7 +186,7 @@ public function handleRedisCommands(RedisEvents\CommandExecuted $event): void
177
186
// If the first parameter is a string and does not contain a newline we use it as the description since it's most likely a key
178
187
// This is not a perfect solution but it's the best we can do without understanding the command that was executed
179
188
if (!empty ($ event ->parameters [0 ]) && is_string ($ event ->parameters [0 ]) && !Str::contains ($ event ->parameters [0 ], "\n" )) {
180
- $ keyForDescription = $ event ->parameters [0 ];
189
+ $ keyForDescription = $ this -> replaceSessionKey ( $ event ->parameters [0 ]) ;
181
190
}
182
191
183
192
$ context ->setDescription (rtrim (strtoupper ($ event ->command ) . ' ' . $ keyForDescription ));
@@ -189,7 +198,7 @@ public function handleRedisCommands(RedisEvents\CommandExecuted $event): void
189
198
];
190
199
191
200
if ($ this ->shouldSendDefaultPii ()) {
192
- $ data ['db.redis.parameters ' ] = $ event ->parameters ;
201
+ $ data ['db.redis.parameters ' ] = $ this -> replaceSessionKeys ( $ event ->parameters ) ;
193
202
}
194
203
195
204
if ($ this ->isTracingFeatureEnabled ('redis_origin ' )) {
@@ -213,7 +222,7 @@ private function maybeHandleCacheEventAsEndOfSpan(Events\CacheEvent $event): boo
213
222
214
223
if ($ finishedSpan !== null && count ($ finishedSpan ->getData ()['cache.key ' ] ?? []) === 1 ) {
215
224
$ finishedSpan ->setData ([
216
- 'cache.hit ' => $ event instanceof Events \CacheHit,
225
+ 'cache.hit ' => $ event instanceof Events \CacheHit
217
226
]);
218
227
}
219
228
@@ -228,7 +237,7 @@ private function maybeHandleCacheEventAsEndOfSpan(Events\CacheEvent $event): boo
228
237
229
238
if ($ finishedSpan !== null ) {
230
239
$ finishedSpan ->setData ([
231
- 'cache.success ' => $ event instanceof Events \KeyWritten,
240
+ 'cache.success ' => $ event instanceof Events \KeyWritten
232
241
]);
233
242
}
234
243
@@ -245,6 +254,53 @@ private function maybeHandleCacheEventAsEndOfSpan(Events\CacheEvent $event): boo
245
254
return false ;
246
255
}
247
256
257
+ /**
258
+ * Retrieve the current session key if available.
259
+ */
260
+ private function getSessionKey (): ?string
261
+ {
262
+ try {
263
+ /** @var Session $sessionStore */
264
+ $ sessionStore = $ this ->container ()->make ('session.store ' );
265
+
266
+ // It is safe for us to get the session ID here without checking if the session is started
267
+ // because getting the session ID does not start the session. In addition we need the ID before
268
+ // the session is started because the cache will retrieve the session ID from the cache before the session
269
+ // is considered started. So if we wait for the session to be started, we will not be able to replace the
270
+ // session key in the cache operation that is being executed to retrieve the session data from the cache.
271
+ return $ sessionStore ->getId ();
272
+ } catch (\Exception $ e ) {
273
+ // We can assume the session store is not available here so there is no session key to retrieve
274
+ // We capture a generic exception to avoid breaking the application because some code paths can
275
+ // result in an exception other than the expected `Illuminate\Contracts\Container\BindingResolutionException`
276
+ return null ;
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Replace a session key with a placeholder.
282
+ */
283
+ private function replaceSessionKey (string $ value ): string
284
+ {
285
+ return $ value === $ this ->getSessionKey () ? '{sessionKey} ' : $ value ;
286
+ }
287
+
288
+ /**
289
+ * Replace session keys in an array of keys with placeholders.
290
+ *
291
+ * @param string[] $values
292
+ *
293
+ * @return mixed[]
294
+ */
295
+ private function replaceSessionKeys (array $ values ): array
296
+ {
297
+ $ sessionKey = $ this ->getSessionKey ();
298
+
299
+ return array_map (static function ($ value ) use ($ sessionKey ) {
300
+ return is_string ($ value ) && $ value === $ sessionKey ? '{sessionKey} ' : $ value ;
301
+ }, $ values );
302
+ }
303
+
248
304
/**
249
305
* Normalize the array of keys to a array of only strings.
250
306
*
0 commit comments