Skip to content

Commit d9aec25

Browse files
authored
Adding Spotless to OpenTelemetry and Server module (#498)
1 parent 3d216a3 commit d9aec25

36 files changed

+1133
-1281
lines changed

integrations/opentelemetry/build.gradle.kts

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ plugins {
44
alias(libs.plugins.arrow.gradle.publish)
55
alias(libs.plugins.semver.gradle)
66
alias(libs.plugins.detekt)
7+
alias(libs.plugins.spotless)
78
}
89

910
dependencies { detektPlugins(project(":detekt-rules")) }
@@ -39,6 +40,15 @@ dependencies {
3940
testRuntimeOnly(libs.kotest.junit5)
4041
}
4142

43+
spotless {
44+
kotlin {
45+
target("**/*.kt")
46+
ktfmt().googleStyle().configure {
47+
it.setRemoveUnusedImport(true)
48+
}
49+
}
50+
}
51+
4252
tasks {
4353
withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
4454
dependsOn(":detekt-rules:assemble")

integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryConfig.kt

+33-34
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,39 @@ import io.opentelemetry.sdk.trace.export.BatchSpanProcessor
1111
import java.util.concurrent.TimeUnit
1212

1313
data class OpenTelemetryConfig(
14-
val endpointConfig: String,
15-
val defaultScopeName: String,
16-
val serviceName: String
14+
val endpointConfig: String,
15+
val defaultScopeName: String,
16+
val serviceName: String
1717
) {
1818

19-
fun newInstance(): OpenTelemetry {
20-
val jaegerOtlpExporter: OtlpGrpcSpanExporter = OtlpGrpcSpanExporter.builder()
21-
.setEndpoint(endpointConfig)
22-
.setTimeout(30, TimeUnit.SECONDS)
23-
.build()
24-
25-
val serviceNameResource: Resource =
26-
Resource.create(Attributes.of(AttributeKey.stringKey("service.name"), serviceName))
27-
28-
val tracerProvider = SdkTracerProvider.builder()
29-
.addSpanProcessor(BatchSpanProcessor.builder(jaegerOtlpExporter).build())
30-
.setResource(Resource.getDefault().merge(serviceNameResource))
31-
.build()
32-
33-
34-
val openTelemetry = OpenTelemetrySdk
35-
.builder()
36-
.setTracerProvider(tracerProvider)
37-
.build()
38-
39-
Runtime.getRuntime().addShutdownHook(Thread { tracerProvider.close() })
40-
return openTelemetry
41-
}
42-
43-
companion object {
44-
val DEFAULT = OpenTelemetryConfig(
45-
endpointConfig = "http://localhost:4317",
46-
defaultScopeName = "io.xef",
47-
serviceName = "xef"
48-
)
49-
}
19+
fun newInstance(): OpenTelemetry {
20+
val jaegerOtlpExporter: OtlpGrpcSpanExporter =
21+
OtlpGrpcSpanExporter.builder()
22+
.setEndpoint(endpointConfig)
23+
.setTimeout(30, TimeUnit.SECONDS)
24+
.build()
25+
26+
val serviceNameResource: Resource =
27+
Resource.create(Attributes.of(AttributeKey.stringKey("service.name"), serviceName))
28+
29+
val tracerProvider =
30+
SdkTracerProvider.builder()
31+
.addSpanProcessor(BatchSpanProcessor.builder(jaegerOtlpExporter).build())
32+
.setResource(Resource.getDefault().merge(serviceNameResource))
33+
.build()
34+
35+
val openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build()
36+
37+
Runtime.getRuntime().addShutdownHook(Thread { tracerProvider.close() })
38+
return openTelemetry
39+
}
40+
41+
companion object {
42+
val DEFAULT =
43+
OpenTelemetryConfig(
44+
endpointConfig = "http://localhost:4317",
45+
defaultScopeName = "io.xef",
46+
serviceName = "xef"
47+
)
48+
}
5049
}

integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt

+44-45
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,60 @@ import io.opentelemetry.api.trace.Span
88
import io.opentelemetry.api.trace.Tracer
99
import io.opentelemetry.context.Context
1010

11-
class OpenTelemetryMetric(
12-
private val config: OpenTelemetryConfig = OpenTelemetryConfig.DEFAULT
13-
) : Metric {
11+
class OpenTelemetryMetric(private val config: OpenTelemetryConfig = OpenTelemetryConfig.DEFAULT) :
12+
Metric {
1413

15-
private val conversations = mutableListOf<Pair<ConversationId, Context>>()
14+
private val conversations = mutableListOf<Pair<ConversationId, Context>>()
1615

17-
private val openTelemetry = config.newInstance()
16+
private val openTelemetry = config.newInstance()
1817

19-
override suspend fun <A> promptSpan(conversation: Conversation, prompt: Prompt, block: suspend Metric.() -> A): A {
20-
val cid = conversation.conversationId ?: return block()
18+
override suspend fun <A> promptSpan(
19+
conversation: Conversation,
20+
prompt: Prompt,
21+
block: suspend Metric.() -> A
22+
): A {
23+
val cid = conversation.conversationId ?: return block()
2124

22-
val parentContext = cid.getParentConversation()
25+
val parentContext = cid.getParentConversation()
2326

24-
val span = getTracer()
25-
.spanBuilder("Prompt: ${prompt.messages.lastOrNull()?.content ?: "empty"}")
26-
.setParent(parentContext)
27-
.startSpan()
27+
val span =
28+
getTracer()
29+
.spanBuilder("Prompt: ${prompt.messages.lastOrNull()?.content ?: "empty"}")
30+
.setParent(parentContext)
31+
.startSpan()
2832

29-
return try {
30-
val output = block()
31-
span.makeCurrent().use {
32-
span.setAttribute("number-of-messages", prompt.messages.count().toString())
33-
span.setAttribute("last-message", prompt.messages.lastOrNull()?.content ?: "empty")
34-
}
35-
output
36-
} finally {
37-
span.end()
38-
}
33+
return try {
34+
val output = block()
35+
span.makeCurrent().use {
36+
span.setAttribute("number-of-messages", prompt.messages.count().toString())
37+
span.setAttribute("last-message", prompt.messages.lastOrNull()?.content ?: "empty")
38+
}
39+
output
40+
} finally {
41+
span.end()
3942
}
43+
}
4044

41-
override fun log(conversation: Conversation, message: String) {
42-
val cid = conversation.conversationId ?: return
45+
override fun log(conversation: Conversation, message: String) {
46+
val cid = conversation.conversationId ?: return
4347

44-
val parentContext = cid.getParentConversation()
48+
val parentContext = cid.getParentConversation()
4549

46-
val span: Span = getTracer().spanBuilder(message)
47-
.setParent(parentContext)
48-
.startSpan()
49-
span.end()
50-
}
51-
52-
private fun ConversationId.getParentConversation(): Context {
53-
val parent = conversations.find { it.first == this }?.second
54-
return if (parent == null) {
55-
val newParent = getTracer()
56-
.spanBuilder(value)
57-
.startSpan()
58-
newParent.end()
59-
val newContext = Context.current().with(newParent)
60-
conversations.add(this to newContext)
61-
newContext
62-
} else parent
63-
}
50+
val span: Span = getTracer().spanBuilder(message).setParent(parentContext).startSpan()
51+
span.end()
52+
}
6453

65-
private fun getTracer(scopeName: String? = null): Tracer =
66-
openTelemetry.getTracer(scopeName ?: config.defaultScopeName)
54+
private fun ConversationId.getParentConversation(): Context {
55+
val parent = conversations.find { it.first == this }?.second
56+
return if (parent == null) {
57+
val newParent = getTracer().spanBuilder(value).startSpan()
58+
newParent.end()
59+
val newContext = Context.current().with(newParent)
60+
conversations.add(this to newContext)
61+
newContext
62+
} else parent
63+
}
6764

65+
private fun getTracer(scopeName: String? = null): Tracer =
66+
openTelemetry.getTracer(scopeName ?: config.defaultScopeName)
6867
}

server/build.gradle.kts

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ plugins {
44
alias(libs.plugins.node.gradle)
55
alias(libs.plugins.arrow.gradle.publish)
66
alias(libs.plugins.semver.gradle)
7+
alias(libs.plugins.spotless)
78
}
89

910
repositories {
@@ -68,6 +69,15 @@ dependencies {
6869
testRuntimeOnly(libs.kotest.junit5)
6970
}
7071

72+
spotless {
73+
kotlin {
74+
target("**/*.kt")
75+
ktfmt().googleStyle().configure {
76+
it.setRemoveUnusedImport(true)
77+
}
78+
}
79+
}
80+
7181
tasks.getByName<Copy>("processResources") {
7282
dependsOn(projects.xefGpt4all.dependencyProject.tasks.getByName("jvmProcessResources"))
7383
from("${projects.xefGpt4all.dependencyProject.buildDir}/processedResources/jvm/main")

server/src/main/kotlin/com/xebia/functional/xef/server/Server.kt

+48-51
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import com.xebia.functional.xef.server.services.RepositoryService
1414
import io.ktor.client.*
1515
import io.ktor.client.engine.cio.*
1616
import io.ktor.client.plugins.auth.*
17+
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation
1718
import io.ktor.client.plugins.logging.*
1819
import io.ktor.http.*
1920
import io.ktor.serialization.kotlinx.json.*
@@ -27,63 +28,59 @@ import io.ktor.server.routing.*
2728
import kotlinx.coroutines.awaitCancellation
2829
import org.jetbrains.exposed.sql.Database
2930
import org.slf4j.LoggerFactory
30-
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation
3131

3232
object Server {
33-
@JvmStatic
34-
fun main(args: Array<String>) = SuspendApp {
35-
resourceScope {
36-
val config = ConfigFactory.load("database.conf").resolve()
37-
val xefDBConfig = XefDatabaseConfig.load("xef", config)
38-
Migrate.migrate(xefDBConfig)
39-
40-
val logger = LoggerFactory.getLogger("xef-server")
33+
@JvmStatic
34+
fun main(args: Array<String>) = SuspendApp {
35+
resourceScope {
36+
val config = ConfigFactory.load("database.conf").resolve()
37+
val xefDBConfig = XefDatabaseConfig.load("xef", config)
38+
Migrate.migrate(xefDBConfig)
4139

42-
val hikariDataSourceXefDB = RepositoryService.getHikariDataSource(
43-
xefDBConfig.getUrl(),
44-
xefDBConfig.user,
45-
xefDBConfig.password
46-
)
47-
Database.connect(hikariDataSourceXefDB)
48-
val vectorStoreConfig = XefVectorStoreConfig.load("xef-vector-store", config)
49-
val vectorStoreService = vectorStoreConfig.getVectorStoreService(config, logger)
50-
vectorStoreService.addCollection()
40+
val logger = LoggerFactory.getLogger("xef-server")
5141

42+
val hikariDataSourceXefDB =
43+
RepositoryService.getHikariDataSource(
44+
xefDBConfig.getUrl(),
45+
xefDBConfig.user,
46+
xefDBConfig.password
47+
)
48+
Database.connect(hikariDataSourceXefDB)
49+
val vectorStoreConfig = XefVectorStoreConfig.load("xef-vector-store", config)
50+
val vectorStoreService = vectorStoreConfig.getVectorStoreService(config, logger)
51+
vectorStoreService.addCollection()
5252

53-
val ktorClient = HttpClient(CIO) {
54-
engine {
55-
requestTimeout = 0 // disabled
56-
}
57-
install(Auth)
58-
install(Logging) {
59-
level = LogLevel.INFO
60-
}
61-
install(ClientContentNegotiation)
62-
}
53+
val ktorClient =
54+
HttpClient(CIO) {
55+
engine {
56+
requestTimeout = 0 // disabled
57+
}
58+
install(Auth)
59+
install(Logging) { level = LogLevel.INFO }
60+
install(ClientContentNegotiation)
61+
}
6362

64-
server(factory = Netty, port = 8081, host = "0.0.0.0") {
65-
install(CORS) {
66-
allowNonSimpleContentTypes = true
67-
HttpMethod.DefaultMethods.forEach { allowMethod(it) }
68-
allowHeaders { true }
69-
anyHost()
70-
}
71-
install(ContentNegotiation) { json() }
72-
install(Resources)
73-
install(Authentication) {
74-
bearer("auth-bearer") {
75-
authenticate { tokenCredential ->
76-
UserIdPrincipal(tokenCredential.token)
77-
}
78-
}
79-
}
80-
exceptionsHandler()
81-
routing {
82-
xefRoutes(logger)
83-
aiRoutes(ktorClient)
84-
}
85-
}
86-
awaitCancellation()
63+
server(factory = Netty, port = 8081, host = "0.0.0.0") {
64+
install(CORS) {
65+
allowNonSimpleContentTypes = true
66+
HttpMethod.DefaultMethods.forEach { allowMethod(it) }
67+
allowHeaders { true }
68+
anyHost()
69+
}
70+
install(ContentNegotiation) { json() }
71+
install(Resources)
72+
install(Authentication) {
73+
bearer("auth-bearer") {
74+
authenticate { tokenCredential -> UserIdPrincipal(tokenCredential.token) }
75+
}
76+
}
77+
exceptionsHandler()
78+
routing {
79+
xefRoutes(logger)
80+
aiRoutes(ktorClient)
8781
}
82+
}
83+
awaitCancellation()
8884
}
85+
}
8986
}

server/src/main/kotlin/com/xebia/functional/xef/server/Web.kt

+6-11
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,9 @@ import io.ktor.server.routing.*
77

88
object WebApp {
99

10-
@JvmStatic
11-
fun main(args: Array<String>) {
12-
embeddedServer(Netty, port = 8080) {
13-
routing {
14-
singlePageApplication {
15-
react("web/dist")
16-
}
17-
}
18-
}.start(wait = true)
19-
}
20-
}
10+
@JvmStatic
11+
fun main(args: Array<String>) {
12+
embeddedServer(Netty, port = 8080) { routing { singlePageApplication { react("web/dist") } } }
13+
.start(wait = true)
14+
}
15+
}

0 commit comments

Comments
 (0)