Skip to content

Commit 334480e

Browse files
authored
Merge pull request #183 from avast/ConfigurablePayloadLogging
Configurable redaction of payload when logging
2 parents 23c3699 + 9df19c3 commit 334480e

8 files changed

+43
-15
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,13 @@ myConsumer {
308308
}
309309
```
310310

311+
### Payload logging or redaction
312+
313+
By default, the client logs received delivery (on the TRACE level, unless timeout or sth happens - it's on some higher levels then) for
314+
better debugging experience. However, if you transfer some sensitive data and you don't want the delivery to be logged, you can easily
315+
turn it off by using `redactPayload = true` parameter in consumer configs (note: producer doesn't log the delivery at all, just its
316+
metadata like routing key and properties).
317+
311318
### Caveats
312319

313320
1. `null` instead of converter instance

core/src/main/scala/com/avast/clients/rabbitmq/ConsumerBase.scala

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import scala.util._
1919
final private[rabbitmq] case class ConsumerBase[F[_]: ConcurrentEffect: Timer, A](
2020
consumerName: String,
2121
queueName: String,
22+
redactPayload: Boolean,
2223
blocker: Blocker,
2324
consumerLogger: ImplicitContextLogger[F],
2425
consumerRootMonitor: Monitor[F])(implicit val contextShift: ContextShift[F], implicit val deliveryConverter: DeliveryConverter[A]) {
@@ -37,24 +38,26 @@ final private[rabbitmq] case class ConsumerBase[F[_]: ConcurrentEffect: Timer, A
3738
case Success(Right(a)) =>
3839
val delivery = Delivery(a, fixedProperties.asScala, dctx.routingKey.value)
3940

40-
consumerLogger.trace(s"[$consumerName] Received delivery from queue '$queueName': ${delivery.copy(body = rawBody)}").as {
41-
delivery
42-
}
41+
consumerLogger
42+
.trace(s"[$consumerName] Received delivery from queue '$queueName': ${logIfAllowed(delivery.toString)}")
43+
.as(delivery)
4344

4445
case Success(Left(ce)) =>
4546
val delivery = Delivery.MalformedContent(rawBody, fixedProperties.asScala, dctx.routingKey.value, ce)
4647

47-
consumerLogger.trace(s"[$consumerName] Received delivery from queue '$queueName' but could not convert it: $delivery").as {
48-
delivery
49-
}
48+
consumerLogger
49+
.trace(
50+
s"[$consumerName] Received delivery from queue '$queueName' but could not convert it: ${logIfAllowed(delivery.toString)}"
51+
)
52+
.as(delivery)
5053

5154
case Failure(ce) =>
5255
val ex = ConversionException("Unexpected failure", ce)
5356
val delivery = Delivery.MalformedContent(rawBody, fixedProperties.asScala, dctx.routingKey.value, ex)
5457

5558
consumerLogger
56-
.trace(
57-
s"[$consumerName] Received delivery from queue '$queueName' but could not convert it as the convertor has failed: $delivery")
59+
.trace(s"[$consumerName] Received delivery from queue '$queueName' but " +
60+
s"could not convert it as the convertor has failed: ${logIfAllowed(delivery.toString)}")
5861
.as(delivery)
5962
}
6063
.map(DeliveryWithContext(_, dctx))
@@ -76,8 +79,9 @@ final private[rabbitmq] case class ConsumerBase[F[_]: ConcurrentEffect: Timer, A
7679
consumerLogger.trace(e)(s"[$consumerName] Timeout for $messageId") >>
7780
timeoutsMeter.mark >> {
7881

79-
lazy val msg =
80-
s"[$consumerName] Task timed-out after $processTimeout of processing delivery $messageId with routing key ${delivery.routingKey}, applying DeliveryResult.$timeoutAction. Delivery was:\n$delivery"
82+
lazy val msg = s"[$consumerName] Task timed-out after $processTimeout of processing delivery $messageId " +
83+
s"with routing key ${delivery.routingKey}, applying DeliveryResult.$timeoutAction. " +
84+
s"Delivery was:\n${logIfAllowed(delivery.toString)}"
8185

8286
(timeoutLogLevel match {
8387
case Level.ERROR => consumerLogger.error(msg)
@@ -92,4 +96,8 @@ final private[rabbitmq] case class ConsumerBase[F[_]: ConcurrentEffect: Timer, A
9296
}
9397
} else result
9498
}
99+
100+
def logIfAllowed(f: => String): String = {
101+
if (!redactPayload) f else "--redacted--"
102+
}
95103
}

core/src/main/scala/com/avast/clients/rabbitmq/DefaultRabbitMQClientFactory.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ private[rabbitmq] class DefaultRabbitMQClientFactory[F[_]: ConcurrentEffect: Tim
118118
val base = new ConsumerBase[F, A](
119119
name,
120120
queueName,
121+
redactPayload,
121122
blocker,
122123
ImplicitContextLogger.createLogger[F, DefaultRabbitMQStreamingConsumer[F, A]],
123124
monitor
@@ -178,6 +179,7 @@ private[rabbitmq] class DefaultRabbitMQClientFactory[F[_]: ConcurrentEffect: Tim
178179
val base = new ConsumerBase[F, A](
179180
name,
180181
queueName,
182+
redactPayload,
181183
blocker,
182184
logger,
183185
monitor
@@ -236,6 +238,7 @@ private[rabbitmq] class DefaultRabbitMQClientFactory[F[_]: ConcurrentEffect: Tim
236238
val base = new ConsumerBase[F, A](
237239
name,
238240
queueName,
241+
redactPayload,
239242
blocker,
240243
logger,
241244
monitor

core/src/main/scala/com/avast/clients/rabbitmq/configuration.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final case class ConsumerConfig(name: String,
3333
timeoutAction: DeliveryResult = DeliveryResult.Republish(),
3434
timeoutLogLevel: Level = Level.WARN,
3535
prefetchCount: Int = 100,
36+
redactPayload: Boolean = false,
3637
declare: Option[AutoDeclareQueueConfig] = None,
3738
consumerTag: String = "Default",
3839
poisonedMessageHandling: Option[PoisonedMessageHandlingConfig] = None)
@@ -45,13 +46,15 @@ final case class StreamingConsumerConfig(name: String,
4546
timeoutLogLevel: Level = Level.WARN,
4647
prefetchCount: Int = 100,
4748
queueBufferSize: Int = 100,
49+
redactPayload: Boolean = false,
4850
declare: Option[AutoDeclareQueueConfig] = None,
4951
consumerTag: String = "Default",
5052
poisonedMessageHandling: Option[PoisonedMessageHandlingConfig] = None)
5153

5254
final case class PullConsumerConfig(name: String,
5355
queueName: String,
5456
bindings: immutable.Seq[AutoBindQueueConfig],
57+
redactPayload: Boolean = false,
5558
declare: Option[AutoDeclareQueueConfig] = None,
5659
poisonedMessageHandling: Option[PoisonedMessageHandlingConfig] = None)
5760

core/src/test/scala/com/avast/clients/rabbitmq/DefaultRabbitMQConsumerTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ class DefaultRabbitMQConsumerTest extends TestBase {
437437
val base = new ConsumerBase[Task, Bytes](
438438
"test",
439439
"queueName",
440+
false,
440441
TestBase.testBlocker,
441442
ImplicitContextLogger.createLogger,
442443
monitor

core/src/test/scala/com/avast/clients/rabbitmq/DefaultRabbitMQPullConsumerTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ class DefaultRabbitMQPullConsumerTest extends TestBase {
266266
val base = new ConsumerBase[Task, A](
267267
"test",
268268
"queueName",
269+
false,
269270
TestBase.testBlocker,
270271
ImplicitContextLogger.createLogger,
271272
Monitor.noOp()

core/src/test/scala/com/avast/clients/rabbitmq/PoisonedMessageHandlerLiveTest.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,13 @@ class PoisonedMessageHandlerLiveTest extends TestBase with ScalaFutures {
206206
// run async:
207207
ex.execute(() => {
208208
while (true) {
209-
val PullResult.Ok(dwh) = cons.pull().await
210-
processed.incrementAndGet()
211-
dwh.handle(DeliveryResult.Republish()).await
209+
cons.pull().await match {
210+
case PullResult.Ok(dwh) =>
211+
processed.incrementAndGet()
212+
dwh.handle(DeliveryResult.Republish()).await
213+
214+
case PullResult.EmptyQueue => // 🤷‍
215+
}
212216
}
213217
})
214218

@@ -318,7 +322,7 @@ class PoisonedMessageHandlerLiveTest extends TestBase with ScalaFutures {
318322
sender.send(initialRoutingKey, Bytes.copyFromUtf8(n.toString), Some(MessageProperties(messageId = Some(s"msg_${n}_")))).await
319323
}
320324

321-
eventually(timeout(Span(90, Seconds)), interval(Span(1, Seconds))) {
325+
eventually(timeout(Span(120, Seconds)), interval(Span(1, Seconds))) {
322326
println(s"PROCESSED COUNT: ${processed.get()}")
323327
// we can't assert the `processed` here - some deliveries may have been cancelled before they were even executed
324328
assertResult(0)(testHelper.queue.getMessagesCount(queueName1))

core/src/test/scala/com/avast/clients/rabbitmq/RepublishStrategyTest.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ class RepublishStrategyTest extends TestBase {
9999

100100
private def newConsumer(channel: ServerChannel, republishStrategy: RepublishStrategy[Task])(
101101
userAction: DeliveryReadAction[Task, Bytes]): DefaultRabbitMQConsumer[Task, Bytes] = {
102-
val base = new ConsumerBase[Task, Bytes]("test", "queueName", TestBase.testBlocker, ImplicitContextLogger.createLogger, Monitor.noOp())
102+
val base =
103+
new ConsumerBase[Task, Bytes]("test", "queueName", false, TestBase.testBlocker, ImplicitContextLogger.createLogger, Monitor.noOp())
103104

104105
val channelOps = new ConsumerChannelOps[Task, Bytes](
105106
"test",

0 commit comments

Comments
 (0)