Skip to content

Commit

Permalink
Adds docstring for tracer
Browse files Browse the repository at this point in the history
  • Loading branch information
roobalimsab committed Oct 1, 2019
1 parent d05e6bb commit 28ac2cc
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 39 deletions.
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ For publishing data using a producer which is defined for the stream router conf
## Tracing
[Open Tracing](https://opentracing.io/docs/overview/) enables to identify the amount of time spent in various stages of the work flow.

Currently, the execution of the handler function can be traced. If the message consumed has the corresponding tracing headers, then the E2E life time of the message from the time of production till the time of consumption can be traced.
Currently, the execution of the handler function is traced. If the message consumed has the corresponding tracing headers, then the E2E life time of the message from the time of production till the time of consumption can be traced.

Tracing has been added to the following flows:

Expand All @@ -212,20 +212,23 @@ Tracing has been added to the following flows:
3. Produce to rabbitmq channel
4. Produce to another kafka topic

By default, tracing is done via [Jaeger](https://www.jaegertracing.io/). The corresponding `:default-tracer-config` has to be set to publish the traces to the desired Jaeger cluster.
To enable custom tracer, a tracer provider function name can be set in `:tracer-provider`. The corresponding function will be executed in runtime to create a tracer. In the event of any errors while executing the custom tracer provider, a Noop tracer will be created.
By default, tracing is done via [Jaeger](https://www.jaegertracing.io/) based on the env configs. Please refer [Jaeger Configuration](https://github.com/jaegertracing/jaeger-client-java/tree/master/jaeger-core#configuration-via-environment)
and [Jaeger Architecture](https://www.jaegertracing.io/docs/1.13/architecture/) to set the respective env variables.
To enable custom tracer, a custom tracer provider function name can be set in `:custom-provider`. The corresponding function will be executed in runtime to create a tracer. In the event of any errors while executing the custom tracer provider, a Noop tracer will be created.

To enable tracing, the following config needs to be added to the `config.edn` under `:ziggurat` key.

```clojure
:tracer {:enabled [true :bool]
:tracer-provider ""
:default-tracer-config {:jaeger-service-name "test_service"
:jaeger-agent-host "localhost"
:jaeger-agent-port [6831 :int]
:jaeger-reporter-log-spans [true :bool]}}
:custom-provider ""}
```

Example Jaeger Env Config:
```
JAEGER_SERVICE_NAME: "service-name"
JAEGER_AGENT_HOST: "localhost"
JAEGER_AGENT_PORT: 6831
```
`:jaeger_service_name` is the operation name for the trace

## Configuration

Expand Down
6 changes: 1 addition & 5 deletions resources/config.test.ci.edn
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,5 @@
:retry {:count [5 :int]
:enabled [true :bool]}}}}}
:tracer {:enabled [true :bool]
:tracer-provider ""
:default-tracer-config {:jaeger-service-name "test_service"
:jaeger-agent-host "localhost"
:jaeger-agent-port [6831 :int]
:jaeger-reporter-log-spans [true :bool]}}}}
:tracer-provider ""}}}

8 changes: 2 additions & 6 deletions resources/config.test.edn
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,5 @@
:channels {:channel-1 {:worker-count [10 :int]
:retry {:count [5 :int]
:enabled [true :bool]}}}}}
:tracer {:enabled [true :bool]
:tracer-provider ""
:default-tracer-config {:jaeger-service-name "test_service"
:jaeger-agent-host "localhost"
:jaeger-agent-port [6831 :int]
:jaeger-reporter-log-spans [true :bool]}}}}
:tracer {:enabled [true :bool]
:custom-provider ""}}}
78 changes: 64 additions & 14 deletions src/ziggurat/tracer.clj
Original file line number Diff line number Diff line change
@@ -1,32 +1,82 @@
(ns ziggurat.tracer
"This namespace creates a [tracer](https://opentracing.io/docs/overview/tracers/)
that can be used to trace the various stages of the application workflow.
The following flows are traced:
1. Normal basic consume
2. Retry via rabbitmq
3. Produce to rabbitmq channel
4. Produce to another kafka topic
At the time of initialization, an instance of `io.opentracing Tracer`
is created based on the configuration.
- If tracer is disabled, then a `NoopTracer` is created,
which will basically do nothing.
- If tracer is enabled, then by default a [Jaeger](https://www.jaegertracing.io/)
tracer will be created based on the environment variables. Please refer
[Jaeger Configuration](https://github.com/jaegertracing/jaeger-client-java/tree/master/jaeger-core#configuration-via-environment)
and [Jaeger Architecture](https://www.jaegertracing.io/docs/1.13/architecture/)
to set the respective env variables.
Example Jaeger Env Config:
`
JAEGER_SERVICE_NAME: \"service-name\"
JAEGER_AGENT_HOST: \"localhost\"
JAEGER_AGENT_PORT: 6831
`
- Custom tracer can be created by passing the name of a custom tracer
provider function as `:custom-provider`.The corresponding function
will be executed to create the tracer.
In the event of any errors, a NoopTracer will be created
Example tracer configuration:
`
:tracer {:enabled [true :bool]\n
:custom-provider \"\"}
`
Usage:
`
In `ziggurat.streams/traced-handler-fn`, around the execution of the handler function,
a span is started, activated and finished. If there are trace-id headers in the kafka message,
this span will be tied to the same trace. If not, a new trace will be started.
Any part of the handler function execution can be traced as a child span of this activated parent span.
Please refer to the [doc](https://github.com/opentracing/opentracing-java#starting-a-new-span)
to understand how to create child spans.
The trace ids are propagated to rabbitmq using `io.opentracing.contrib.rabbitmq.TracingConnection`.
Hence rabbitmq flows are also traced.
The trace ids are propagated back to kafka using `io.opentracing.contrib.kafka.TracingKafkaProducer`.
Hence push back to kafka flow is traced.
`"
(:require [mount.core :refer [defstate]]
[ziggurat.config :refer [ziggurat-config]]
[clojure.tools.logging :as log])
(:import [io.jaegertracing Configuration Configuration$ReporterConfiguration Configuration$SenderConfiguration]
(:import [io.jaegertracing Configuration]
[io.opentracing.noop NoopTracerFactory]
[io.opentracing Tracer]))

(defn- default-tracer-provider [{:keys [jaeger-service-name jaeger-agent-host jaeger-agent-port jaeger-reporter-log-spans]}]
(let [sender-configuration (-> (Configuration$SenderConfiguration.)
(.withAgentHost jaeger-agent-host)
(.withAgentPort (int jaeger-agent-port)))
reporter-configuration (-> (Configuration$ReporterConfiguration.)
(.withLogSpans jaeger-reporter-log-spans)
(.withSender sender-configuration))
configuration (.withTraceId128Bit (Configuration. jaeger-service-name) true)]
(.getTracer (.withReporter configuration reporter-configuration))))
(defn default-tracer-provider []
(.getTracer (Configuration/fromEnv)))

(defn create-tracer []
(try
(let [tracer-config (:tracer (ziggurat-config))
tracer-provider (:tracer-provider tracer-config)]
custom-provider (:custom-provider tracer-config)]
(if (or (nil? tracer-config) (false? (:enabled tracer-config)))
(NoopTracerFactory/create)

(if (or (nil? tracer-provider) (empty? tracer-provider))
(default-tracer-provider (:default-tracer-config tracer-config))
(if (or (nil? custom-provider) (empty? custom-provider))
(default-tracer-provider)

(let [custom-tracer (apply (resolve (symbol tracer-provider)) [])]
(let [custom-tracer (apply (resolve (symbol custom-provider)) [])]
(if-not (instance? Tracer custom-tracer)
(throw (RuntimeException. "Tracer provider did not return a valid tracer"))
custom-tracer)))))
Expand Down
13 changes: 8 additions & 5 deletions test/ziggurat/tracer_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
[ziggurat.config :refer [ziggurat-config]]
[ziggurat.fixtures :as fix]
[ziggurat.tracer :as tracer])
(:import [io.opentracing.mock MockTracer]))
(:import [io.opentracing.mock MockTracer]
(io.jaegertracing.internal JaegerTracer$Builder)))

(use-fixtures :once fix/silence-logging)

Expand All @@ -14,14 +15,16 @@
(deftest mount-tracer-test
(testing "should start JaegerTracer when tracer is enabled and tracer provider is empty"
(fix/mount-config)
(mount/start (mount/only [#'tracer/tracer]))
(is (= "JaegerTracer" (.getSimpleName (.getClass tracer/tracer))))
(with-redefs [tracer/default-tracer-provider (fn [] (.build (JaegerTracer$Builder. "test")))]
(mount/start (mount/only [#'tracer/tracer]))
(is (= "JaegerTracer" (.getSimpleName (.getClass tracer/tracer)))))
(mount/stop))

(testing "should start JaegerTracer when tracer is enabled and tracer provider is nil"
(fix/mount-config)
(mount/start (mount/only [#'tracer/tracer]))
(is (= "JaegerTracer" (.getSimpleName (.getClass tracer/tracer))))
(with-redefs [tracer/default-tracer-provider (fn [] (.build (JaegerTracer$Builder. "test")))]
(mount/start (mount/only [#'tracer/tracer]))
(is (= "JaegerTracer" (.getSimpleName (.getClass tracer/tracer)))))
(mount/stop))

(testing "should execute create custom tracer when tracer is enabled and tracer provider is set"
Expand Down

0 comments on commit 28ac2cc

Please sign in to comment.