Skip to content

Commit

Permalink
Add Compojure example
Browse files Browse the repository at this point in the history
- Added `countries-service` app to demonstrate use of
  `wrap-compojure-route`
- Updated guide to include Compojure support
  • Loading branch information
steffan-westcott committed Dec 27, 2023
1 parent 39a8ef5 commit 9277539
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 24 deletions.
5 changes: 4 additions & 1 deletion .zprint.edn
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@
"go" :flow-body

;; clojure.tools.build.api
"with-project-root" :arg1-body}}
"with-project-root" :arg1-body

;; Compojure
"defroutes" :arg1-body}}
3 changes: 2 additions & 1 deletion build.clj
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ clojure -A:deps -T:build help/doc"
"examples/microservices/manual-instrument/middleware/random-word-service"])

(def ^:private other-demo-project-paths
["examples/cube-app"
["examples/countries-service"
"examples/cube-app"
"examples/divisor-app"
"examples/factorial-app"
"examples/square-app"
Expand Down
29 changes: 23 additions & 6 deletions doc/examples.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ graph LR
----
+
endif::[]
A small application run with the OpenTelemetry instrumentation agent on `localhost`, exporting telemetry to a Collector instance.
A small application `cube-app` run with the OpenTelemetry instrumentation agent on `localhost`, exporting telemetry to a Collector instance.

* `examples/square-app`
+
Expand All @@ -66,7 +66,7 @@ graph LR
----
+
endif::[]
A small application using autoconfigured OpenTelemetry SDK, run on `localhost`, exporting telemetry to a Collector instance.
A small application `square-app` using autoconfigured OpenTelemetry SDK, run on `localhost`, exporting telemetry to a Collector instance.

* `examples/factorial-app`
+
Expand All @@ -83,7 +83,7 @@ graph LR
----
+
endif::[]
A small application using programmatically configured OpenTelemetry SDK, run on `localhost`, exporting telemetry to a Collector instance.
A small application `factorial-app` using programmatically configured OpenTelemetry SDK, run on `localhost`, exporting telemetry to a Collector instance.

* `examples/divisor-app`
+
Expand All @@ -101,7 +101,24 @@ graph LR
----
+
endif::[]
A small application using autoconfigured OpenTelemetry SDK, run on `localhost`, exporting telemetry directly to Jaeger and Prometheus instances.
A small application `divisor-app` using autoconfigured OpenTelemetry SDK, run on `localhost`, exporting telemetry directly to Jaeger and Prometheus instances.

* `examples/countries-service`
+
ifdef::env-github[[source,mermaid]]
ifndef::env-github,env-cljdoc[[mermaid]]
ifndef::env-cljdoc[]
----
graph LR
subgraph docker network
otel-collector --> jaeger
otel-collector --remote write--> prometheus
end
localhost --> otel-collector
----
+
endif::[]
A single HTTP service `countries-service` run with the OpenTelemetry instrumentation agent on `localhost`, implemented with Ring middleware, Compojure router, exporting telemetry to a Collector instance.

* `examples/microservices/auto-instrument/middleware`
+
Expand All @@ -120,7 +137,7 @@ graph LR
----
+
endif::[]
A pair of dependent microservices `sentence-summary-service` and `word-length-service` implemented with Ring middleware, both using the OpenTelemetry instrumentation agent, exporting telemetry to a Collector instance.
A pair of dependent microservices `sentence-summary-service` and `word-length-service` implemented with Ring middleware, Reitit router, both using the OpenTelemetry instrumentation agent, exporting telemetry to a Collector instance.

* `examples/microservices/auto-instrument/interceptor`
+
Expand Down Expand Up @@ -158,7 +175,7 @@ graph LR
----
+
endif::[]
A pair of dependent microservices `puzzle-service` and `random-word-service` implemented with Ring middleware, not using the agent, exporting telemetry to a Collector instance.
A pair of dependent microservices `puzzle-service` and `random-word-service` implemented with Ring middleware, Reitit router, not using the agent, exporting telemetry to a Collector instance.

* `examples/microservices/manual-instrument/interceptor`
+
Expand Down
52 changes: 36 additions & 16 deletions doc/guides.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,9 @@ This is the same example as above, for an application run without the agent
----

* If you use middleware that injects data on the matched route into the Ring request map, add middleware https://cljdoc.org/d/com.github.steffan-westcott/clj-otel-api/CURRENT/api/steffan-westcott.clj-otel.api.trace.http#wrap-route[`steffan-westcott.clj-otel.api.trace.http/wrap-route`] to add the route data to HTTP server spans for all matched routes.
Alternatively, use https://cljdoc.org/d/com.github.steffan-westcott/clj-otel-api/CURRENT/api/steffan-westcott.clj-otel.api.trace.http#wrap-reitit-route[`steffan-westcott.clj-otel.api.trace.http/wrap-reitit-route`] for https://github.com/metosin/reitit[Reitit] or https://cljdoc.org/d/com.github.steffan-westcott/clj-otel-api/CURRENT/api/steffan-westcott.clj-otel.api.trace.http#wrap-compojure-route[`steffan-westcott.clj-otel.api.trace.http/wrap-compojure-route`] for https://github.com/weavejester/compojure[Compojure].
+
This is an example when using https://github.com/metosin/reitit[Reitit], with Jetty in an application run with the agent
This is an example when using Reitit, with Jetty in an application run with the agent
+
[source,clojure]
----
Expand All @@ -391,11 +392,6 @@ This is an example when using https://github.com/metosin/reitit[Reitit], with Je
[ring.adapter.jetty :as jetty]
[steffan-westcott.clj-otel.api.trace.http :as trace-http]))
(defn wrap-reitit-route [handler]
(trace-http/wrap-route handler
(fn [request]
(get-in request [:reitit.core/match :template]))))
(defn foo-handler [request]
;; ...
)
Expand All @@ -404,21 +400,49 @@ This is an example when using https://github.com/metosin/reitit[Reitit], with Je
(ring/ring-handler (ring/router
["/foo" {:name ::foo :get foo-handler}]
{:data {:muuntaja m/instance
:middleware [wrap-reitit-route
:middleware [trace-http/wrap-reitit-route
;; ... other middleware
]}})
(ring/create-default-handler)
;; Wrap handling of all requests, including those which have no matching route.
;; Add HTTP server span support to all requests, including
;; those which have no matching route.
{:middleware [[trace-http/wrap-server-span {:create-span? false}]]}))
(defonce server
(jetty/run-jetty #'handler {:port 8080 :join? false}))
----
+
This is an example when using Compojure, again with Jetty in an application run with the agent
+
[source,clojure]
----
(ns example.service
(:require [compojure.core :refer [defroutes GET] :as compojure]
[ring.adapter.jetty :as jetty]
[steffan-westcott.clj-otel.api.trace.http :as trace-http]))
(defroutes handler
(GET "/foo" [] ...)
...)
(def service
(-> handler
;; Add matched Compojure route to server span data.
(compojure/wrap-routes trace-http/wrap-compojure-route)
;; Add HTTP server span support to all requests, including
;; those which have no matching route.
trace-http/wrap-server-span))
(defonce server
(jetty/run-jetty #'service {:port 8080 :join? false}))
----
+
Optionally, to add some HTTP server metrics for applications run without the OpenTelemetry instrumentation agent, add middleware https://cljdoc.org/d/com.github.steffan-westcott/clj-otel-api/CURRENT/api/steffan-westcott.clj-otel.api.metrics.http.server#wrap-active-requests[`steffan-westcott.clj-otel.api.metrics.http.server/wrap-active-requests`] and https://cljdoc.org/d/com.github.steffan-westcott/clj-otel-api/CURRENT/api/steffan-westcott.clj-otel.api.metrics.http.server#wrap-metrics-by-route[`steffan-westcott.clj-otel.api.metrics.http.server/wrap-metrics-by-route`].
+
This is the same example as above, for an application run without the agent
This is the same example using Reitit as above, for an application run without the agent
+
[source,clojure]
----
Expand All @@ -429,11 +453,6 @@ This is the same example as above, for an application run without the agent
[steffan-westcott.clj-otel.api.metrics.http.server :as metrics-http-server]
[steffan-westcott.clj-otel.api.trace.http :as trace-http]))
(defn wrap-reitit-route [handler]
(trace-http/wrap-route handler
(fn [request]
(get-in request [:reitit.core/match :template]))))
(defn foo-handler [request]
;; ...
)
Expand All @@ -442,13 +461,14 @@ This is the same example as above, for an application run without the agent
(ring/ring-handler (ring/router
["/foo" {:name ::foo :get foo-handler}]
{:data {:muuntaja m/instance
:middleware [wrap-reitit-route
:middleware [trace-http/wrap-reitit-route
metrics-http-server/wrap-metrics-by-route
;; ... other middleware
]}})
(ring/create-default-handler)
;; Wrap handling of all requests, including those which have no matching route.
;; Wrap handling of all requests, including those
;; which have no matching route.
{:middleware [[trace-http/wrap-server-span {:create-span? true}]
[metrics-http-server/wrap-active-requests]]}))
Expand Down
34 changes: 34 additions & 0 deletions examples/countries-service/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
services:

# Jaeger
jaeger:
image: jaegertracing/all-in-one:latest
command:
- --collector.otlp.enabled=true
ports:
- "16686:16686" # Jaeger web interface

# Prometheus
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yaml:/etc/prometheus.yaml
command:
- --config.file=/etc/prometheus.yaml
- --web.enable-remote-write-receiver
ports:
- "9090:9090" # Prometheus web interface

# OpenTelemetry Collector
otel-collector:
image: otel/opentelemetry-collector:latest
volumes:
- ./otel-collector.yaml:/etc/otel-collector.yaml
command:
- --config=/etc/otel-collector.yaml
ports:
- "4317:4317" # OTLP gRPC receiver
# - "4318:4318" # OTLP HTTP receiver
depends_on:
- jaeger
- prometheus
31 changes: 31 additions & 0 deletions examples/countries-service/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
;!zprint {:style [:respect-nl] :width 140}

{:paths ["src" "resources"]

:deps {org.clojure/clojure {:mvn/version "1.11.1"}

;; Application configuration
aero/aero {:mvn/version "1.1.6"}

;; Clojure wrapper of OpenTelemetry API
com.github.steffan-westcott/clj-otel-api {:local/root "../../clj-otel-api"}

;; Compojure HTTP router
compojure/compojure {:mvn/version "1.7.0"}

;; Ring-Jetty web server integration
ring/ring-jetty-adapter {:mvn/version "1.10.0"}}

:aliases {;; Include this alias to export telemetry data
:otel {:jvm-opts [;; Use the OpenTelemetry instrumentation agent
"-javaagent:../opentelemetry-javaagent.jar"
"-Dotel.semconv-stability.opt-in=http"

;; Name the instrumented application or service
"-Dotel.resource.attributes=service.name=countries-service"

;; Set metric export to every 5 seconds
"-Dotel.metric.export.interval=5000"

;; Disable logs export
"-Dotel.logs.exporter=none"]}}}
67 changes: 67 additions & 0 deletions examples/countries-service/otel-collector.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# OpenTelemetry Collector configuration.

# Telemetry data receivers components
receivers:

# Receives data in OpenTelemetry Protocol format
otlp:
protocols:

# Enable gRPC receiver
grpc:

# Enable HTTP receiver
# http:



# Telemetry data processors components
processors:

# Help avoid out-of-memory errors during high load
memory_limiter:
check_interval: 1s
limit_mib: 50

# Places received data in batches prior to export
batch:



# Telemetry data exporters components
exporters:

# Logs brief summary of telemetry data to console
logging:

# Exports to Jaeger using OTLP over gRPC
otlp/jaeger:
endpoint: "jaeger:4317"
tls:
insecure: true

# Exports to Prometheus
prometheusremotewrite:
endpoint: "http://prometheus:9090/api/v1/write"
tls:
insecure: true



# Enable receivers, processors, exporters and extensions components
service:

# Enable pipelines of components for telemetry data
pipelines:

# Enable pipeline of components for traces
traces:
receivers: [ otlp ]
processors: [ memory_limiter, batch ]
exporters: [ logging, otlp/jaeger ]

# Enable pipeline of components for metrics
metrics:
receivers: [ otlp ]
processors: [ memory_limiter, batch ]
exporters: [ prometheusremotewrite ]
2 changes: 2 additions & 0 deletions examples/countries-service/prometheus.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global:
evaluation_interval: 15s
2 changes: 2 additions & 0 deletions examples/countries-service/resources/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{:jetty-opts {:max-threads 16
:port 8080}}
16 changes: 16 additions & 0 deletions examples/countries-service/resources/log4j2.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
status = warn

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = JsonTemplateLayout
appender.console.layout.eventTemplateUri = classpath:JsonLayout.json
appender.console.layout.eventTemplateAdditionalField[0].type = EventTemplateAdditionalField
appender.console.layout.eventTemplateAdditionalField[0].key = message
appender.console.layout.eventTemplateAdditionalField[0].format = JSON
appender.console.layout.eventTemplateAdditionalField[0].value = {"$resolver":"message"}

logger.app.level = debug
logger.app.name = example

rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT
Loading

0 comments on commit 9277539

Please sign in to comment.