Skip to content
Merged
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
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ ext {
consuleClientVersion = '1.4.5'
javaxAnnotationVersion = '1.3.2'
recordBuilderVersion = '28'
guavaVersion = '31.0.1-jre'
bucket4jVersion = '6.3.0'
}
25 changes: 25 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id 'java'
}

group 'dev.jsheets'
version '0.1.0'

sourceCompatibility = 16
targetCompatibility = 16

repositories {
mavenCentral()
}

dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitPlatformVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitPlatformVersion"
implementation "com.google.guava:guava:$guavaVersion"
compileOnly "io.soabase.record-builder:record-builder-core:$recordBuilderVersion"
annotationProcessor "io.soabase.record-builder:record-builder-processor:$recordBuilderVersion"
}

test {
useJUnitPlatform()
}
13 changes: 13 additions & 0 deletions common/src/main/java/jsheets/config/Configs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package jsheets.config;

public final class Configs {
private Configs() {}

public static Config loadAll(Config.Source... sources) {
var configs = new Config[sources.length];
for (int source = 0; source < sources.length; source++) {
configs[source] = sources[source].load();
}
return CombinedConfig.of(configs);
}
}
62 changes: 62 additions & 0 deletions common/src/main/java/jsheets/config/FileConfigSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package jsheets.config;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;

import io.soabase.recordbuilder.core.RecordBuilder;

@RecordBuilder
public record FileConfigSource(
Config.Key<?> key,
Path relativePath,
Path workingDirectory
) implements Config.Source {

public static FileConfigSource inCurrentWorkingDirectory(
Config.Key<?> key,
Path relativePath
) {
var workingDirectory = Path.of(System.getProperty("user.dir"));
return new FileConfigSource(key, relativePath, workingDirectory);
}

@Override
public Config load() {
return loadContent()
.map(content -> RawConfig.of(Map.of(key.toString(), content)))
.orElseGet(() -> RawConfig.of(Map.of()));
}

private Optional<String> loadContent() {
return loadFromSystem().or(this::loadFromClassPath);
}

private Optional<String> loadFromSystem() {
var fullPath = workingDirectory.resolve(relativePath);
try {
return Optional.of(
Files.readString(fullPath, StandardCharsets.UTF_8)
);
} catch (IOException failedRead) {
return Optional.empty();
}
}

private Optional<String> loadFromClassPath() {
var resources = Thread.currentThread().getContextClassLoader();
var file = resources.getResourceAsStream(relativePath.toString());
if (file == null) {
return Optional.empty();
}
try (var input = new BufferedInputStream(file)) {
return Optional.of(new String(input.readAllBytes()));
} catch (IOException failedRead) {
return Optional.empty();
}
}
}
24 changes: 24 additions & 0 deletions common/src/main/java/jsheets/event/EventSink.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package jsheets.event;

import java.util.function.Supplier;

public interface EventSink {
void post(Object event);

/**
* Only creates the event to post if the sink is enabled.
* <p>
* This method is preferred if creating an event is associated with some
* overhead. It only runs the {@code eventFactory}, if there is a chance that
* it is subscribed.
*
* @param eventFactory Lazily creates the event
*/
default void postIfEnabled(Supplier<Object> eventFactory) {
post(eventFactory.get());
}

static EventSink ignore() {
return event -> {};
}
}
28 changes: 28 additions & 0 deletions common/src/main/java/jsheets/event/GuavaEventSink.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package jsheets.event;

import java.util.Objects;

import com.google.common.eventbus.EventBus;

public final class GuavaEventSink implements EventSink {
public static EventSink forBus(EventBus bus) {
Objects.requireNonNull(bus, "bus");
return new GuavaEventSink(bus);
}

private final EventBus bus;

private GuavaEventSink(EventBus bus) {
this.bus = bus;
}

@Override
public void post(Object event) {
bus.post(event);
}

@Override
public String toString() {
return "GuavaEventSink(bus=%s)".formatted(bus);
}
}
7 changes: 7 additions & 0 deletions common/src/main/java/jsheets/event/LabeledEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package jsheets.event;

import java.util.Map;

public interface LabeledEvent {
Map<String, Object> labels();
}
File renamed without changes.
2 changes: 2 additions & 0 deletions deploy/compose/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
docker-compose -f monitoring.yml -f main.yml "$@"
16 changes: 14 additions & 2 deletions deploy/minimal/docker-compose.yml → deploy/compose/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ services:
server:
image: ehenoma/jsheets:latest
restart: always
build:
context: ../../
dockerfile: ./server/deploy/Dockerfile
environment:
JSHEETS_SERVER_PORT: 8080
JSHEETS_MONGODB_URI: mongodb://root:root@document-store/jsheets
JSHEETS_MONGODB_URI: mongodb://root:root@document-store/jsheets?authSource=admin
JSHEETS_ZOOKEEPER_CONNECTION_STRING: zookeeper:2181
JSHEETS_SERVER_RATE_LIMIT_CAPACITY: 100
JSHEETS_SERVER_RATE_LIMIT_REFILL_PER_SECOND: 50
ports:
- "8080:8080"
depends_on:
- document-store
networks:
- document-store
- zookeeper
Expand Down Expand Up @@ -38,14 +45,19 @@ services:
restart: always
container_name: runtime
hostname: runtime
build:
context: ../../
dockerfile: ./runtime/deploy/Dockerfile
environment:
JSHEETS_RUNTIME_SERVER_PORT: 8080
JSHEETS_RUNTIME_ZOOKEEPER_CONNECTION_STRING: zookeeper:2181
JSHEETS_RUNTIME_SERVICE_ADVERTISED_HOST: runtime:8080
depends_on:
- zookeeper
networks:
- zookeeper
- runtime
networks:
document-store:
zookeeper:
runtime:
runtime:
35 changes: 35 additions & 0 deletions deploy/compose/monitoring.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: '3.7'
services:
influxdb:
image: influxdb:2.0
hostname: influxdb
ports:
- '8086:8086'
volumes:
- influxdb-storage:/var/lib/influxdb
environment:
DOCKER_INFLUXDB_DB: jsheets
DOCKER_INFLUXDB_INIT_ORG: jsheets
DOCKER_INFLUXDB_INIT_BUCKET: jsheets
DOCKER_INFLUXDB_INIT_USERNAME: ${INFLUXDB_USERNAME}
DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_PASSWORD}
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_TOKEN}
networks:
- influxdb
chronograf:
image: chronograf:latest
ports:
- '127.0.0.1:8888:8888'
volumes:
- chronograf-storage:/var/lib/chronograf
depends_on:
- influxdb
environment:
INFLUXDB_URL: http://influxdb:8086
INFLUXDB_USERNAME: ${INFLUXDB_USERNAME}
INFLUXDB_PASSWORD: ${INFLUXDB_PASSWORD}
volumes:
influxdb-storage:
chronograf-storage:
networks:
influxdb:
15 changes: 15 additions & 0 deletions evaluation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Events
When building the `EvaluationEngine` you can pass an `EventSink`, it will then
post events type `EvaluationEvent`. Those events can be used to record
metrics and run custom code with pretty loose coupling.

If no `EventSink` is configured, the engine will typically not attempt to
create any events, thus no overhead is produced.

Following events are currently posted:

| Name | Posted by | When |
|-------|-----------|--------|
| `EvaluationStartEvent` | `EvaluationEngine` | An evaluation begins
| `EvaluationStopEvent` | `EvaluationEngine` | An evaluation completes or fails
| `BoxLifecycleEvent` | `ForkedExecutionEnvironment` | A JVM is starting/ready/stopping |
3 changes: 2 additions & 1 deletion evaluation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ ext {

dependencies {
implementation project(':protocol')
implementation project(':common')
implementation "org.ow2.asm:asm:$asmVersion"
implementation "com.google.protobuf:protobuf-java-util:$protobufJavaVersion"
implementation "com.google.flogger:flogger:$floggerVersion"
testRuntimeOnly "com.google.flogger:flogger-slf4j-backend:$floggerVersion"
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitPlatformVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitPlatformVersion"
testRuntimeOnly "com.google.flogger:flogger-slf4j-backend:$floggerVersion"
compileOnly "io.soabase.record-builder:record-builder-core:$recordBuilderVersion"
annotationProcessor "io.soabase.record-builder:record-builder-processor:$recordBuilderVersion"
}
Expand Down
11 changes: 11 additions & 0 deletions evaluation/src/main/java/jsheets/evaluation/EvaluationEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package jsheets.evaluation;

import jsheets.event.LabeledEvent;

/**
* The evaluation engine produces events during preprocessing and evaluation
* of snippets that can be used to create metrics and trigger custom code.
*/
public interface EvaluationEvent extends LabeledEvent {
String snippetId();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package jsheets.evaluation;

import java.util.Map;

import io.soabase.recordbuilder.core.RecordBuilder;

@RecordBuilder
public record EvaluationStartEvent(
String snippetId,
Map<String, Object> labels
) implements EvaluationEvent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package jsheets.evaluation;

import java.time.Duration;
import java.util.Map;

import io.soabase.recordbuilder.core.RecordBuilder;

@RecordBuilder
public record EvaluationStopEvent(
String snippetId,
Duration duration,
Status status,
Map<String, Object> labels
) implements EvaluationEvent {

public boolean hasFailed() {
return status.equals(Status.Failed);
}

public enum Status {
/**
* The evaluation was successful, there were no errors in the user code.
*/
CompletedSuccessfully,
/**
* The evaluation could be run but there were errors in the user code.
*/
CompletedWithErrors,
/**
* The evaluation failed, this must not indicate that user code is invalid.
*/
Failed
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package jsheets.evaluation.sandbox;

import java.util.Collection;
import java.util.Map;

import io.soabase.recordbuilder.core.RecordBuilder;
import jsheets.evaluation.EvaluationEvent;
import jsheets.evaluation.sandbox.validation.Analysis;

@RecordBuilder
public record ViolationEvent(
String snippetId,
String componentId,
Collection<Analysis.Violation> violations,
Map<String, Object> labels
) implements EvaluationEvent {}
Loading