Skip to content

Commit

Permalink
Merge branch 'develop' into feature/adaptive-learning/add-metrics-ser…
Browse files Browse the repository at this point in the history
…vice
  • Loading branch information
MaximilianAnzinger authored May 8, 2024
2 parents 026a085 + f40b0fb commit 22cdef2
Show file tree
Hide file tree
Showing 183 changed files with 1,786 additions and 1,298 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ Refer to [Using JHipster in production](http://www.jhipster.tech/production) for
The following command can automate the deployment to a server. The example shows the deployment to the main Artemis test server (which runs a virtual machine):

```shell
./artemis-server-cli deploy [email protected] -w build/libs/Artemis-7.0.3.war
./artemis-server-cli deploy [email protected] -w build/libs/Artemis-7.0.4.war
```

## Architecture
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ plugins {
}

group = "de.tum.in.www1.artemis"
version = "7.0.3"
version = "7.0.4"
description = "Interactive Learning with Individual Feedback"

java {
Expand Down Expand Up @@ -190,7 +190,7 @@ jacocoTestCoverageVerification {
counter = "CLASS"
value = "MISSEDCOUNT"
// TODO: in the future the following value should become less than 10
maximum = 26
maximum = 27
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion docker/artemis/config/node1.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SPRING_PROFILES_ACTIVE='prod,localvc,localci,buildagent,core,scheduling,docker'
SPRING_PROFILES_ACTIVE='prod,localvc,localci,core,scheduling,docker'
EUREKA_INSTANCE_INSTANCEID='Artemis:1'
EUREKA_INSTANCE_HOSTNAME='artemis-app-node-1'
SPRING_HAZELCAST_INTERFACE='artemis-app-node-1'
3 changes: 3 additions & 0 deletions docker/artemis/config/node2.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ SPRING_PROFILES_ACTIVE='prod,localvc,localci,buildagent,core,docker'
EUREKA_INSTANCE_INSTANCEID='Artemis:2'
EUREKA_INSTANCE_HOSTNAME='artemis-app-node-2'
SPRING_HAZELCAST_INTERFACE='artemis-app-node-2'

ARTEMIS_VERSIONCONTROL_USER='artemis_admin'
ARTEMIS_VERSIONCONTROL_PASSWORD='artemis_admin'
5 changes: 4 additions & 1 deletion docker/artemis/config/node3.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
SPRING_PROFILES_ACTIVE='prod,localvc,localci,buildagent,core,docker'
SPRING_PROFILES_ACTIVE='prod,buildagent'
EUREKA_INSTANCE_INSTANCEID='Artemis:3'
EUREKA_INSTANCE_HOSTNAME='artemis-app-node-3'
SPRING_HAZELCAST_INTERFACE='artemis-app-node-3'

ARTEMIS_VERSIONCONTROL_USER='artemis_admin'
ARTEMIS_VERSIONCONTROL_PASSWORD='artemis_admin'
2 changes: 1 addition & 1 deletion docker/artemis/config/prod-multinode.env
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ EUREKA_INSTANCE_APPNAME='Artemis'
JHIPSTER_REGISTRY_PASSWORD="admin"
JHIPSTER_SECURITY_AUTHENTICATION_JWT_BASE64SECRET="bXktc2VjcmV0LWtleS13aGljaC1zaG91bGQtYmUtY2hhbmdlZC1pbi1wcm9kdWN0aW9uLWFuZC1iZS1iYXNlNjQtZW5jb2RlZAo="

ARTEMIS_VERSIONCONTROL_URL='https://localhost'
ARTEMIS_VERSIONCONTROL_URL='http://artemis-app-node-2:8080'
ARTEMIS_VERSIONCONTROL_USER='demo'
ARTEMIS_VERSIONCONTROL_PASSWORD='demo'
ARTEMIS_CONTINUOUSINTEGRATION_ARTEMISAUTHENTICATIONTOKENVALUE='demo'
Expand Down
1 change: 0 additions & 1 deletion docker/nginx/artemis-upstream-multi-node.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
server artemis-app-node-1:8080;
server artemis-app-node-2:8080;
server artemis-app-node-3:8080;
117 changes: 117 additions & 0 deletions docs/admin/setup/distributed.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ have to be synchronized:

Each of these three aspects is synchronized using a different solution

.. _Database Cache:

Database cache
^^^^^^^^^^^^^^
Artemis uses a cache provider that supports distributed caching: Hazelcast_.
Expand Down Expand Up @@ -281,6 +283,8 @@ This enables the registry in nginx
This will apply the config changes and the registry will be reachable.


.. _WebSockets:

WebSockets
^^^^^^^^^^

Expand Down Expand Up @@ -652,3 +656,116 @@ different ports and a unique instance ID for each instance.
#. Start the remaining instances.

You should now be able to see all instances in the registry interface at ``http://localhost:8761``.

.. _Running multiple instances locally with Docker:

Running multiple instances locally with Docker
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You can also run multiple instances of Artemis locally using Docker. This will start 3 Artemis instances, each running
on a its own container. A load balancer (nginx) will be used to distribute the requests to the different instances. The
load balancer will be running in a separate container and will be accessible on ports 80/443 of the host system. The
instances will be registered in the registry service running on a separate container. The instances will use the registry
service to discover each other and form a Hazelcast cluster. Further details can be found in :ref:`Database Cache`. The
instances will also use a ActiveMQ Artemis broker to synchronize WebSocket messages. Further details can be found in
:ref:`WebSockets`. In summary, the setup will look like this:

* 3 Artemis instances:

* artemis-app-node-1: using following spring profile: ``prod,localvc,localci,core,scheduling,docker``
* artemis-app-node-2: using following profile: ``prod,localvc,localci,buildagent,core,docker``
* artemis-app-node-3: using following profile: ``prod,buildagent``
* A MySQL database addressable on port 3306 of the host system
* A Load balancer (nginx) addressable on ports 80/443 of the host system: ``http(s)://localhost``
* A Registry service addressable on port 8761 of the host system: ``http://localhost:8761``
* An ActiveMQ broker


.. figure:: distributed/multi-node-setup.drawio.png
:align: center



.. note::

- You don't have to start the client manually. The client files are served by the Artemis instances and can be
accessed through the load balancer on ``http(s)://localhost``.

- You may run into the following error when starting the containers
``No member group is available to assign partition ownership...``. This issue should resolve itself after a few
minutes. Otherwise, you can first start the following containers:
``docker compose -f docker/test-server-multi-node-mysql-localci.yml up mysql jhipster-registry activemq-broker artemis-app-node-1``.
After these containers are up and running, you can start the remaining containers:
``docker compose -f docker/test-server-multi-node-mysql-localci.yml up artemis-app-node-2 artemis-app-node-3 nginx``.


Linux setup
"""""""""""

#. When running the Artemis container on a Unix system, you will have to give the user running in the container
permission to access the Docker socket by adding them to the docker group. You can find the group ID of the docker
group by running ``getent group docker | cut -d: -f3``. Afterwards, create a new file ``docker/.env`` with the
following content:

.. code:: bash
DOCKER_GROUP_ID=<REPLACE_WITH_DOCKER_GROUP_ID_OF_YOUR_SYSTEM>
#. The docker compose setup which we will use will mount some local directories
(namely the ones under docker/.docker-data) into the containers. To ensure that the user running in the container has
the necessary permissions to these directories, you will have to change the owner of these directories to the
user running in the container (User with ID 1337). You can do this by running the following command:

.. code:: bash
sudo chown -R 1337:1337 docker/.docker-data
.. note::

- If you don't want to change the owner of the directories, you can create other directories with the necessary
permissions and adjust the paths in the docker-compose file accordingly.
- You could also use docker volumes instead of mounting local directories. You will have to adjust the docker-compose
file accordingly (`Docker docs <https://docs.docker.com/storage/volumes/#use-a-volume-with-docker-compose/>`_).
However, this would make it more difficult to access the files on the host system.

#. Start the docker containers by running the following command:

.. code:: bash
docker compose -f docker/test-server-multi-node-mysql-localci.yml up
#. You can now access artemis on ``http(s)://localhost`` and the registry on ``http://localhost:8761``.

Windows setup
"""""""""""""

#. When running the Artemis container on a Windows system, you will have to change the value for the Docker connection
URI. You need to change the value of the environment variable ``ARTEMIS_CONTINUOUSINTEGRATION_DOCKERCONNECTIONURI``
in the file ``docker/artemis/config/prod-multinode.env`` to ``tcp://host.docker.internal:2375``.

.. note::

- Make sure that option "Expose daemon on tcp://localhost:2375 without TLS" is enabled. This can be found under
Settings > General in Docker Desktop.

#. Start the docker containers by running the following command:

.. code:: bash
docker compose -f docker/test-server-multi-node-mysql-localci.yml up
#. You can now access artemis on ``http(s)://localhost`` and the registry on ``http://localhost:8761``.

MacOS setup
"""""""""""

#. Make sure to enable "Allow the default Docker socket to be used (requires password)" in the Docker Desktop settings.
This can be found under Settings > Advanced in Docker Desktop.

#. Start the docker containers by running the following command:

.. code:: bash
docker compose -f docker/test-server-multi-node-mysql-localci.yml up
#. You can now access artemis on ``http(s)://localhost`` and the registry on ``http://localhost:8761``.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/dev/guidelines/language-guidelines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ The German language is mainly used for user interaction.
**Best practices** (written in German for demonstration purposes)

* **Nutze neutrale Formulierungen**: Wenn möglich ist es empfehlenswert, neutrale Formulierungen zu finden. Neben passiven Formen, wie z.B. Studierende, können auch aktive mit „Mensch“ bzw. „Person“ etc. verwendet werden. Das spart „der/die“ und inkludiert alle Menschen unabhängig davon, welche Eigenschaften/Kategorien diese Personen sonst noch mitbringen.
* **Verwende die Anrede „du“**:Um eine persönliche und weniger formelle Atmosphäre zu schaffen, verwende „du“ statt „Sie".
* **Beschreibe Handlungen (aktiv oder passiv)**:

* „Automatisch generierte Ergebnisse werden am Ende des Bearbeitungszeitraums erstellt“. Statt „Die Studierenden erhalten am Ende des Bearbeitungszeitraums ein automisch generiertes Ergebnis.“)
Expand Down
8 changes: 7 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ org.gradle.jvmargs=-Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
--add-modules java.se \
--add-exports java.base/jdk.internal.ref=ALL-UNNAMED \
--add-opens java.base/java.lang=ALL-UNNAMED \
--add-opens java.base/sun.nio.ch=ALL-UNNAMED \
--add-opens java.management/sun.management=ALL-UNNAMED \
--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "artemis",
"version": "7.0.3",
"version": "7.0.4",
"description": "Interactive Learning with Individual Feedback",
"private": true,
"license": "MIT",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties
config.getSerializationConfig().addSerializerConfig(createPathSerializerConfig());

if (registration == null) {
log.warn("No discovery service is set up, Hazelcast cannot create a cluster.");
log.info("No discovery service is set up, Hazelcast cannot create a cluster.");
hazelcastBindOnlyOnInterface("127.0.0.1", config);
}
else {
Expand Down Expand Up @@ -270,7 +270,7 @@ public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties

private void configureQueueCluster(Config config, JHipsterProperties jHipsterProperties) {
// Queue specific configurations
log.info("Configure Build Job Queue synchronization in Hazelcast for Local CI");
log.debug("Configure Build Job Queue synchronization in Hazelcast for Local CI");
QueueConfig queueConfig = new QueueConfig("buildJobQueue");
queueConfig.setBackupCount(jHipsterProperties.getCache().getHazelcast().getBackupCount());
queueConfig.setPriorityComparatorClassName("de.tum.in.www1.artemis.service.connectors.localci.LocalCIPriorityQueueComparator");
Expand All @@ -279,7 +279,7 @@ private void configureQueueCluster(Config config, JHipsterProperties jHipsterPro

private void hazelcastBindOnlyOnInterface(String hazelcastInterface, Config config) {
// Hazelcast should bind to the interface and use it as local and public address
log.info("Binding Hazelcast to interface {}", hazelcastInterface);
log.debug("Binding Hazelcast to interface {}", hazelcastInterface);
System.setProperty("hazelcast.local.localAddress", hazelcastInterface);
System.setProperty("hazelcast.local.publicAddress", hazelcastInterface);
config.getNetworkConfig().getInterfaces().setEnabled(true).setInterfaces(Collections.singleton(hazelcastInterface));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class EurekaClientRestTemplateConfiguration {
@Bean
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(TlsProperties tlsProperties,
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) throws GeneralSecurityException, IOException {
log.info("Using RestTemplate for the Eureka client.");
log.debug("Using RestTemplate for the Eureka client.");
// The Eureka DiscoveryClientOptionalArgsConfiguration invokes a private method setupTLS.
// This code is taken from that method.
var args = new RestTemplateDiscoveryClientOptionalArgs(eurekaClientHttpRequestFactorySupplier);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/de/tum/in/www1/artemis/config/MetricsBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ public void calculateCachedActiveUserNames() {

cachedActiveUserNames = statisticsRepository.getActiveUserNames(ZonedDateTime.now().minusDays(14), ZonedDateTime.now());

log.info("calculateCachedActiveUserLogins took {}ms", System.currentTimeMillis() - startDate);
log.debug("calculateCachedActiveUserLogins took {}ms", System.currentTimeMillis() - startDate);
}

/**
Expand Down Expand Up @@ -399,7 +399,7 @@ public void recalculateMetrics() {
updateMultiGaugeIntegerForMinuteRanges(releaseExamGauge, examRepository::countExamsWithStartDateBetween);
updateMultiGaugeIntegerForMinuteRanges(releaseExamStudentMultiplierGauge, examRepository::countExamUsersInExamsWithStartDateBetween);

log.info("recalculateMetrics took {}ms", System.currentTimeMillis() - startDate);
log.debug("recalculateMetrics took {}ms", System.currentTimeMillis() - startDate);
}

@FunctionalInterface
Expand Down Expand Up @@ -546,7 +546,7 @@ public void updatePublicArtemisMetrics() {
activeExamsGauge.set(examRepository.countAllActiveExams(now));
examsGauge.set((int) examRepository.count());

log.info("updatePublicArtemisMetrics took {}ms", System.currentTimeMillis() - startDate);
log.debug("updatePublicArtemisMetrics took {}ms", System.currentTimeMillis() - startDate);
}

private void updateActiveUserMultiGauge(ZonedDateTime now) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void setImages(final Map<String, Map<String, String>> buildImages) {
final var languageSpecificBuildImages = loadImages(buildImages);
checkImageForAllProgrammingLanguagesDefined(languageSpecificBuildImages);
images = languageSpecificBuildImages;
log.info("Loaded Docker image configuration: {}", images);
log.debug("Loaded Docker image configuration: {}", images);
}

/**
Expand Down Expand Up @@ -77,7 +77,7 @@ private Stream<String> buildDockerFlag(final DockerFlag dockerFlag) {
* @param dockerFlags key value pairs of run arguments
*/
public void setDefaultDockerFlags(final List<DockerFlag> dockerFlags) {
log.info("Set Docker flags to {}", dockerFlags);
log.debug("Set Docker flags to {}", dockerFlags);
this.defaultDockerFlags = dockerFlags;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties) {
@Override
public void onStartup(ServletContext servletContext) {
if (env.getActiveProfiles().length != 0) {
log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
log.debug("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
}
setCachingHttpHeaders(servletContext);
log.info("Web application fully configured");
log.debug("Web application fully configured");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public JGitServletConfiguration(LocalVCServletService localVCServletService) {
@Bean
public ServletRegistrationBean<GitServlet> jgitServlet() {
ArtemisGitServlet gitServlet = new ArtemisGitServlet(localVCServletService);
log.info("Registering ArtemisGitServlet for handling fetch and push requests to [Artemis URL]/git/[Project Key]/[Repository Slug].git");
log.debug("Registering ArtemisGitServlet for handling fetch and push requests to [Artemis URL]/git/[Project Key]/[Repository Slug].git");
return new ServletRegistrationBean<>(gitServlet, "/git/*");
}
}
Loading

0 comments on commit 22cdef2

Please sign in to comment.