Skip to content

Commit e85d971

Browse files
authored
feat: adding metrics and Vagrantfile to big example (#25)
* feat: adding metrics and Vagrantfile to big example * feat: adding docker image creation for big example
1 parent 5d105c6 commit e85d971

8 files changed

Lines changed: 209 additions & 29 deletions

File tree

.github/workflows/docker.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
target: [ diningPhilosophers, count, cigaretteSmokers, chameneos ]
18+
target: [ diningPhilosophers, count, cigaretteSmokers, chameneo, big ]
1919
permissions:
2020
packages: write
2121
contents: read

big.Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM gradle:9.3.0-jdk25 AS build
2+
3+
COPY --chown=gradle:gradle . /usr/src/cirrina-baselines
4+
5+
WORKDIR /usr/src/cirrina-baselines
6+
7+
RUN gradle :big:distZip
8+
9+
RUN unzip big/build/distributions/big.zip -d /tmp
10+
11+
FROM gcr.io/distroless/java25-debian13 AS runtime
12+
13+
COPY --from=build /tmp/big /opt/big
14+
15+
ENTRYPOINT ["java", "-cp", "/opt/big/lib/*", "ac.at.uibk.dps.dapr.big.BigKt"]

big.Vagrantfile

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
2+
Vagrant.configure("2") do |config|
3+
nodes = {
4+
"redis_pub_sub" => {},
5+
"sink" => {},
6+
"w0" => { "BIG_ID" => "0" },
7+
"w1" => { "BIG_ID" => "1" },
8+
"w2" => { "BIG_ID" => "2" },
9+
"w3" => { "BIG_ID" => "3" },
10+
"w4" => { "BIG_ID" => "4" },
11+
"w5" => { "BIG_ID" => "5" },
12+
"w6" => { "BIG_ID" => "6" },
13+
"w7" => { "BIG_ID" => "7" },
14+
"w8" => { "BIG_ID" => "8" },
15+
"w9" => { "BIG_ID" => "9" },
16+
"w10" => { "BIG_ID" => "10" },
17+
"w11" => { "BIG_ID" => "11" }
18+
}
19+
20+
nodes.each do |name, env_vars|
21+
config.vm.define name do |node|
22+
node.vm.box = "generic/ubuntu2004"
23+
ip_suffix = case name
24+
when "sink" then 10
25+
when "redis_pub_sub" then 9
26+
else 11 + name[1..-1].to_i
27+
end
28+
node.vm.network "private_network", ip: "192.168.56.#{ip_suffix}"
29+
node.vm.synced_folder ".", "/app"
30+
node.vm.provision "shell", inline: <<-SHELL
31+
apt-get update -qq && apt-get install -y docker.io linuxptp
32+
33+
docker load -i /app/big.tar.gz
34+
35+
if [ "#{name}" = "redis_pub_sub" ]; then
36+
docker run -d --name redis --network host redis:8.2.4-alpine \
37+
redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru --save ""
38+
exit 0
39+
fi
40+
# Every node gets own state store (default config is fine)
41+
docker rm -f redis || true
42+
docker run -d --name redis --network host redis:8.2.4-alpine
43+
44+
# Every node gets its own placement
45+
docker rm -f placement || true
46+
docker run -d --name placement --network host daprio/placement:1.16.0 ./placement --port 50006
47+
48+
# Sidecar
49+
docker rm -f #{name}-sidecar || true
50+
docker run -d \
51+
--name #{name}-sidecar \
52+
--network host \
53+
-v /app/config/redis/components-vagrant:/components \
54+
daprio/daprd:edge \
55+
./daprd \
56+
--app-id #{name}-sidecar \
57+
--app-port 3000 \
58+
--resources-path /components \
59+
--placement-host-address localhost:50006 \
60+
--metrics-port 9091
61+
62+
sleep 2
63+
64+
# Application
65+
docker rm -f #{name} || true
66+
if [ "#{name}" = "sink" ]; then
67+
docker run -d \
68+
--name #{name} \
69+
--network host \
70+
-e ROLE=sink \
71+
-e DAPR_HTTP_ENDPOINT=http://localhost:3500 \
72+
-e METRICS_DIRECTORY=/app/metrics \
73+
-e DAPR_GRPC_ENDPOINT=http://localhost:50001 \
74+
-v /app/big/runTest/metrics_#{name}:/app/metrics \
75+
big
76+
else
77+
docker run -d \
78+
--name #{name} \
79+
--network host \
80+
-e ROLE=big \
81+
-e BIG_ID=#{env_vars['BIG_ID']} \
82+
-e DAPR_HTTP_ENDPOINT=http://localhost:3500 \
83+
-e METRICS_DIRECTORY=/app/metrics \
84+
-e DAPR_GRPC_ENDPOINT=http://localhost:50001 \
85+
-v /app/big/runTest/metrics_#{name}:/app/metrics \
86+
big
87+
fi
88+
89+
nohup bash -c 'while true; do docker stats --no-stream --format "$(date +%s),{{.Name}},{{.CPUPerc}},{{.MemUsage}}" >> /app/big/run/metrics_#{name}/docker_stats.csv; sleep 1; done' &
90+
SHELL
91+
end
92+
end
93+
end

big/src/main/kotlin/ac/at/uibk/dps/dapr/big/Big.kt

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,61 @@ package ac.at.uibk.dps.dapr.big
33
import ac.at.uibk.dps.dapr.big.big.BigActor
44
import ac.at.uibk.dps.dapr.big.big.BigActorImpl
55
import ac.at.uibk.dps.dapr.big.sink.SinkActorImpl
6+
import com.codahale.metrics.CsvReporter
7+
import com.codahale.metrics.MetricRegistry
68
import io.dapr.actors.ActorId
79
import io.dapr.actors.client.ActorClient
810
import io.dapr.actors.client.ActorProxyBuilder
911
import io.dapr.actors.runtime.ActorRuntime
12+
import io.micrometer.core.instrument.Clock
13+
import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics
14+
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics
15+
import io.micrometer.core.instrument.binder.system.ProcessorMetrics
16+
import io.micrometer.core.instrument.dropwizard.DropwizardConfig
17+
import io.micrometer.core.instrument.dropwizard.DropwizardMeterRegistry
18+
import io.micrometer.core.instrument.util.HierarchicalNameMapper
19+
import java.nio.file.Files
20+
import java.nio.file.Paths
21+
import java.util.concurrent.TimeUnit
1022
import org.springframework.boot.ApplicationArguments
1123
import org.springframework.boot.ApplicationRunner
1224
import org.springframework.boot.autoconfigure.SpringBootApplication
1325
import org.springframework.boot.runApplication
1426
import org.springframework.stereotype.Component
1527

16-
@SpringBootApplication class Big
28+
@SpringBootApplication
29+
class Big {
30+
companion object {
31+
val metricsDirectory = System.getenv("METRICS_DIRECTORY") ?: "metrics"
32+
33+
fun provideMetricRegistry(): MetricRegistry =
34+
MetricRegistry().apply {
35+
val path = Paths.get(metricsDirectory).toAbsolutePath()
36+
Files.createDirectories(path)
37+
38+
CsvReporter.forRegistry(this).build(path.toFile()).start(1L, TimeUnit.SECONDS)
39+
40+
object :
41+
DropwizardMeterRegistry(
42+
object : DropwizardConfig {
43+
override fun get(key: String): String? = null
44+
45+
override fun prefix(): String = ""
46+
},
47+
this,
48+
HierarchicalNameMapper.DEFAULT,
49+
Clock.SYSTEM,
50+
) {
51+
override fun nullGaugeValue(): Double = Double.NaN
52+
}
53+
.apply {
54+
ProcessorMetrics().bindTo(this)
55+
JvmMemoryMetrics().bindTo(this)
56+
JvmGcMetrics().bindTo(this)
57+
}
58+
}
59+
}
60+
}
1761

1862
fun main(args: Array<String>) {
1963
val role = System.getenv("ROLE") ?: "big"

big/src/main/kotlin/ac/at/uibk/dps/dapr/big/big/BigActorImpl.kt

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ package ac.at.uibk.dps.dapr.big.big
33
// import io.dropwizard.metrics5.CsvReporter
44
// import io.dropwizard.metrics5.MetricName
55
// import io.dropwizard.metrics5.MetricRegistry
6+
import ac.at.uibk.dps.dapr.big.Big
67
import io.dapr.actors.ActorId
78
import io.dapr.actors.runtime.AbstractActor
89
import io.dapr.actors.runtime.ActorRuntimeContext
910
import io.dapr.client.DaprClientBuilder
11+
import java.util.concurrent.TimeUnit
12+
import kotlin.time.Clock
1013
import kotlin.time.measureTime
14+
import kotlin.time.toJavaDuration
1115

1216
class BigActorImpl(runtimeContext: ActorRuntimeContext<BigActorImpl>, val actorId: ActorId) :
1317
AbstractActor(runtimeContext, actorId), BigActor {
@@ -17,25 +21,12 @@ class BigActorImpl(runtimeContext: ActorRuntimeContext<BigActorImpl>, val actorI
1721
var target: String = ""
1822
var count = 0
1923

20-
/*var metricRegistry: MetricRegistry =
21-
MetricRegistry().apply {
22-
CsvReporter.forRegistry(this)
23-
.build(Paths.get("/metrics").toAbsolutePath().toFile())
24-
.start(1L, TimeUnit.SECONDS)
25-
}
24+
var metricRegistry = Big.provideMetricRegistry()
2625

27-
var counter =
28-
metricRegistry.counter(
29-
MetricName.build("big.pings").tagged(mapOf("id" to actorId.toString()))
30-
)
31-
var eventTimer =
32-
metricRegistry.timer(
33-
MetricName.build("event.latency").tagged(mapOf("id" to actorId.toString()))
34-
)
35-
var pingTimer =
36-
metricRegistry.timer(MetricName.build("ping.duration").tagged("id", actorId.toString()))
37-
var pongTimer =
38-
metricRegistry.timer(MetricName.build("pong.duration").tagged("id", actorId.toString()))*/
26+
var counter = metricRegistry.counter("big.pings")
27+
var eventTimer = metricRegistry.timer("event.latency")
28+
var pingTimer = metricRegistry.timer("ping.duration")
29+
var pongTimer = metricRegistry.timer("pong.duration")
3930

4031
override fun register() {
4132
client.publishEvent("pubsub", "register", actorId.toString()).subscribe()
@@ -49,45 +40,58 @@ class BigActorImpl(runtimeContext: ActorRuntimeContext<BigActorImpl>, val actorI
4940
override fun receivePong(data: Map<String, Any>) {
5041
val delta = measureTime {
5142
val time = data["time"] as Long
52-
// eventTimer.update((System.nanoTime() - time) / 1_000, TimeUnit.MICROSECONDS)
43+
44+
val now = Clock.System.now()
45+
val nowNanos = (now.epochSeconds * 1_000_000_000L) + now.nanosecondsOfSecond
46+
val deltaNanos = (nowNanos - time).coerceAtLeast(0L)
47+
48+
eventTimer.update(deltaNanos, TimeUnit.NANOSECONDS)
5349

5450
val sender = data["sender"] as String
5551

5652
if (sender == target) {
5753
sendPing()
5854
++count
5955

60-
// counter.inc()
56+
counter.inc()
6157
}
6258
}
63-
// pingTimer.update(delta.toJavaDuration())
59+
pingTimer.update(delta.toJavaDuration())
6460
}
6561

6662
override fun sendPong(data: Map<String, Any>) {
6763
val delta = measureTime {
6864
val time = data["time"] as Long
69-
// eventTimer.update((System.nanoTime() - time) / 1_000, TimeUnit.MICROSECONDS)
65+
66+
val now = Clock.System.now()
67+
val nowNanos = (now.epochSeconds * 1_000_000_000L) + now.nanosecondsOfSecond
68+
val deltaNanos = (nowNanos - time).coerceAtLeast(0L)
69+
70+
eventTimer.update(deltaNanos, TimeUnit.NANOSECONDS)
7071

7172
val sender = data["sender"] as String
7273

7374
client
7475
.publishEvent(
7576
"pubsub",
7677
"pong",
77-
mapOf("sender" to actorId.toString(), "receiver" to sender, "time" to System.nanoTime()),
78+
mapOf("sender" to actorId.toString(), "receiver" to sender, "time" to nowNanos),
7879
)
7980
.subscribe()
8081
}
81-
// pongTimer.update(delta.toJavaDuration())
82+
pongTimer.update(delta.toJavaDuration())
8283
}
8384

8485
private fun sendPing() {
8586
target = neighbors.random()
87+
val now = Clock.System.now()
88+
val nowNanos = (now.epochSeconds * 1_000_000_000L) + now.nanosecondsOfSecond
89+
8690
client
8791
.publishEvent(
8892
"pubsub",
8993
"ping",
90-
mapOf("sender" to actorId.toString(), "receiver" to target, "time" to System.nanoTime()),
94+
mapOf("sender" to actorId.toString(), "receiver" to target, "time" to nowNanos),
9195
)
9296
.subscribe()
9397
}

big/src/main/kotlin/ac/at/uibk/dps/dapr/big/sink/SinkActorImpl.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ class SinkActorImpl(runtimeContext: ActorRuntimeContext<SinkActorImpl>, actorId:
1010

1111
val client = DaprClientBuilder().build()
1212
var bigs = mutableListOf<String>()
13-
var startTime = 0L
1413

1514
override fun register(actor: String) {
1615
if (!bigs.contains(actor)) {
@@ -22,7 +21,6 @@ class SinkActorImpl(runtimeContext: ActorRuntimeContext<SinkActorImpl>, actorId:
2221
}
2322

2423
override fun sendNeighbors() {
25-
startTime = System.nanoTime()
2624
client.publishEvent("pubsub", "neighbors", bigs.toList()).subscribe()
2725
bigs.clear()
2826
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: dapr.io/v1alpha1
2+
kind: Component
3+
metadata:
4+
name: pubsub
5+
spec:
6+
type: pubsub.redis
7+
version: v1
8+
metadata:
9+
- name: redisHost
10+
value: 192.168.56.9:6379
11+
- name: redisPassword
12+
value: ""
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: dapr.io/v1alpha1
2+
kind: Component
3+
metadata:
4+
name: statestore
5+
spec:
6+
type: state.redis
7+
version: v1
8+
metadata:
9+
- name: redisHost
10+
value: localhost:6379
11+
- name: redisPassword
12+
value: ""
13+
- name: actorStateStore
14+
value: "true"

0 commit comments

Comments
 (0)