From 4f13050d06519ba49ef700580a4362fed6905fdf Mon Sep 17 00:00:00 2001 From: maeddes Date: Thu, 18 Jul 2024 16:09:00 +0000 Subject: [PATCH] added todoui --- .../initial/todobackend-springboot/pom.xml | 13 +- .../OpenTelemetryConfiguration.java | 15 +- .../todobackend/TodobackendApplication.java | 12 +- .../initial/todoui-thymeleaf/Dockerfile | 26 +++ .../initial/todoui-thymeleaf/pom.xml | 91 +++++++++++ .../todoui/OpenTelemetryConfiguration.java | 60 +++++++ .../io/novatec/todoui/TodouiApplication.java | 151 ++++++++++++++++++ .../src/main/resources/application.properties | 17 ++ .../src/main/resources/templates/items.html | 88 ++++++++++ exercises/manual-instrumentation-java/steps | 10 +- 10 files changed, 466 insertions(+), 17 deletions(-) create mode 100644 exercises/manual-instrumentation-java/initial/todoui-thymeleaf/Dockerfile create mode 100644 exercises/manual-instrumentation-java/initial/todoui-thymeleaf/pom.xml create mode 100644 exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/OpenTelemetryConfiguration.java create mode 100644 exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/TodouiApplication.java create mode 100644 exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/application.properties create mode 100644 exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/templates/items.html diff --git a/exercises/manual-instrumentation-java/initial/todobackend-springboot/pom.xml b/exercises/manual-instrumentation-java/initial/todobackend-springboot/pom.xml index eff4041..647a7db 100644 --- a/exercises/manual-instrumentation-java/initial/todobackend-springboot/pom.xml +++ b/exercises/manual-instrumentation-java/initial/todobackend-springboot/pom.xml @@ -54,6 +54,12 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-devtools + runtime + true + io.opentelemetry opentelemetry-api @@ -76,12 +82,7 @@ opentelemetry-semconv 1.26.0-alpha - - org.springframework.boot - spring-boot-devtools - runtime - true - + diff --git a/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/OpenTelemetryConfiguration.java b/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/OpenTelemetryConfiguration.java index 925543d..b8eac2d 100644 --- a/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/OpenTelemetryConfiguration.java +++ b/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/OpenTelemetryConfiguration.java @@ -7,17 +7,21 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; -//Basic Otel +//Basic Otel API & SDK import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.exporter.logging.LoggingSpanExporter; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.semconv.ResourceAttributes; + //Tracing and Spans import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; -import io.opentelemetry.semconv.ResourceAttributes; + +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; + +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.propagation.ContextPropagators; @SuppressWarnings("deprecation") @@ -47,6 +51,7 @@ public OpenTelemetry openTelemetry(){ OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) + .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .build(); return openTelemetry; diff --git a/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/TodobackendApplication.java b/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/TodobackendApplication.java index e0d2ecf..f88cc3c 100644 --- a/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/TodobackendApplication.java +++ b/exercises/manual-instrumentation-java/initial/todobackend-springboot/src/main/java/io/novatec/todobackend/TodobackendApplication.java @@ -21,7 +21,9 @@ import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import jakarta.persistence.Entity; @@ -34,6 +36,8 @@ public class TodobackendApplication { private Logger logger = LoggerFactory.getLogger(TodobackendApplication.class); + + private OpenTelemetry openTelemetry; private Tracer tracer; @Value("${HOSTNAME:not_set}") @@ -45,8 +49,10 @@ public class TodobackendApplication { @Autowired TodoRepository todoRepository; - TodobackendApplication(OpenTelemetry openTelemetry) { + public TodobackendApplication(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; tracer = openTelemetry.getTracer(TodobackendApplication.class.getName(), "0.1.0"); + } private String getInstanceId() { @@ -85,7 +91,9 @@ List getTodos() { @PostMapping("/todos/{todo}") String addTodo(@PathVariable String todo) { - Span span = tracer.spanBuilder("addTodo").startSpan(); + //Context extractedContext = openTelemetry.getPropagators().getTextMapPropagator().extract(Context.current(), httpExchange, getter); + + Span span = tracer.spanBuilder("addTodo").setSpanKind(SpanKind.SERVER).startSpan(); System.out.println("Span initial:"+span.toString()); diff --git a/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/Dockerfile b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/Dockerfile new file mode 100644 index 0000000..0e57025 --- /dev/null +++ b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/Dockerfile @@ -0,0 +1,26 @@ +FROM docker.io/maven:3-eclipse-temurin-21 as build +WORKDIR /workspace/app + +COPY pom.xml . +COPY src src + +RUN --mount=type=cache,target=/root/.m2 mvn install -DskipTests +# RUN mvn install -DskipTests +RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) + +FROM docker.io/eclipse-temurin:21-jdk-alpine +RUN mkdir -p /opt/todoui +WORKDIR /opt/todoui +# RUN addgroup -S demo && adduser -S demo -G demo +# USER demo +VOLUME /tmp +ARG DEPENDENCY=/workspace/app/target/dependency +COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /opt/todoui/app/lib +COPY --from=build ${DEPENDENCY}/META-INF /opt/todoui/app/META-INF +COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /opt/todoui/app + +ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar /opt/todoui + +ENTRYPOINT ["java","-cp","/opt/todoui/app:/opt/todoui/app/lib/*", "-javaagent:/opt/todoui/opentelemetry-javaagent.jar", "io.novatec.todoui.TodouiApplication"] +#ENTRYPOINT ["java", "-cp", "/opt/todobackend/app:/opt/todobackend/app/lib/*", "-javaagent:/opt/todobackend/opentelemetry-javaagent.jar","io.novatec.todobackend.TodobackendApplication"] + diff --git a/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/pom.xml b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/pom.xml new file mode 100644 index 0000000..781505c --- /dev/null +++ b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + io.novatec + todoui-manual + 0.0.1-SNAPSHOT + jar + + todoui-manual + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.7.16 + + + + + UTF-8 + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + io.opentelemetry + opentelemetry-api + + + io.opentelemetry + opentelemetry-sdk + + + io.opentelemetry + opentelemetry-exporter-logging + + + io.opentelemetry + opentelemetry-exporter-otlp + + + + io.opentelemetry.semconv + opentelemetry-semconv + 1.26.0-alpha + + + + + + + io.opentelemetry + opentelemetry-bom + 1.40.0 + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/OpenTelemetryConfiguration.java b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/OpenTelemetryConfiguration.java new file mode 100644 index 0000000..06582e7 --- /dev/null +++ b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/OpenTelemetryConfiguration.java @@ -0,0 +1,60 @@ +package io.novatec.todoui; + +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +//Basic Otel API & SDK +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.semconv.ResourceAttributes; + +//Tracing and Spans +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; + +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; + +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.propagation.ContextPropagators; + + +@SuppressWarnings("deprecation") +@Configuration +public class OpenTelemetryConfiguration { + + @Bean + @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) + public OpenTelemetry openTelemetry(){ + + Resource resource = Resource.getDefault().toBuilder().put(ResourceAttributes.SERVICE_NAME, "tododui").put(ResourceAttributes.SERVICE_VERSION, "0.1.0").build(); + + OtlpGrpcSpanExporter jaegerOtlpExporter = + OtlpGrpcSpanExporter.builder() + .setEndpoint("http://localhost:4317") + .setTimeout(30, TimeUnit.SECONDS) + .build(); + + SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) + .addSpanProcessor(SimpleSpanProcessor.create(jaegerOtlpExporter)) + // .addSpanProcessor(BatchSpanProcessor.builder(LoggingSpanExporter.create()).build()) // same results for now + .setResource(resource) + .build(); + // .buildAndRegisterGlobal(); + + + OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() + .setTracerProvider(sdkTracerProvider) + .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) + .build(); + + return openTelemetry; + } + +} diff --git a/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/TodouiApplication.java b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/TodouiApplication.java new file mode 100644 index 0000000..0ab9105 --- /dev/null +++ b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/java/io/novatec/todoui/TodouiApplication.java @@ -0,0 +1,151 @@ +package io.novatec.todoui; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.client.RestTemplate; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Tracer; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; + +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; + +import java.util.List; +import java.util.ArrayList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SpringBootApplication +@Controller +public class TodouiApplication { + + private Logger logger = LoggerFactory.getLogger(TodouiApplication.class); + + private OpenTelemetry openTelemetry; + private Tracer tracer; + + @Value("${backend.url}") + String endpoint; + RestTemplate template = new RestTemplate(); + + public TodouiApplication(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + tracer = openTelemetry.getTracer(TodouiApplication.class.getName(), "0.1.0"); + } + + @PostConstruct + public void postConstruct(){ + + logger.info(" UI initialized for backend at "+endpoint); + } + + @GetMapping("/stress") + public String stress(){ + + logger.info(java.time.LocalDateTime.now() + " : Starting stress"); + double result = 0; + for (int i = 0; i < 100000000; i++) { + result += System.currentTimeMillis(); + } + logger.info(java.time.LocalDateTime.now() + " : Ending stress, result: " + result); + return "redirect:/"; + + } + + public static List list = new ArrayList<>(); // can never be GC'ed + @GetMapping("/leak") + public String leak(){ + + logger.info(java.time.LocalDateTime.now() + " : Start leaking"); + for (int i = 0; i < 10000000; i++) { + list.add(Math.random()); + } + logger.info(java.time.LocalDateTime.now() + " : End leaking"); + return "redirect:/"; + + } + + @GetMapping("/createcookie") + public String createCookie(HttpServletResponse response) { + + Cookie cookie = new Cookie("featureflag", "on"); + cookie.setPath("/"); + response.addCookie(cookie); + return "redirect:/"; + + } + + @GetMapping("/deletecookie") + public String deleteCookie(HttpServletResponse response) { + + Cookie cookie = new Cookie("featureflag", null); + cookie.setMaxAge(0); + cookie.setPath("/"); + response.addCookie(cookie); + return "redirect:/"; + + } + + + @GetMapping + public String getItems(Model model){ + + logger.info("GET "+ endpoint + "/todos/"); + ResponseEntity response = template.getForEntity(endpoint+"/todos/", String[].class); + if(response != null) model.addAttribute("items", response.getBody()); + return "items"; + + } + + @PostMapping + public String addItem(String toDo){ + + logger.info("POST "+ endpoint + "/todos/"+toDo); + + Span span = tracer.spanBuilder("addItem").setSpanKind(SpanKind.CLIENT).startSpan(); + + Context context = Context.current(); + + System.out.println("Context: "+context); + System.out.println("### Hallo"); + + template.postForEntity(endpoint+"/todos/"+toDo, null, String.class); + + + + span.end(); + + return "redirect:/"; + + } + + @PostMapping("{toDo}") + public String setItemDone(@PathVariable String toDo){ + + logger.info("POST "+ endpoint + "/todos/"+toDo); + template.delete(endpoint+"/todos/"+toDo); + return "redirect:/"; + + } + + public static void main(String[] args) { + SpringApplication.run(TodouiApplication.class, args); + } +} diff --git a/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/application.properties b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/application.properties new file mode 100644 index 0000000..dad2d1b --- /dev/null +++ b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/application.properties @@ -0,0 +1,17 @@ +#server port +server.port=8090 + +#todobackend config +backend.host=${BACKEND_HOST:todobackend} +backend.port=${BACKEND_PORT:8080} +backend.url=http://${backend.host}:${backend.port} + +#actuator +management.endpoints.web.exposure.include=* + +#error handling +#server.error.include-exception=true +server.error.include-message=always +#server.error.include-stacktrace=always + + diff --git a/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/templates/items.html b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/templates/items.html new file mode 100644 index 0000000..38668aa --- /dev/null +++ b/exercises/manual-instrumentation-java/initial/todoui-thymeleaf/src/main/resources/templates/items.html @@ -0,0 +1,88 @@ + + + + Most beautiful of all Java Todo Lists + + + + + +
+ +
+

Most beautiful of all Java Todo Lists

+
+ +

Add a ToDo

+ +
+ + + + + + + + + + + +
ItemAction
+ + + + +
+
+ +
+ +

ToDo List

+ +
+ + + + + + + + + +
ItemAction
+ +
+ +
+
+
+ +
+ + + + + + + + + +
ItemAction
You have no ToDos :-)None
+
+
+ + + + + diff --git a/exercises/manual-instrumentation-java/steps b/exercises/manual-instrumentation-java/steps index ee64fb0..a4ffd59 100644 --- a/exercises/manual-instrumentation-java/steps +++ b/exercises/manual-instrumentation-java/steps @@ -63,9 +63,6 @@ import io.opentelemetry.semconv.ResourceAttributes; } - - - For Tracing: import io.opentelemetry.sdk.trace.SdkTracerProvider; @@ -97,4 +94,9 @@ Acquiring a tracer: Creating spans: import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; \ No newline at end of file +import io.opentelemetry.context.Scope; + + +Frontend: + +export BACKEND_URL=http://localhost:8080 \ No newline at end of file