Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jaeger): add Jaeger for Distributed Tracing #156

Merged
merged 7 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions server/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("org.jooq:jooq:3.19.11")
jooqGenerator("org.jooq:jooq-meta-extensions:3.19.11")
implementation("io.micrometer:micrometer-tracing-bridge-otel")
implementation("io.opentelemetry:opentelemetry-exporter-otlp")
}

tasks.named<Test>("test") {
Expand Down Expand Up @@ -107,6 +109,7 @@ sourceSets {
main {
kotlin {
srcDir(layout.buildDirectory.dir("openapi/src/main").get().toString())
srcDir(layout.buildDirectory.dir("generated-src/jooq/main").get().toString())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package mu.muse.application
import mu.muse.application.muse.PersistenceConfiguration
import mu.muse.application.muse.RestConfiguration
import mu.muse.application.muse.SecurityConfiguration
import mu.muse.application.muse.TracingConfiguration
import mu.muse.application.muse.UseCaseConfiguration
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
Expand All @@ -14,5 +15,6 @@ import org.springframework.context.annotation.Import
RestConfiguration::class,
SecurityConfiguration::class,
MvcConfiguration::class,
TracingConfiguration::class,
)
class ApplicationConfiguration
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package mu.muse.application.muse

import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import org.jooq.ExecuteContext
import org.jooq.ExecuteListener
import java.util.concurrent.ConcurrentHashMap

class JaegerDbSpanCreator(
private val tracer: Tracer,
) : ExecuteListener {

companion object {
const val CONTEXT_KEY_SPAN_ID = "spanId"
}

private val spanIdToSpan = ConcurrentHashMap<String, Span>()

override fun start(ctx: ExecuteContext) {
val span = tracer.spanBuilder("PostgreSQL Query").startSpan()
span.setAttribute("sql", ctx.query().toString())
val spanId = span.spanContext.spanId
spanIdToSpan[spanId] = span
ctx.data(CONTEXT_KEY_SPAN_ID, spanId)
}

override fun end(ctx: ExecuteContext) {
val spanId = ctx.data(CONTEXT_KEY_SPAN_ID)
val span = spanIdToSpan.remove(spanId)
?: throw RuntimeException("No span for Span ID=`${spanId}`") // fail-fast in case of breaking invariant
span.end()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package mu.muse.application.muse

import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import io.opentelemetry.api.trace.Tracer
import mu.muse.persistence.instrument.jooq.JooqPostgresInstrumentIdGenerator
import mu.muse.persistence.instrument.jooq.JooqPostgresInstrumentRepository
import mu.muse.persistence.user.jooq.JooqPostgresUserIdGenerator
import mu.muse.persistence.user.jooq.JooqPostgresUserRepository
import org.jooq.DSLContext
import org.jooq.SQLDialect
import org.jooq.impl.DSL
import org.jooq.impl.DefaultConfiguration
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
Expand Down Expand Up @@ -47,7 +49,16 @@ class PersistenceConfiguration {
}

@Bean
fun dslContext(dataSource: DataSource): DSLContext = DSL.using(dataSource, SQLDialect.POSTGRES)
fun jooqConfiguration(dataSource: DataSource, otelTracer: Tracer) =
with(DefaultConfiguration()) {
set(dataSource)
set(SQLDialect.POSTGRES)
set(JaegerDbSpanCreator(otelTracer))
this
}

@Bean
fun dslContext(jooqConfiguration: org.jooq.Configuration) = DSL.using(jooqConfiguration)

@Bean
fun userIdGenerator(dslContext: DSLContext) = JooqPostgresUserIdGenerator(dslContext)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mu.muse.application.muse

import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class TracingConfiguration(
@Value("\${tracing.url}") private val tracingUrl: String,
) {

@Bean
fun otlpHttpSpanExporter(): OtlpGrpcSpanExporter {
return OtlpGrpcSpanExporter
.builder()
.setEndpoint(tracingUrl)
.build()
}
}
2 changes: 2 additions & 0 deletions server/app/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ spring.sql.init.mode=always
spring.sql.init.schema-locations=classpath:db/schema.sql
spring.sql.init.data-locations=classpath:db/data.sql

management.tracing.sampling.probability=1.0
tracing.url=${OPEN_TELEMETERY_URL} # there is no autoconfiguration for default exporter, so it requires to set up it explicitly
18 changes: 18 additions & 0 deletions tools/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ services:
- POSTGRES_DB
- POSTGRES_DSN
- CLIENT_PORT
- OPEN_TELEMETERY_URL
networks:
- muse
profiles:
Expand Down Expand Up @@ -88,6 +89,23 @@ services:
- muse
profiles:
- local

muse-jaeger:
image: jaegertracing/all-in-one:1.60
container_name: "muse-jaeger"
ports:
- "${OPEN_TELEMETERY_COLLECTOR_PORT}:4317"
- "${JAEGER_UI_PORT}:16686"
environment:
- COLLECTOR_OTLP_ENABLED=true
networks:
- muse
profiles:
- local
- dev
- staging
- prod

## portainer:
# image: portainer/portainer-ce:linux-amd64-2.20.3-alpine
# container_name: portainer
Expand Down
8 changes: 7 additions & 1 deletion tools/docker/env/dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ POSTGRES_PORT=50009
POSTGRES_USER=muse
POSTGRES_PASSWORD=muse
POSTGRES_DB=muse
POSTGRES_DSN=jdbc:postgresql://muse-postgres:5432/${POSTGRES_DB} # used default postgresql port due to bridge driver
POSTGRES_DSN=jdbc:postgresql://muse-postgres:5432/${POSTGRES_DB} # used default postgresql port due to bridge driver

OPEN_TELEMETERY_COLLECTOR_PORT=50023
OPEN_TELEMETERY_URL=http://muse-jaeger:4317

JAEGER_UI_PORT=50028

5 changes: 5 additions & 0 deletions tools/docker/env/local.env
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ POSTGRES_USER=muse
POSTGRES_PASSWORD=muse
POSTGRES_DB=muse
POSTGRES_DSN=jdbc:postgresql://muse-postgres:5432/${POSTGRES_DB} # used default postgresql port due to bridge driver

OPEN_TELEMETERY_COLLECTOR_PORT=50021
OPEN_TELEMETERY_URL=http://muse-jaeger:4317

JAEGER_UI_PORT=50026
5 changes: 5 additions & 0 deletions tools/docker/env/prod.env
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ POSTGRES_USER=muse
POSTGRES_PASSWORD=muse
POSTGRES_DB=muse
POSTGRES_DSN=jdbc:postgresql://muse-postgres:5432/${POSTGRES_DB} # used default postgresql port due to bridge driver

OPEN_TELEMETERY_COLLECTOR_PORT=50024
OPEN_TELEMETERY_URL=http://muse-jaeger:4317

JAEGER_UI_PORT=50025
8 changes: 7 additions & 1 deletion tools/docker/env/staging.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ POSTGRES_PORT=50015
POSTGRES_USER=muse
POSTGRES_PASSWORD=muse
POSTGRES_DB=muse
POSTGRES_DSN=jdbc:postgresql://muse-postgres:5432/${POSTGRES_DB} # used default postgresql port due to bridge driver
POSTGRES_DSN=jdbc:postgresql://muse-postgres:5432/${POSTGRES_DB} # used default postgresql port due to bridge driver

OPEN_TELEMETERY_COLLECTOR_PORT=50022
OPEN_TELEMETERY_URL=http://muse-jaeger:4317

JAEGER_UI_PORT=50027

Loading