1- package kamon .instrumentation .lettuce
1+ package kamon .instrumentation .combined
22
3- import io .lettuce .core .RedisClient
3+
4+ import io .lettuce .core .{RedisClient => LettuceClient }
45import kamon .testkit .{MetricInspection , TestSpanReporter }
56import kamon .trace .Span .Kind
67import org .scalatest .concurrent .{Eventually , ScalaFutures }
78import org .scalatest .{BeforeAndAfterAll , Matchers , OptionValues , WordSpec }
9+ import org .slf4j .LoggerFactory
810import org .testcontainers .containers .GenericContainer
911import org .testcontainers .utility .DockerImageName
12+ import redis .clients .jedis .Jedis
13+ import redis .{RedisBlockingClient , RedisClient }
1014
1115import java .time .Duration
1216import scala .concurrent .duration .DurationInt
1317import scala .util .control .NonFatal
1418
15- class LettuceInstrumentationSpec extends WordSpec
19+
20+ class RedisInstrumentationsSpec extends WordSpec
1621 with Matchers
1722 with ScalaFutures
1823 with Eventually
@@ -21,20 +26,45 @@ class LettuceInstrumentationSpec extends WordSpec
2126 with OptionValues
2227 with TestSpanReporter {
2328
29+ private val logger = LoggerFactory .getLogger(classOf [RedisInstrumentationsSpec ])
2430 var container : GenericContainer [Nothing ] = _
31+
2532 override def beforeAll : Unit = {
2633 val REDIS_IMAGE = DockerImageName .parse(" redis" )
2734 container = new GenericContainer (REDIS_IMAGE ).withExposedPorts(6379 )
35+
2836 container.start()
2937 }
3038
3139 override def afterAll : Unit = {
3240 container.stop()
3341 }
3442
43+ " the Jedis instrumentation" should {
44+ " generate a client span for get and set commands" in {
45+ val jedis = new Jedis (container.getHost, container.getFirstMappedPort)
46+ jedis.set(" foo" , " bar" )
47+
48+ eventually(timeout(2 .seconds)) {
49+ val span = testSpanReporter().nextSpan().get
50+ span.operationName shouldBe " redis.command.SET"
51+ span.kind shouldBe Kind .Client
52+ }
53+
54+ testSpanReporter().clear()
55+
56+ jedis.get(" foo" )
57+ eventually(timeout(2 .seconds)) {
58+ val span = testSpanReporter().nextSpan().get
59+ span.operationName shouldBe " redis.command.GET"
60+ span.kind shouldBe Kind .Client
61+ }
62+ }
63+ }
64+
3565 " the Lettuce instrumentation" should {
3666 " generate a client span for async commands" in {
37- val client = RedisClient .create(s " redis:// ${container.getHost}: ${container.getFirstMappedPort}" )
67+ val client = LettuceClient .create(s " redis:// ${container.getHost}: ${container.getFirstMappedPort}" )
3868 val connection = client.connect
3969 val asyncCommands = connection.async()
4070 asyncCommands.set(" key" , " Hello, Redis!" )
@@ -49,7 +79,7 @@ class LettuceInstrumentationSpec extends WordSpec
4979 }
5080
5181 " generate a client span for sync commands" in {
52- val client = RedisClient .create(s " redis:// ${container.getHost}: ${container.getFirstMappedPort}" )
82+ val client = LettuceClient .create(s " redis:// ${container.getHost}: ${container.getFirstMappedPort}" )
5383 val connection = client.connect
5484 val commands = connection.sync()
5585
@@ -65,7 +95,7 @@ class LettuceInstrumentationSpec extends WordSpec
6595 }
6696
6797 " fail a span that times out" in {
68- val client = RedisClient .create(s " redis:// ${container.getHost}: ${container.getFirstMappedPort}" )
98+ val client = LettuceClient .create(s " redis:// ${container.getHost}: ${container.getFirstMappedPort}" )
6999 client.setDefaultTimeout(Duration .ofNanos(1 ))
70100 val connection = client.connect
71101 val commands = connection.sync()
@@ -86,4 +116,32 @@ class LettuceInstrumentationSpec extends WordSpec
86116 client.shutdown()
87117 }
88118 }
119+
120+ " the Rediscala instrumentation" should {
121+ implicit val akkaSystem = akka.actor.ActorSystem ()
122+ " generate only one client span for commands" in {
123+ val client = RedisClient (host = container.getHost, port = container.getFirstMappedPort)
124+ client.set(" a" , " a" )
125+
126+ eventually(timeout(30 .seconds)) {
127+ val span = testSpanReporter().nextSpan().value
128+ span.operationName shouldBe " redis.command.Set"
129+ span.hasError shouldBe false
130+ }
131+ client.shutdown()
132+ }
133+
134+ " generate only one client span when using the blocking client" in {
135+ val blockingClient = RedisBlockingClient (host = container.getHost, port = container.getFirstMappedPort)
136+ blockingClient.blpop(Seq (" a" , " b" , " c" ))
137+
138+ eventually(timeout(30 .seconds)) {
139+ val span = testSpanReporter().nextSpan().value
140+ span.operationName shouldBe " redis.command.Blpop"
141+ span.hasError shouldBe true
142+ }
143+ blockingClient.stop()
144+ }
145+
146+ }
89147}
0 commit comments