Skip to content
This repository has been archived by the owner on Mar 27, 2023. It is now read-only.

Commit

Permalink
Refactor stats to be able to drop old data
Browse files Browse the repository at this point in the history
  • Loading branch information
Michel Zimmer committed Jul 21, 2022
1 parent 811be95 commit 4506161
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 54 deletions.
3 changes: 1 addition & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
!project/build.properties
!project/plugins.sbt
!src/
!build.sbt
!Dockerfile
!build.sbt
2 changes: 1 addition & 1 deletion .sdkmanrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
java=17.0.3-tem
sbt=1.6.2
sbt=1.7.1
24 changes: 5 additions & 19 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
FROM eclipse-temurin:17.0.3_7-jre-alpine as build
RUN set -euxo pipefail; \
apk update; \
apk add --no-cache \
bash \
ca-certificates \
;
ADD https://github.com/sbt/sbt/releases/download/v1.6.2/sbt-1.6.2.tgz /tmp/sbt-1.6.2.tgz
RUN set -euxo pipefail; \
tar --extract --gzip --file /tmp/sbt-1.6.2.tgz --directory /opt; \
rm -rf /tmp/sbt-1.6.2.tgz; \
chown -hR root:root /opt/sbt
WORKDIR /opt/sbt
RUN set -euxo pipefail; \
/opt/sbt/bin/sbt sbtVersion
COPY --chown=root:root . /tmp/bandwhichd-server/
FROM sbtscala/scala-sbt:eclipse-temurin-17.0.3_1.7.1_3.1.3 as build
WORKDIR /tmp/bandwhichd-server
RUN /opt/sbt/bin/sbt assembly
COPY --chown=sbtuser:sbtuser . ./
RUN sbt assembly

FROM eclipse-temurin:17.0.3_7-jre-alpine
LABEL org.opencontainers.image.authors="neuland Open Source Maintainers <opensource@neuland-bfi.de>"
Expand All @@ -26,11 +12,11 @@ LABEL org.opencontainers.image.vendor="neuland – Büro für Informatik GmbH"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.title="bandwhichd-server"
LABEL org.opencontainers.image.description="bandwhichd server collecting measurements and calculating statistics"
LABEL org.opencontainers.image.version="0.6.0-rc2"
LABEL org.opencontainers.image.version="0.6.0-rc3"
USER guest
ENTRYPOINT ["/opt/java/openjdk/bin/java"]
CMD ["-jar", "/opt/bandwhichd-server.jar"]
EXPOSE 8080
HEALTHCHECK --interval=5s --timeout=1s --start-period=2s --retries=2 \
CMD wget --spider http://localhost:8080/v1/health || exit 1
COPY --from=build --chown=root:root /tmp/bandwhichd-server/target/scala-3.1.2/bandwhichd-server-assembly-0.6.0-rc2.jar /opt/bandwhichd-server.jar
COPY --from=build --chown=root:root /tmp/bandwhichd-server/target/scala-3.1.3/bandwhichd-server-assembly-0.6.0-rc3.jar /opt/bandwhichd-server.jar
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ lazy val root = (project in file("."))
.settings(
organization := "de.neuland-bfi",
name := "bandwhichd-server",
version := "0.6.0-rc2",
scalaVersion := "3.1.2",
version := "0.6.0-rc3",
scalaVersion := "3.1.3",
Compile / scalaSource := baseDirectory.value / "src" / "main" / "scala",
Test / scalaSource := baseDirectory.value / "src" / "test" / "scala",
Test / fork := true,
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.6.2
sbt.version=1.7.1
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ case class UnidentifiedHost(
}

object UnidentifiedHost {
type HostId = HostId.HostHostId
type HostId = HostId.Host
}

sealed trait IdentifiedHost[+I <: HostId] extends AnyHost[I]

sealed trait MachineIdHost extends IdentifiedHost[HostId.MachineIdHostId] {
sealed trait MachineIdHost extends IdentifiedHost[HostId.MachineId] {
def hostId: MachineIdHost.HostId
}

object MachineIdHost {
type HostId = HostId.MachineIdHostId
type HostId = HostId.MachineId
}

case class MonitoredHost(
hostId: HostId.MachineIdHostId,
hostId: HostId.MachineId,
agentIds: Set[AgentId],
hostname: Hostname,
additionalHostnames: Set[Hostname],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package de.neuland.bandwhichd.server.domain.stats

import com.comcast.ip4s.{Host, Hostname, IDN}
import de.neuland.bandwhichd.server.domain.MachineId
import com.comcast.ip4s.{Host => Ip4sHost, Hostname, IDN}
import de.neuland.bandwhichd.server.domain.{MachineId => BandwhichdMachineId}

import java.nio.charset.StandardCharsets
import java.nio.charset.StandardCharsets.UTF_8
Expand All @@ -13,19 +13,19 @@ sealed trait HostId {
}

object HostId {
case class MachineIdHostId(machineId: MachineId) extends HostId {
case class MachineId(machineId: BandwhichdMachineId) extends HostId {
override def uuid: UUID =
machineId.value
}

case class HostHostId(host: Host) extends HostId {
case class Host(host: Ip4sHost) extends HostId {
override def uuid: UUID =
UUID.nameUUIDFromBytes(host.toString.getBytes(UTF_8))
}

def apply(machineId: MachineId): MachineIdHostId =
MachineIdHostId(machineId)
def apply(machineId: BandwhichdMachineId): MachineId =
MachineId(machineId)

def apply(host: Host): HostHostId =
HostHostId(host)
def apply(host: Ip4sHost): Host =
Host(host)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,31 @@ class Stats[L <: HostId, H <: AnyHost[L], R <: HostId] private (

def connections: Set[(L, R)] =
bundles.values.flatMap { bundle =>
bundle.remoteHostIds.map { remoteHostId =>
bundle.connections.keys.map { remoteHostId =>
bundle.host.hostId -> remoteHostId
}
}.toSet

def dropBefore(timestamp: Timing.Timestamp): Stats[L, H, R] =
new Stats(
bundles
.filterNot { case (_, bundle) =>
bundle.lastSeenAt.instant.isBefore(timestamp.instant)
}
.view
.mapValues(bundle =>
bundle.copy(
connections = bundle.connections.filterNot { case (_, connection) =>
connection.lastSeenAt.instant.isBefore(timestamp.instant)
}
)
)
.toMap
)
}

type AnyStats = Stats[HostId, AnyHost[HostId], HostId]
type MonitoredStats = Stats[HostId.MachineIdHostId, MonitoredHost, HostId]
type MonitoredStats = Stats[HostId.MachineId, MonitoredHost, HostId]

object Stats {
val defaultTimeframeDuration: Duration = Duration.ofHours(2)
Expand Down Expand Up @@ -69,10 +86,10 @@ object Stats {
interfaces,
_
) =>
val hostId: HostId.MachineIdHostId = HostId(machineId)
val hostId: HostId.MachineId = HostId(machineId)

val maybeBundle
: Option[Bundle[HostId.MachineIdHostId, MonitoredHost, HostId]] =
: Option[Bundle[HostId.MachineId, MonitoredHost, HostId]] =
stats.bundles
.get(hostId)
.orElse {
Expand All @@ -93,7 +110,7 @@ object Stats {
interfaces = interfaces.toSet
),
lastSeenAt = timing,
remoteHostIds = Set.empty
connections = Map.empty
)
} { bundle =>
bundle.copy(
Expand Down Expand Up @@ -121,7 +138,7 @@ object Stats {
new Stats(
stats.bundles + (bundle.host.hostId -> bundle.copy(
lastSeenAt = timing.end,
remoteHostIds = bundle.remoteHostIds ++ connections.map {
connections = bundle.connections ++ connections.map {
connection =>

val remoteHost: Host = connection.remoteSocket.value.host
Expand All @@ -148,7 +165,9 @@ object Stats {
_.host.hostId
)

remoteHostId
remoteHostId -> Bundle.Connection(
lastSeenAt = timing.end
)
}
))
)
Expand All @@ -163,10 +182,10 @@ object Stats {
new Stats(
stats.bundles.view.mapValues { bundle =>
bundle.copy(
remoteHostIds = bundle.remoteHostIds.filter {
_ match
case _: HostId.MachineIdHostId => true
case HostId.HostHostId(ipAddress: IpAddress) =>
connections = bundle.connections.filter {
_._1 match
case _: HostId.MachineId => true
case HostId.Host(ipAddress: IpAddress) =>
stats.monitoredNetworks.exists(_.contains(ipAddress))
case _ => false
}
Expand All @@ -176,20 +195,26 @@ object Stats {

def unidentifiedRemoteHosts: Set[UnidentifiedHost] =
stats.bundles.values.flatMap { bundle =>
bundle.remoteHostIds.flatMap {
_ match
case HostId.HostHostId(host) => Some(UnidentifiedHost(host))
case HostId.MachineIdHostId(_) => None
bundle.connections.flatMap {
_._1 match
case HostId.Host(host) => Some(UnidentifiedHost(host))
case HostId.MachineId(_) => None
}
}.toSet

def allHosts: Set[AnyHost[HostId]] =
stats.hosts ++ stats.unidentifiedRemoteHosts
}

private case class Bundle[L <: HostId, H <: AnyHost[L], R <: HostId](
private[Stats] case class Bundle[L <: HostId, H <: AnyHost[L], R <: HostId](
host: H,
lastSeenAt: Timing.Timestamp,
remoteHostIds: Set[R]
connections: Map[R, Bundle.Connection]
)

private[Stats] object Bundle {
private[Stats] case class Connection(
lastSeenAt: Timing.Timestamp
)
}
}
Loading

0 comments on commit 4506161

Please sign in to comment.