Skip to content
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
10 changes: 10 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
### Description

> 한줄요약

<br>

### Changes

- changes
-
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## monilab-exporter-ex
## mexporter

monilab exporter ex는 exporter 개발 이전
> made by intelliegence-lab

exporter의 요구사항을 파악하기 위한, (+알아야할 범위를 좁히기 위한) 예제 서버입니다.
monilab - jvm exporter service

차후 예제 서버 결과를 토대로 별도의 exporter를 개발하고 ga할 예정
(jvm monitoring, ai agent)
Binary file added ai-models/gc_test.model
Binary file not shown.
Binary file added ai-models/gc_train.model
Binary file not shown.
54 changes: 54 additions & 0 deletions ai/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
plugins {
kotlin("jvm")
kotlin("plugin.spring")
id("org.springframework.boot") version "3.5.5"
id("io.spring.dependency-management") version "1.1.7"
id("org.jlleitschuh.gradle.ktlint") version "12.1.0"
application
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.2")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")

implementation(project(":exporter"))

implementation("com.github.haifengl:smile-core:2.6.0")
implementation("com.github.haifengl:smile-plot:2.6.0")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
useJUnitPlatform()
}

ktlint {
filter {
exclude { entry -> entry.file.path.contains("src/test/") }
}
}

tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask> {
if (name.contains("TestSourceSet")) {
enabled = false
}
}

tasks.named("ktlintCheck") {
enabled = false
}
tasks.named("ktlintMainSourceSetCheck") {
enabled = false
}
12 changes: 12 additions & 0 deletions ai/src/main/kotlin/lab/Application.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package lab

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class Application

fun main(args: Array<String>) {
runApplication<Application>(*args)
}

22 changes: 22 additions & 0 deletions ai/src/main/kotlin/lab/ai-model/gc/GcFeatureExtractor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package lab.`ai-model`.gc


object GcFeatureExtractor {
private val gcStrategyMap = mapOf(
"G1" to 0.0,
"Parallel" to 1.0,
"Serial" to 2.0,
"ZGC" to 3.0
)

fun extract(gc: GcTrainData): DoubleArray {
return doubleArrayOf(
gc.count.toDouble(),
gc.time.toDouble(),
gc.pause.toDouble(),
gc.allocationRate,
gc.liveDataSize.toDouble(),
gcStrategyMap[gc.gcStrategy] ?: -1.0
)
}
}
11 changes: 11 additions & 0 deletions ai/src/main/kotlin/lab/ai-model/gc/GcTrainData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package lab.`ai-model`.gc

data class GcTrainData(
val count: Long,
val time: Long,
val pause: Long,
val allocationRate: Double,
val liveDataSize: Long,
val gcStrategy: String,
val label: Int // 1 정상, 0 비정상
)
78 changes: 78 additions & 0 deletions ai/src/main/kotlin/lab/ai-model/gc/GcTrainer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package lab.`ai-model`.gc

import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
import smile.classification.LogisticRegression
import smile.data.DataFrame
import smile.data.formula.Formula
import smile.data.vector.DoubleVector
import smile.data.vector.IntVector
import java.io.File
import java.io.ObjectOutputStream

@Component
class GcTrainer {
private val extractor: GcFeatureExtractor by lazy { GcFeatureExtractor }
private var model: LogisticRegression? = null
private val log = LoggerFactory.getLogger(GcTrainer::class.java)

private val projectRootDir: String = System.getProperty("user.dir")
private val modelDir = File("$projectRootDir/ai-models/gc-model").apply { mkdirs() }

fun train() {
log.info("Start GcTrainer training...")
val dataList = getDataList()
if (dataList.isEmpty()) {
log.warn("No data available for training.")
return
}

log.info("Training data size: ${dataList.size}")
log.info("Sample training data: ${dataList.take(3)}")

val features = dataList.map { extractor.extract(it) }.toTypedArray()
val labels = dataList.map { it.label }.toIntArray()
val df = DataFrame.of(
DoubleVector.of("count", features.map { it[0] }.toDoubleArray()),
DoubleVector.of("time", features.map { it[1] }.toDoubleArray()),
DoubleVector.of("pause", features.map { it[2] }.toDoubleArray()),
DoubleVector.of("allocationRate", features.map { it[3] }.toDoubleArray()),
DoubleVector.of("liveDataSize", features.map { it[4] }.toDoubleArray()),
DoubleVector.of("gcStrategy", features.map { it[5] }.toDoubleArray()),
IntVector.of("label", labels)
)

val formula = Formula.lhs("label")
model = LogisticRegression.fit(formula, df)
log.info("GcTrainer training completed.")

saveModel("train")
saveModel("test")
}

private fun saveModel(key: String) {
val m = model ?: run {
log.error("Model not trained. Cannot save [$key].")
return
}

val file = File(modelDir, "gc_$key.model")

ObjectOutputStream(file.outputStream().buffered()).use { oos ->
oos.writeObject(m)
}

log.info("💾 Saved model [$key] → ${file.absolutePath}")
}

private fun getDataList(): List<GcTrainData> {
// TODO - khope heesung이 만들어준 data get에서 가져와쓰는걸로 수정
return listOf(
GcTrainData(100, 400, 30, 1.2, 300_000, "G1", label = 1),
GcTrainData(150, 700, 300, 3.8, 1_000_000, "G1", label = 0),
GcTrainData(80, 250, 15, 0.8, 200_000, "Parallel", label = 1),
GcTrainData(400, 1200, 700, 6.2, 2_000_000, "G1", label = 0),
GcTrainData(90, 320, 20, 1.5, 350_000, "Serial", label = 1)
)
}
}
16 changes: 16 additions & 0 deletions ai/src/main/kotlin/lab/api/ApiController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package lab.api

import lab.`ai-model`.gc.GcTrainer
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class ApiController(
private val gcTrainer: GcTrainer
) {

@GetMapping("/api/train")
fun train() {
gcTrainer.train()
}
}
2 changes: 1 addition & 1 deletion cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
languageVersion.set(JavaLanguageVersion.of(17))
}
}

Expand Down
2 changes: 1 addition & 1 deletion exporter/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
languageVersion.set(JavaLanguageVersion.of(17))
}
}

Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
rootProject.name = "monilab-exporter-ex"
include(":exporter")
include(":cli")
include(":ai")