diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5b1270409d45a971d16767f8466607d52e9311c5..1ed4fb19502796feb4a19048806e259efc86dad6 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.7.2 +current_version = 2.7.10 commit = True tag = True tag_name = {new_version} diff --git a/Dockerfile b/Dockerfile index 1ddc78d9a19badff6f0c0081dc2794f87b04b77f..b79069b160c39e7a671f160fdf3553c05ebd8258 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,16 +19,22 @@ ARG BUILD_DATE ARG VCS_REF ARG VERSION +ENV CONTEXT_PATH "/services" + +RUN apk add --update --no-cache curl + COPY docker/config/application.tmpl /config/application.tmpl COPY docker/README.md docker/run.sh / COPY --from=java-build-env /project/target/portal-backend.jar /usr/share/jars/ -# 8080: Web service API, health checks on http://host:8087/health +ENTRYPOINT ["/run.sh"] + +# 8080: Web service API, health checks on http://host:8080/$CONTEXT_PATH/health # 4089: Akka cluster EXPOSE 4089 8080 -ENTRYPOINT ["/run.sh"] +HEALTHCHECK --start-period=60s CMD curl -v --silent http://localhost:8080/$CONTEXT_PATH/health 2>&1 | grep UP LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.name="hbpmip/portal-backend" \ diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl index 911af6200bda7587d08d1543ad269d969fba3c81..9a56dad4cd7bcdc5d78db3b07473f28521149358 100644 --- a/docker/config/application.tmpl +++ b/docker/config/application.tmpl @@ -78,15 +78,9 @@ endpoints: enabled: true health: enabled: true - endoint: /health - sentitive: false + endpoint: /health + sensitive: false services: exareme: miningExaremeUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/query - -akka: - woken: - host: {{ default .Env.WOKEN_PORT_8088_TCP_ADDR "woken" }} - port: {{ default .Env.WOKEN_PORT_8088_TCP_PORT "8088" }} - path: {{ default .Env.WOKEN_AKKA_PATH "/user/entrypoint" }} diff --git a/hbp.yml b/hbp.yml index 9cf5b11bf8e83fd71aeefd6de25a08c7b93c7905..a7c40057acc24c34509d2baa0ee4facc1c9f42bf 100644 --- a/hbp.yml +++ b/hbp.yml @@ -58,9 +58,9 @@ testing: command: ./test.sh release_management: - current_version: 2.7.2 - current_code_release: https://github.com/HBPMedical/portal-backend/archive/2.7.2.zip - current_binary_release: https://pypi.python.org/pypi/portal-backend/2.7.2 + current_version: 2.7.10 + current_code_release: https://github.com/HBPMedical/portal-backend/archive/2.7.10.zip + current_binary_release: https://pypi.python.org/pypi/portal-backend/2.7.10 release_script: 'publish.sh' continuous_integration: @@ -75,10 +75,10 @@ continuous_integration: distribution: docker_hub: name: hbpmip/portal-backend - current_tag: 2.7.2 + current_tag: 2.7.10 url: https://hub.docker.com/r/hbpmip/portal-backend/ badge: https://img.shields.io/badge/docker-hbpmip%2Fportal--backend-008bb8.svg - command: docker pull hbpmip/portal-backend:2.7.2 + command: docker pull hbpmip/portal-backend:2.7.10 planning: github: diff --git a/pom.xml b/pom.xml index 51625bdc02a5e7e6ba56db4806281701d3876aac..517a89dcc9f0b65d0a17ba40bb9f364ec648b62d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ <groupId>eu.hbp.mip</groupId> <artifactId>portal-backend</artifactId> - <version>2.7.2</version><!-- BUMP_VERSION --> + <version>2.7.10</version><!-- BUMP_VERSION --> <packaging>jar</packaging> <name>portal-backend</name> @@ -47,7 +47,7 @@ <spring-data-jpa.version>1.10.11.RELEASE</spring-data-jpa.version> <spring-boot-starter-actuator.version>1.4.7.RELEASE</spring-boot-starter-actuator.version> <aspectjweaver.version>1.8.9</aspectjweaver.version> - <woken-messages.version>2.7.2</woken-messages.version> + <woken-messages.version>2.7.3</woken-messages.version> <javax-inject.version>1</javax-inject.version> <akka.version>2.5.12</akka.version> <spring-context.version>4.3.4.RELEASE</spring-context.version> diff --git a/src/main/java/eu/hbp/mip/StartupTasks.java b/src/main/java/eu/hbp/mip/StartupTasks.java index a72e119529fb6fcd497b8ad90fc0b60d4dd7c14a..b09bc06a5c10842aff6ce5e1aee260c6295b1b58 100644 --- a/src/main/java/eu/hbp/mip/StartupTasks.java +++ b/src/main/java/eu/hbp/mip/StartupTasks.java @@ -1,12 +1,12 @@ package eu.hbp.mip; +import akka.actor.ActorRef; +import akka.cluster.Cluster; import ch.chuv.lren.woken.messages.datasets.Dataset; import com.google.gson.Gson; import eu.hbp.mip.controllers.DatasetsApi; import eu.hbp.mip.controllers.MiningApi; import eu.hbp.mip.controllers.VariablesApi; -import eu.hbp.mip.model.Algorithm; -import eu.hbp.mip.model.MiningQuery; import eu.hbp.mip.model.Variable; import eu.hbp.mip.repositories.VariableRepository; import org.slf4j.Logger; @@ -14,11 +14,12 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; -import java.util.Collections; @Component +@DependsOn("wokenCluster") public class StartupTasks implements ApplicationListener<ApplicationReadyEvent> { private static final Logger LOGGER = LoggerFactory.getLogger(StartupTasks.class); @@ -38,19 +39,25 @@ public class StartupTasks implements ApplicationListener<ApplicationReadyEvent> @Override public void onApplicationEvent(ApplicationReadyEvent event) { + // Pre-fill the local variable repository with the list of datasets, interpreted here as variables // (a bit like a categorical variable can be split into a set of variables (a.k.a one hot encoding in Data science) ) - try { - for (Dataset dataset: datasetsApi.fetchDatasets()) { - final String code = dataset.dataset().code(); - Variable v = variableRepository.findOne(code); - if (v == null) { - v = new Variable(code); - variableRepository.save(v); + // Try 5 times, to be more robust in the face of cluster failures / slow startup + for (int i = 0; i < 5; i++) { + try { + for (Dataset dataset : datasetsApi.fetchDatasets()) { + final String code = dataset.dataset().code(); + Variable v = variableRepository.findOne(code); + if (v == null) { + v = new Variable(code); + variableRepository.save(v); + } } + LOGGER.info("Datasets fetched from Woken"); + break; + } catch (Exception e) { + LOGGER.error("Cannot initialise the variable repository. Is the connection to Woken working?", e); } - } catch (Exception e) { - LOGGER.error("Cannot initialise the variable repository. Is the connection to Woken working?", e); } /* @@ -67,4 +74,5 @@ public class StartupTasks implements ApplicationListener<ApplicationReadyEvent> LOGGER.info("MIP Portal backend is ready!"); } + } diff --git a/src/main/java/eu/hbp/mip/akka/AkkaClusterHealthCheck.java b/src/main/java/eu/hbp/mip/akka/AkkaClusterHealthCheck.java new file mode 100644 index 0000000000000000000000000000000000000000..932599223fbf1c160485174faaf76da04db6b864 --- /dev/null +++ b/src/main/java/eu/hbp/mip/akka/AkkaClusterHealthCheck.java @@ -0,0 +1,26 @@ +package eu.hbp.mip.akka; + +import akka.cluster.Cluster; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.stereotype.Component; + + +@Component +public class AkkaClusterHealthCheck implements HealthIndicator { + + @Autowired + private Cluster wokenCluster; + + @Override + public Health health() { + if (wokenCluster.state().getLeader() == null) { + return Health.down().withDetail("Error", "No leader in the cluster").build(); + } else if (!wokenCluster.state().allRoles().contains("woken")) { + return Health.down().withDetail("Error", "Woken server cannot be seen in the cluster").build(); + } + return Health.up().build(); + } + +} \ No newline at end of file diff --git a/src/main/java/eu/hbp/mip/akka/WokenClientController.java b/src/main/java/eu/hbp/mip/akka/WokenClientController.java index 5931c13eb1aa64afdb0b573fb9844b06ad84ead5..5e34b75b38ba7fd8a2a8e14d4b8764acabbbc5ad 100644 --- a/src/main/java/eu/hbp/mip/akka/WokenClientController.java +++ b/src/main/java/eu/hbp/mip/akka/WokenClientController.java @@ -2,7 +2,6 @@ package eu.hbp.mip.akka; import akka.actor.ActorRef; import akka.actor.ActorSystem; -import akka.cluster.pubsub.DistributedPubSub; import akka.cluster.pubsub.DistributedPubSubMediator; import akka.pattern.Patterns; import akka.util.Timeout; @@ -19,7 +18,6 @@ import scala.concurrent.ExecutionContext; import scala.concurrent.Future; import scala.concurrent.duration.Duration; -import javax.annotation.PostConstruct; import java.util.function.Function; /** @@ -32,21 +30,12 @@ public abstract class WokenClientController { @Autowired private ActorSystem actorSystem; - @Autowired - private String wokenReceptionistPath; - @Value("#{'${akka.woken.path:/user/entrypoint}'}") private String wokenPath; + @Autowired private ActorRef wokenMediator; - @SuppressWarnings("unused") - @PostConstruct - public void initClusterClient() { - LOGGER.info("Start Woken client " + wokenReceptionistPath); - wokenMediator = DistributedPubSub.get(actorSystem).mediator(); - } - @SuppressWarnings("unchecked") protected <A, B> B askWoken(A message, int waitInSeconds) throws Exception { LOGGER.info("Akka is trying to reach remote " + wokenPath); diff --git a/src/main/java/eu/hbp/mip/configuration/AkkaConfiguration.java b/src/main/java/eu/hbp/mip/configuration/AkkaConfiguration.java index cfcfefe7dbb2bc637e4090a42c037ee1e3563b63..d2f285d4582537c714837d16c17f934f08bc6831 100644 --- a/src/main/java/eu/hbp/mip/configuration/AkkaConfiguration.java +++ b/src/main/java/eu/hbp/mip/configuration/AkkaConfiguration.java @@ -1,14 +1,20 @@ package eu.hbp.mip.configuration; +import akka.actor.ActorRef; import akka.actor.ActorSystem; +import akka.actor.ExtendedActorSystem; +import akka.cluster.Cluster; +import akka.cluster.pubsub.DistributedPubSub; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.*; + +import java.util.List; +import java.util.concurrent.Semaphore; import static eu.hbp.mip.akka.SpringExtension.SPRING_EXTENSION_PROVIDER; @@ -20,30 +26,90 @@ import static eu.hbp.mip.akka.SpringExtension.SPRING_EXTENSION_PROVIDER; @ComponentScan class AkkaConfiguration { + protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + @Autowired private ApplicationContext applicationContext; - @Value("#{'${akka.woken.host:woken}'}") - private String wokenHost; - - @Value("#{'${akka.woken.port:8088}'}") - private String wokenPort; + private final Config config; - @Value("#{'${akka.woken.path:/user/entrypoint}'}") - private String wokenPath; + { + Config remotingConfig = ConfigFactory.parseResourcesAnySyntax("akka-remoting.conf").resolve(); + String remotingImpl = remotingConfig.getString("remoting.implementation"); + config = ConfigFactory + .parseString("akka {\n" + + " actor.provider = cluster\n" + + " extensions += \"akka.cluster.pubsub.DistributedPubSub\"\n" + + "}") + .withFallback(ConfigFactory.parseResourcesAnySyntax("akka.conf")) + .withFallback(ConfigFactory.parseResourcesAnySyntax("akka-" + remotingImpl + "-remoting.conf")) + .withFallback(ConfigFactory.parseResourcesAnySyntax("kamon.conf")) + .withFallback(ConfigFactory.load()) + .resolve(); + } @Bean - public ActorSystem actorSystem() { - Config config = ConfigFactory.load("application.conf"); - ActorSystem system = ActorSystem.create("woken", config); + public ExtendedActorSystem actorSystem() { + LOGGER.info("Step 1/3: Starting actor system..."); + LOGGER.info("Create actor system at " + wokenClusterHost() + ":" + wokenClusterPort()); + ExtendedActorSystem system = (ExtendedActorSystem) ActorSystem.create("woken", config); SPRING_EXTENSION_PROVIDER.get(system).initialize(applicationContext); return system; } @Bean - public String wokenReceptionistPath() { - return "akka.tcp://woken@" + wokenHost + ":" + wokenPort + "/system/receptionist"; + public Cluster wokenCluster() { + Cluster cluster = Cluster.get(actorSystem()); + LOGGER.info("Connect to Woken cluster nodes at " + String.join(",", wokenPath())); + Semaphore semaphore = new Semaphore(1); + cluster.registerOnMemberUp( () -> { + LOGGER.info("Step 2/3: Cluster up, registering the actors..."); + + // Do not call wokenMediator() here to avoid recursive loops + ActorRef mediator = DistributedPubSub.get(actorSystem()).mediator(); + + LOGGER.info("Woken Mediator available at " + mediator.path().toStringWithoutAddress()); + + semaphore.release(); + }); + + try { + semaphore.acquire(); + Thread.sleep(5000); + } catch (InterruptedException e) { + LOGGER.warn("Cannot wait for Akka cluster start", e); + } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + cluster.leave(cluster.selfAddress()); + }) + ); + + LOGGER.info("Step 3/3: Cluster connected to Woken."); + + return cluster; + } + + @Bean + public String wokenClusterHost() { + return config.getString("clustering.ip"); + } + + @Bean + public Integer wokenClusterPort() { + return config.getInt("clustering.port"); } + @Bean + public List<String> wokenPath() { + return config.getStringList("akka.cluster.seed-nodes"); + } + + @Bean + @Lazy + @DependsOn("wokenCluster") + public ActorRef wokenMediator() { + return DistributedPubSub.get(actorSystem()).mediator(); + } } diff --git a/src/main/java/eu/hbp/mip/configuration/WebConfiguration.java b/src/main/java/eu/hbp/mip/configuration/WebConfiguration.java index fb41a0da12783723de821f00eb04e24f05679b0b..eb84126ff753b3b458995030ee8faf429ae5e5e9 100644 --- a/src/main/java/eu/hbp/mip/configuration/WebConfiguration.java +++ b/src/main/java/eu/hbp/mip/configuration/WebConfiguration.java @@ -2,6 +2,7 @@ package eu.hbp.mip.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; import org.springframework.data.web.config.EnableSpringDataWebSupport; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; @@ -19,6 +20,7 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 @EnableSpringDataWebSupport +@DependsOn("wokenCluster") public class WebConfiguration { @Bean diff --git a/src/main/java/eu/hbp/mip/controllers/VariablesApi.java b/src/main/java/eu/hbp/mip/controllers/VariablesApi.java index 1c284f1bbb406e3907ee28888d88aa250757ad5d..3b5b07feeb0351a489e10d39f882aa3ef3be0bb9 100644 --- a/src/main/java/eu/hbp/mip/controllers/VariablesApi.java +++ b/src/main/java/eu/hbp/mip/controllers/VariablesApi.java @@ -5,10 +5,15 @@ package eu.hbp.mip.controllers; +import ch.chuv.lren.mip.portal.WokenConversions; +import ch.chuv.lren.woken.messages.variables.VariableMetaData; +import ch.chuv.lren.woken.messages.variables.VariablesForDatasetsQuery; +import ch.chuv.lren.woken.messages.variables.VariablesForDatasetsResponse; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import eu.hbp.mip.akka.WokenClientController; import eu.hbp.mip.model.Algorithm; import eu.hbp.mip.model.MiningQuery; import eu.hbp.mip.model.Variable; @@ -20,11 +25,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.web.bind.annotation.*; +import scala.collection.JavaConversions; +import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -35,7 +43,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @RestController @RequestMapping(value = "/variables", produces = {APPLICATION_JSON_VALUE}) @Api(value = "/variables", description = "the variables API") -public class VariablesApi { +public class VariablesApi extends WokenClientController { private static final Logger LOGGER = LoggerFactory.getLogger(VariablesApi.class); @@ -71,6 +79,38 @@ public class VariablesApi { return ResponseEntity.ok(variablesObjects); } + @ApiOperation(value = "Get variables available for a dataset", response = List.class, responseContainer = "List") + @Cacheable(value = "availableVariables", + key = "#datasets", + unless = "#result.getStatusCode().value()!=200") + @RequestMapping(value = "/availableVariables", method = RequestMethod.GET) + public ResponseEntity getAvailableVariables( + @ApiParam(value = "List of datasets : ds1,ds2,...") @RequestParam(value = "datasets") String datasets) { + + LOGGER.info("Get available variables for datasets " + datasets); + + List<Variable> dsAsVariables = Arrays.stream(datasets.split(",")).map(Variable::new).collect(Collectors.toList()); + WokenConversions conv = new WokenConversions(); + + VariablesForDatasetsQuery query = new VariablesForDatasetsQuery(conv.toDatasets(dsAsVariables), true); + + return requestWoken(query, 30, r -> { + VariablesForDatasetsResponse response = (VariablesForDatasetsResponse) r; + + if (response.error().isDefined()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response.error().get()); + } else { + List<Variable> variables = new ArrayList<>(); + for (VariableMetaData var: JavaConversions.setAsJavaSet(response.variables())) { + variables.add(new Variable(var.code())); + } + return ResponseEntity.ok(variables); + } + }); + + } + + @ApiOperation(value = "Get a variable", response = Object.class) @Cacheable("variable") @RequestMapping(value = "/{code}", method = RequestMethod.GET) diff --git a/src/main/resources/akka-artery-remoting.conf b/src/main/resources/akka-artery-remoting.conf new file mode 100644 index 0000000000000000000000000000000000000000..c89f41b643d8b6cff4ba5480b03bddcd57848348 --- /dev/null +++ b/src/main/resources/akka-artery-remoting.conf @@ -0,0 +1,25 @@ +akka { + + remote { + + netty.tcp { + enabled = off + } + + artery { + enabled = on + transport = tcp + + canonical.hostname = ${clustering.ip} # external (logical) hostname + canonical.port = ${clustering.port} # external (logical) port + + bind.hostname = 0.0.0.0 # internal (bind) hostname + bind.port = ${clustering.port} # internal (bind) port + + } + } +} + +remoting { + protocol = "akka" +} diff --git a/src/main/resources/akka-netty-remoting.conf b/src/main/resources/akka-netty-remoting.conf new file mode 100644 index 0000000000000000000000000000000000000000..2c830d0dc17969d54f8a331196fdb53ba15f18d0 --- /dev/null +++ b/src/main/resources/akka-netty-remoting.conf @@ -0,0 +1,28 @@ +akka { + + remote { + maximum-payload-bytes = 30000000 bytes + + netty.tcp { + hostname = ${clustering.ip} # external (logical) hostname + port = ${clustering.port} # external (logical) port + + bind-hostname = 0.0.0.0 # internal (bind) hostname + bind-port = ${clustering.port} # internal (bind) port + + message-frame-size = 30000000b + send-buffer-size = 30000000b + receive-buffer-size = 30000000b + maximum-frame-size = 30000000b + } + + artery { + enabled = off + + } + } +} + +remoting { + protocol = "akka.tcp" +} diff --git a/src/main/resources/akka-remoting.conf b/src/main/resources/akka-remoting.conf new file mode 100644 index 0000000000000000000000000000000000000000..18f2189d453d0c76cbb94505af6cd735fe7c3ff4 --- /dev/null +++ b/src/main/resources/akka-remoting.conf @@ -0,0 +1,7 @@ +remoting { + + implementation = "netty" + # Alternative option is 'artery' + implementation = ${?AKKA_REMOTING} + +} diff --git a/src/main/resources/akka.conf b/src/main/resources/akka.conf new file mode 100644 index 0000000000000000000000000000000000000000..b169e7b9c2cc700b878cbce1518ecb18d8a56ebc --- /dev/null +++ b/src/main/resources/akka.conf @@ -0,0 +1,57 @@ +# Merged with defaults in woken-messages/reference.conf +akka { + loglevel = "WARNING" + loglevel = ${?LOG_LEVEL} + stdout-loglevel = "WARNING" + stdout-loglevel = ${?LOG_LEVEL} + loggers = ["akka.event.slf4j.Slf4jLogger"] + logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + + log-config-on-start = off + log-config-on-start = ${?LOG_CONFIG} + + log-dead-letters = 10 + log-dead-letters-during-shutdown = off + + actor { + # provider = "cluster" + + allow-java-serialization = off + enable-additional-serialization-bindings = true + + } + + remote { + log-sent-messages = off + log-received-messages = off + log-remote-lifecycle-events = off + + watch-failure-detector { + acceptable-heartbeat-pause = 20 s + } + + } + + cluster { + seed-nodes = [ + ${remoting.protocol}"://"${clustering.cluster.name}"@"${clustering.seed-ip}":"${clustering.seed-port} + ] + + roles = ["portal"] + + } + + http { + server { + idle-timeout = 300s + request-timeout = 180s + ssl-encryption = off + ssl-tracing = on + } + + client { + idle-timeout = 300s + request-timeout = 20 s + } + } +} diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 5f553c58dd73df1307ce5d9c6d28c5a48cb05928..333813a1dedc7f79090e077f1d826763ea6521f8 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -1,73 +1,3 @@ -akka { - loglevel = "WARNING" - loglevel = ${?LOG_LEVEL} - stdout-loglevel = "WARNING" - stdout-loglevel = ${?LOG_LEVEL} - loggers = ["akka.event.slf4j.Slf4jLogger"] - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" +# No specific configuration for Portal backend +# All configuration is related to Akka - log-config-on-start = off - log-config-on-start = ${?LOG_CONFIG} - - log-dead-letters = 10 - log-dead-letters-during-shutdown = off - - actor { - provider = "cluster" - - allow-java-serialization = off - enable-additional-serialization-bindings = true - - } - - remote { - log-sent-messages = on - log-received-messages = on - log-remote-lifecycle-events = on - - maximum-payload-bytes = 10000000 bytes - - watch-failure-detector { - acceptable-heartbeat-pause = 20 s - } - - artery { - enabled = on - transport = tcp - - canonical.hostname = ${clustering.ip} # external (logical) hostname - canonical.port = ${clustering.port} # external (logical) port - - bind.hostname = 0.0.0.0 # internal (bind) hostname - bind.port = ${clustering.port} # internal (bind) port - - } - - } - - cluster { - seed-nodes = [ - "akka://"${clustering.cluster.name}"@"${clustering.seed-ip}":"${clustering.seed-port} - ] - - roles = ["portal"] - - } - - extensions += "akka.cluster.pubsub.DistributedPubSub" - -} - -clustering { - ip = "127.0.0.1" - ip = ${?CLUSTER_IP} - port = 4089 - port = ${?CLUSTER_PORT} - seed-ip = "woken" - seed-ip = ${?CLUSTER_IP} - seed-ip = ${?WOKEN_PORT_8088_TCP_ADDR} - seed-port = 8088 - seed-port = ${?WOKEN_PORT_8088_TCP_PORT} - cluster.name = "woken" - cluster.name = ${?CLUSTER_NAME} -} diff --git a/src/main/resources/kamon.conf b/src/main/resources/kamon.conf new file mode 100644 index 0000000000000000000000000000000000000000..00b068b2199b6105255f66e86b23d67ece3e75c8 --- /dev/null +++ b/src/main/resources/kamon.conf @@ -0,0 +1,65 @@ +kamon { + enabled = no + enabled = ${?KAMON_ENABLED} + + environment { + service = "woken" + } + + zipkin = { + enabled = no + enabled = ${?ZIPKIN_ENABLED} + host = "zipkin" + host = ${?ZIPKIN_IP} + port = 9411 + port = ${?ZIPKIN_PORT} + } + + prometheus = { + enabled = no + enabled = ${?PROMETHEUS_ENABLED} + host = "prometheus" + host = ${?PROMETHEUS_IP} + port = 9090 + port = ${?PROMETHEUS_PORT} + } + + util.filters { + "akka.tracked-actor" { + includes = ["**"] + } + + "akka.tracked-dispatcher" { + includes = ["**"] + } + + "akka.traced-actor" { + includes = ["**"] + } + + } + + akka-http { + add-http-status-code-as-metric-tag = true + } + + akka { + ask-pattern-timeout-warning = lightweight + } + + trace { + join-remote-parents-with-same-span-id = yes + } + + system-metrics { + host { + enabled = no + enabled = ${?SIGAR_SYSTEM_METRICS} + } + jvm { + enabled = no + enabled = ${?JVM_SYSTEM_METRICS} + } + } + +} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index c1339c7b2b5e52cf61c7bb41bb7b3ba59c451460..659940446830b456353b9f8510ff4f1428fcad39 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -10,25 +10,25 @@ <Root level="DEBUG"> <AppenderRef ref="Console"/> </Root> - <Logger name="akka.actor.LocalActorRefProvider(akka://woken)" level="info"> + <Logger name="akka.actor.LocalActorRefProvider(akka://woken)" level="INFO"> <AppenderRef ref="Console"/> </Logger> - <Logger name="akka.cluster" level="info"> + <Logger name="akka.cluster" level="${sys:AKKA_CLUSTER_LOG_LEVEL:-INFO}"> <AppenderRef ref="Console"/> </Logger> - <Logger name="akka.io" level="info"> + <Logger name="akka.io" level="INFO"> <AppenderRef ref="Console"/> </Logger> - <Logger name="akka.http.impl" level="info"> + <Logger name="akka.http.impl" level="INFO"> <AppenderRef ref="Console"/> </Logger> - <Logger name="akka.remote.artery.compress" level="info"> + <Logger name="akka.remote.artery.compress" level="${sys:AKKA_CLUSTER_LOG_LEVEL:-INFO}"> <AppenderRef ref="Console"/> </Logger> - <Logger name="akka.remote.artery.tcp" level="info"> + <Logger name="akka.remote.artery.tcp" level="${sys:AKKA_CLUSTER_LOG_LEVEL:-INFO}"> <AppenderRef ref="Console"/> </Logger> - <Logger name="akka.stream.impl" level="info"> + <Logger name="akka.stream.impl" level="INFO"> <AppenderRef ref="Console"/> </Logger> </Loggers> diff --git a/src/main/resources/reference.conf b/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..c6ce4a9034d3dcca6d4d801997217c78b775684b --- /dev/null +++ b/src/main/resources/reference.conf @@ -0,0 +1,12 @@ + +app { + clusterSystemName = ${clustering.cluster.name} +} + +# Merged with defaults in woken-messages/reference.conf +clustering { + ip = "127.0.0.1" + ip = ${?CLUSTER_IP} + port = 4489 + port = ${?CLUSTER_PORT} +}