Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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 .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ jobs:
bash -n deploy/observability/alloy/validate.sh
bash -n deploy/observability/preflight-host.sh
bash -n deploy/observability/tests/host-preflight-test.sh
bash -n deploy/observability/tests/recommendation-assets-test.sh
bash -n deploy/observability/tests/update-api-test.sh
bash -n deploy/observability/update-api.sh
test -x deploy/observability/alloy/validate.sh
test -x deploy/observability/preflight-host.sh
test -x deploy/observability/tests/host-preflight-test.sh
test -x deploy/observability/tests/recommendation-assets-test.sh
test -x deploy/observability/tests/update-api-test.sh
test -x deploy/observability/update-api.sh

Expand All @@ -63,3 +65,4 @@ jobs:
run: |
jq empty deploy/observability/grafana/mapleland-production-overview.json
jq empty deploy/observability/grafana/alert-rules.json
deploy/observability/tests/recommendation-assets-test.sh
22 changes: 22 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ dependencies {
testImplementation 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:mysql'
testImplementation 'net.ttddyy:datasource-proxy:1.10.1'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

Expand All @@ -81,7 +84,26 @@ sourceSets {
}
}

// JGit bundled by gradle-git-properties 2.4.1 treats a linked-worktree `.git`
// pointer file as a directory. CI/release checkouts still generate git.properties;
// linked worktrees skip only that metadata task so the required clean test/bootJar
// validation can run from an isolated feature worktree.
if (file('.git').isFile()) {
def commonGitDir = providers.exec {
commandLine 'git', 'rev-parse', '--path-format=absolute', '--git-common-dir'
}.standardOutput.asText.get().trim()
gitProperties {
dotGitDirectory.set(file(commonGitDir))
}
tasks.named('generateGitProperties') {
enabled = false
}
}

tasks.named('test') {
useJUnitPlatform()
// Testcontainers 1.20.6 defaults to an API older than Docker Engine 29's
// supported floor. API 1.40 is accepted by both current CI engines and
// Docker 29; callers can still override it with -Dapi.version.
systemProperty 'api.version', System.getProperty('api.version', '1.40')
}
95 changes: 52 additions & 43 deletions deploy/observability/alloy/config.alloy
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,13 @@ prometheus.scrape "application" {
prometheus.relabel "application" {
forward_to = [prometheus.remote_write.grafana_cloud.receiver]

// Preserve only the metrics needed for RED, JVM, process, and HikariCP
// views. Route-template `uri` remains; high-cardinality identifiers do not.
// Preserve only the metrics needed for RED, JVM, process, HikariCP, and the
// bounded recommendation outcome/result views. Route-template `uri` remains;
// high-cardinality identifiers do not.
rule {
action = "keep"
source_labels = ["__name__"]
regex = "^(up|http_server_requests_seconds_(bucket|count|sum|max)|jvm_memory_(used|committed|max)_bytes|jvm_gc_pause_seconds_(bucket|count|sum|max)|jvm_threads_(live|daemon|peak|states)_threads|process_(cpu|memory|resident|virtual|uptime|start|files).*|system_cpu_(usage|count)|hikaricp_connections_(active|idle|pending|max|min|timeout_total|acquire_seconds_(bucket|count|sum|max)|creation_seconds_(bucket|count|sum|max)|usage_seconds_(bucket|count|sum|max)))$"
regex = "^(up|http_server_requests_seconds_(bucket|count|sum|max)|jvm_memory_(used|committed|max)_bytes|jvm_gc_pause_seconds_(bucket|count|sum|max)|jvm_threads_(live|daemon|peak|states)_threads|process_(cpu|memory|resident|virtual|uptime|start|files).*|system_cpu_(usage|count)|hikaricp_connections_(active|idle|pending|max|min|timeout_total|acquire_seconds_(bucket|count|sum|max)|creation_seconds_(bucket|count|sum|max)|usage_seconds_(bucket|count|sum|max))|mapleland_recommendation_requests_total|mapleland_recommendation_results_recommendations_(count|sum|max))$"
}

rule {
Expand Down Expand Up @@ -224,28 +225,32 @@ loki.process "application" {

stage.json {
expressions = {
ecs_timestamp = "\"@timestamp\"",
level = "\"log.level\"",
logger = "\"log.logger\"",
thread = "\"process.thread.name\"",
process_pid = "\"process.pid\"",
service_name = "\"service.name\"",
deployment_environment = "\"service.environment\"",
service_version = "\"service.version\"",
event_action = "\"event.action\"",
event_outcome = "\"event.outcome\"",
event_category = "\"event.category\"",
http_request_method = "\"http.request.method\"",
http_response_status_code = "\"http.response.status_code\"",
http_route = "\"http.route\"",
error_type = "\"error.type\"",
error_message = "\"error.message\"",
trace_id = "\"trace.id\"",
span_id = "\"span.id\"",
request_id = "\"request.id\"",
mapleland_batch_type = "\"mapleland.batch.type\"",
mapleland_batch_record_count = "\"mapleland.batch.record_count\"",
mapleland_external_system = "\"mapleland.external.system\"",
ecs_timestamp = "\"@timestamp\"",
level = "\"log.level\"",
logger = "\"log.logger\"",
thread = "\"process.thread.name\"",
process_pid = "\"process.pid\"",
service_name = "\"service.name\"",
deployment_environment = "\"service.environment\"",
service_version = "\"service.version\"",
event_action = "\"event.action\"",
event_outcome = "\"event.outcome\"",
event_category = "\"event.category\"",
http_request_method = "\"http.request.method\"",
http_response_status_code = "\"http.response.status_code\"",
http_route = "\"http.route\"",
error_type = "\"error.type\"",
error_message = "\"error.message\"",
trace_id = "\"trace.id\"",
span_id = "\"span.id\"",
request_id = "\"request.id\"",
mapleland_batch_type = "\"mapleland.batch.type\"",
mapleland_batch_record_count = "\"mapleland.batch.record_count\"",
mapleland_external_system = "\"mapleland.external.system\"",
event_duration = "\"event.duration\"",
mapleland_recommendation_engine = "\"mapleland.recommendation.engine\"",
mapleland_api_version = "\"mapleland.api.version\"",
mapleland_result_count = "\"mapleland.result.count\"",
}
drop_malformed = false
}
Expand Down Expand Up @@ -291,24 +296,28 @@ loki.process "application" {
// ECS and mapleland.* fields remain available through `| json` as well.
stage.structured_metadata {
values = {
logger = "logger",
thread = "thread",
process_pid = "process_pid",
service_version = "service_version",
event_action = "event_action",
event_outcome = "event_outcome",
event_category = "event_category",
http_request_method = "http_request_method",
http_response_status_code = "http_response_status_code",
http_route = "http_route",
error_type = "error_type",
error_message = "error_message",
trace_id = "trace_id",
span_id = "span_id",
request_id = "request_id",
mapleland_batch_type = "mapleland_batch_type",
mapleland_batch_record_count = "mapleland_batch_record_count",
mapleland_external_system = "mapleland_external_system",
logger = "logger",
thread = "thread",
process_pid = "process_pid",
service_version = "service_version",
event_action = "event_action",
event_outcome = "event_outcome",
event_category = "event_category",
http_request_method = "http_request_method",
http_response_status_code = "http_response_status_code",
http_route = "http_route",
error_type = "error_type",
error_message = "error_message",
trace_id = "trace_id",
span_id = "span_id",
request_id = "request_id",
mapleland_batch_type = "mapleland_batch_type",
mapleland_batch_record_count = "mapleland_batch_record_count",
mapleland_external_system = "mapleland_external_system",
event_duration = "event_duration",
mapleland_recommendation_engine = "mapleland_recommendation_engine",
mapleland_api_version = "mapleland_api_version",
mapleland_result_count = "mapleland_result_count",
}
}

Expand Down
3 changes: 3 additions & 0 deletions deploy/observability/docker-compose.override.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ services:
MANAGEMENT_SERVER_PORT: "18080"
MANAGEMENT_SCRAPE_TOKEN: "${MANAGEMENT_SCRAPE_TOKEN:?MANAGEMENT_SCRAPE_TOKEN must be set}"
SERVICE_VERSION: "${SERVICE_VERSION:-unknown}"
RECOMMENDATION_V1_ENGINE: "${RECOMMENDATION_V1_ENGINE:?RECOMMENDATION_V1_ENGINE must be AURA or MYSQL}"
RECOMMENDATION_V2_ENABLED: "${RECOMMENDATION_V2_ENABLED:?RECOMMENDATION_V2_ENABLED must be true or false}"
RECOMMENDATION_QUERY_TIMEOUT_SECONDS: "${RECOMMENDATION_QUERY_TIMEOUT_SECONDS:?RECOMMENDATION_QUERY_TIMEOUT_SECONDS must be set}"
ports:
- "127.0.0.1:18080:18080"
volumes:
Expand Down
Loading
Loading