Skip to content
This repository was archived by the owner on Feb 20, 2026. It is now read-only.
Open
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
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,27 @@ For this, `applyForInternalIP.yaml`, will be used in place of `scyllaApply.yaml`

## Installation Instructions
1. Install microk8s if not already installed (: see https://microk8s.io/docs/install-alternatives for instructions)
- If on mac, just run `brew install microk8s`
2. Enable dns with `microk8s enable dns`
3. Install scylla
- If on mac, just run `brew install ubuntu/microk8s/microk8s` but make sure you read
[these notes](https://microk8s.io/docs/install-macos)
2. Run `mickrok8s status` to see which addons are enabled
3. Run `microk8s enable <name>` to ensure these addons are enabled:
`dashboard, dns, metrics-server, observability, registry`
4. Copy the `microk8s/microk8s-config.yaml` file to the standard config location
per [these instructions](https://microk8s.io/docs/add-launch-config). You will need to repeat this every time
the YAML file changes.
5. Install scylla
1. `docker run --name some-scylla -d scylladb/scylla` to download scylla-db image locally as a container
2. `docker save scylladb/scylla > scylla.tar` to save container for uploading
3. `multipass transfer scylla.tar microk8s-vm:/tmp/scylla.tar` to transfer image into multipass directory
4. `microk8s ctr image import /tmp/scylla.tar` to import from multipass image to microk8s
5. `microk8s kubectl apply -f scyllaApplyForInternalIP.yaml`
4. Upload or push directories
6. Upload or push directories
- Option 1: `./importAllFromDockerLocally.sh` or `./importToMicro.sh improving-app-[serviceName]` for individual services
- Option 2: `./tagAllForDocker.sh`
5. Run command `microk8s kubectl apply -f microApplyLocal.yaml` for Option 1 or `microk8s kubectl apply -f microApply.yaml` for Option 2 in previous step
7. Run command `microk8s kubectl apply -f microApplyLocal.yaml` for Option 1 or `microk8s kubectl apply -f microApply.yaml` for Option 2 in previous step
6. Check status with `microk8s kubectl get pods -o wide`
7. `microk8s kubectl apply -f applyForInternalIP.yaml`
6. Run `microk8s kubectl get all --all-namespaces` to view all services in k8s
- expected results should look like below. Use `NAME` column to fill in `[pod-name]` in steps to expose
```
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
Expand Down
36 changes: 21 additions & 15 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,55 +1,61 @@
ThisBuild / dynverSeparator := "-"
Global / onChangedBuildSource := ReloadOnSourceChanges

lazy val allServices = project
lazy val `back-end` = project
.in(file("."))
.aggregate(gateway, tenant, organization, member, store, event, product, gatling)
.aggregate(commonUtils, gateway, tenant, organization, member, store, event, product, gatling)

// This is for protobuf types defined at 'domain' scope and having cross-service applicability only.
lazy val commonTypes = project
.in(file("common-types"))
.configure(C.protobufsLib("improving-app-common-types"))

lazy val commonUtils = project
.in(file("common-utils"))
.configure(C.scalaCompilation("improving-app-common-utils"))
.configure(C.Compilation.scala, C.Testing.scalaTest)
.configure(C.openTelemetry)

lazy val tenant = project
.in(file("tenant"))
.configure(C.akkaPersistentEntity("improving-app-tenant", 8080))
.dependsOn(commonTypes)
.dependsOn(commonTypes, commonUtils)

lazy val organization = project
.in(file("organization"))
.configure(C.akkaPersistentEntity("improving-app-organization", 8082))
.dependsOn(commonTypes)
.dependsOn(commonTypes, commonUtils)

lazy val member = project
.in(file("member"))
.configure(C.akkaPersistentEntity("improving-app-member", 8081))
.dependsOn(commonTypes)
.dependsOn(commonTypes, commonUtils)

lazy val store = project
.in(file("store"))
.configure(C.akkaPersistentEntity("improving-app-store", 8083))
.dependsOn(commonTypes)
.dependsOn(commonTypes, commonUtils)

lazy val event = project
.in(file("event"))
.configure(C.akkaPersistentEntity("improving-app-event", 8084))
.dependsOn(commonTypes)
.dependsOn(commonTypes, commonUtils)

lazy val product = project
.in(file("product"))
.configure(C.akkaPersistentEntity("improving-app-product", 8085))
.dependsOn(commonTypes)
.dependsOn(commonTypes, commonUtils)

lazy val gateway = project
.in(file("gateway"))
.configure(C.Compilation.service("improving-app-gateway", 8090))
.dependsOn(
commonTypes,
tenant % "compile->compile;test->test;it->test",
organization % "compile->compile;test->test;it->test",
member % "compile->compile;test->test;it->test",
store % "compile->compile;test->test;it->test",
event % "compile->compile;test->test;it->test",
product % "compile->compile;test->test;it->test"
tenant % "compile->compile;test->test",
organization % "compile->compile;test->test",
member % "compile->compile;test->test",
store % "compile->compile;test->test",
event % "compile->compile;test->test",
product % "compile->compile;test->test"
)

lazy val gatling = project
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.improving.app.common

import io.opentelemetry.api
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.metrics.{LongCounter, Meter}
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.GlobalOpenTelemetry
import io.opentelemetry.context.Context
import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.metrics.SdkMeterProvider
import io.opentelemetry.sdk.resources.Resource
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.`export`.SimpleSpanProcessor
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME

object OpenTelemetry {
private[common] lazy val sdk: api.OpenTelemetry = GlobalOpenTelemetry.get()
}

case class Tracer(scope: String) {
private val tracer: api.trace.Tracer = OpenTelemetry.sdk.getTracer(scope)
def startSpan(name: String): Span = tracer.spanBuilder(name).startSpan
}

case class Counter(name: String, contextName: String, description: String, uOfM: String) extends LongCounter {
private val meter: Meter = OpenTelemetry.sdk.meterBuilder(contextName).build()
private val counter: LongCounter = meter
.counterBuilder(name)
.setDescription(description)
.setUnit(uOfM)
.build()

def incr(attributes: Attributes = Attributes.empty(), context: Context = Context.current()): Unit =
counter.add(1L, attributes, context)
def decr(attributes: Attributes = Attributes.empty(), context: Context = Context.current()): Unit =
counter.add(-1L, attributes, context)

override def add(value: Long): Unit = counter.add(value)

override def add(value: Long, attributes: Attributes): Unit =
counter.add(value, attributes)

override def add(value: Long, attributes: Attributes, context: Context): Unit =
counter.add(value, attributes, context)
}

case class Histogram(name: String, contextName: String, description: String, unit: String)
extends api.metrics.LongHistogram {
private val meter: api.metrics.Meter = OpenTelemetry.sdk.getMeter(contextName)
private val histogram: api.metrics.LongHistogram =
meter.histogramBuilder(name).ofLongs.setDescription(description).setUnit(unit).build()

override def record(value: Long): Unit = histogram.record(value)

override def record(value: Long, attributes: Attributes): Unit =
histogram.record(value, attributes)

override def record(value: Long, attributes: Attributes, context: Context): Unit =
histogram.record(value, attributes, context)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.improving.app.common

import org.scalatest.matchers.must.Matchers
import org.scalatest.wordspec.AnyWordSpec

class OpenTelemetryTest extends AnyWordSpec with Matchers {

"OpenTelemetry" must {
"capture counters" in {
System.setProperty("otel.java.global-autoconfigure.enabled", "true")
System.setProperty("otel.metrics.exporter", "logging")
val cntr = Counter("testCounter", "OpenTelemetryTest", "just a simple counter", "each")
cntr.add(1L)
cntr.add(10L)
cntr.add(100L)
}
"capture histograms" in {
val cntr = Histogram("testHistogram", "OpenTelemetryTest", "just a simple histogram", "widgets/sec")
cntr.record(1L)
cntr.record(10L)
cntr.record(100L)
}
"trace execution" in {
System.setProperty("otel.java.global-autoconfigure.enabled", "true")
System.setProperty("otel.metrics.exporter", "logging")
val tracer = Tracer("testTracer")
val span = tracer.startSpan("top")
for (i <- 1 to 10) {
span.addEvent(i.toString)
}
span.end()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "com/improving/app/common/domain/ids.proto";
import "google/protobuf/timestamp.proto";
import "scalapb/scalapb.proto";
import "scalapb/validate.proto";
import "validate/validate.proto";
// import "validate/validate.proto";

option (scalapb.options) = {
scope: FILE
Expand Down Expand Up @@ -87,4 +87,4 @@ message EventMetaInfo {
google.protobuf.Timestamp actual_end = 8;
EventState current_state = 9;
optional EventStateInfo event_state_info = 10;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "com/improving/app/event/domain/eventDomainObjects.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "scalapb/scalapb.proto";
import "validate/validate.proto";
// import "validate/validate.proto";
import "scalapb/validate.proto";

option (scalapb.options) = {
Expand All @@ -31,7 +31,7 @@ message EventRequestPB{
option (scalapb.message).sealed_oneof_extends = "com.improving.app.common.serialize.PBMsgOneOfSerializable";

oneof sealed_value {
EditEventInfo edit_event_info = 1;
EditEventInfo edit_event_info = 1;
CreateEvent create_event = 2;
ScheduleEvent schedule_event = 3;
CancelEvent cancel_event = 4;
Expand All @@ -46,17 +46,17 @@ message EditEventInfo {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
EditableEventInfo info = 2;
common.domain.EventId event_id = 1;
EditableEventInfo info = 2;
common.domain.MemberId on_behalf_of = 3;
}

message CreateEvent {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
EditableEventInfo info = 2;
common.domain.EventId event_id = 1;
EditableEventInfo info = 2;
common.domain.MemberId on_behalf_of = 4;
}

Expand All @@ -73,7 +73,7 @@ message CancelEvent {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
common.domain.EventId event_id = 1;
string reason = 2;
common.domain.MemberId on_behalf_of = 3;
}
Expand All @@ -82,7 +82,7 @@ message RescheduleEvent {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
common.domain.EventId event_id = 1;
google.protobuf.Timestamp start = 2;
google.protobuf.Timestamp end = 3;
common.domain.MemberId on_behalf_of = 4;
Expand All @@ -92,7 +92,7 @@ message DelayEvent {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
common.domain.EventId event_id = 1;
string reason = 2;
google.protobuf.Duration expected_duration = 3;
common.domain.MemberId on_behalf_of = 4;
Expand All @@ -102,14 +102,14 @@ message StartEvent {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
common.domain.EventId event_id = 1;
common.domain.MemberId on_behalf_of = 2;
}

message EndEvent {
option (scalapb.message) = {
extends: [ "EventCommand" ]
};
common.domain.EventId event_id = 1;
common.domain.EventId event_id = 1;
common.domain.MemberId on_behalf_of = 2;
}
}
Loading