From 67f199a620361b7f611fcda885cf24b23520b42d Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 8 Aug 2019 11:17:54 +0200 Subject: [PATCH 01/22] First draft: "named tracers" --- 0000-named-tracers.md | 67 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 0000-named-tracers.md diff --git a/0000-named-tracers.md b/0000-named-tracers.md new file mode 100644 index 000000000..ada3a81a3 --- /dev/null +++ b/0000-named-tracers.md @@ -0,0 +1,67 @@ +# Named Tracers + +_Creating tracers using a factory mechanism and naming those tracers in accordance with the (logical) components being traced._ + +## Suggested reading + +* [Proposal: Tracer Components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) +* [Global Instance discussions](https://github.com/open-telemetry/opentelemetry-specification/labels/global%20instance) + +## Motivation + +Instead of having a global tracer singleton, every library needs to create its own tracer, which also has a proper name that identifies the library / logical component that uses this tracer. + +This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10), but the term "components" was quickly found to being too generic and possibly misleading, since it is already used frequently in differing contexts and connotations. + +The purpose of _Named Tracers_ is the ability to allow for a more fine-grained control of the amount of tracing data being generated by a library or application. Associating a name (e.g. _"io.opentelemetry.contrib.mongodb"_) with a tracer allows for a logical coupling of this tracer and a certain technology or library (like _MongoDB_ in this example). + +By using *Named Tracers* a library can: +* Identify the spans it created, by automatically setting e.g. a `component` (usually the tracer's name) on each newly created span. +* Enable / Disable tracing of a specific library, which might be necessary in case: + * A library causes too much runtime or memory overhead. + * A library has issues or bugs (e.g. does not call `span.end()` in every case). + * "Double-Tracing" becomes a problem. This can be the case if a vendor (e.g. Dynatrace) might already have built-in auto-instrumentation for a certain library. In this case the vendor might want to decide (automatically or configuration-based) which of the implementations should be enabled or disabled. + + +## Explanation + +From a user perspective, working with *Named Tracers* and *TracerFactories* is very similar to how logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. + +```java +Tracer tracer = OpenTelemetry.Tracing.getTracerFactory().getTracer("io.opentelemetry.contrib.mongodb"); +``` + +In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a tracer instance. + + +## Internal details + +By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing tracers and can decide whether or not to produce spans for a specific traced component and even change this behavior at runtime. + +In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do no want/need to: +* Set the according `component` on the produced spans. +* Enable or disable a tracer. + +Alternatively, an implementation can provide different tracers per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to: +* Enable / Disable a tracer based on a custom configuration. +* Automatically set the `component` ("the component being traced") on every span being produced. + +## Trade-offs and mitigations + +## Prior art and alternatives + +Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return and additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. + +```java + TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder("io.opentelemetry.contrib.mongodb"); + Span span = traceComponent.spanBuilder("someMethod").startSpan(); +``` + +Overall, this would not change a lot since the levels of indirection until producing an actual span are the same. + + +## Open questions + +## Future possibilities + +By adapting this proposal, current implementations that do not honour the specified tracer name and provide a single global tracer, do not required much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracer* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. \ No newline at end of file From 5c6c2b688eb663c8c14431cf727d85546b108639 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 8 Aug 2019 15:54:38 +0200 Subject: [PATCH 02/22] Implement feedback. --- 0000-named-tracers.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/0000-named-tracers.md b/0000-named-tracers.md index ada3a81a3..bc33fa3ea 100644 --- a/0000-named-tracers.md +++ b/0000-named-tracers.md @@ -1,6 +1,6 @@ # Named Tracers -_Creating tracers using a factory mechanism and naming those tracers in accordance with the (logical) components being traced._ +_Creating tracers using a factory mechanism and naming those tracers in accordance with the library that provides the instrumentation for a traced component._ ## Suggested reading @@ -9,18 +9,16 @@ _Creating tracers using a factory mechanism and naming those tracers in accordan ## Motivation -Instead of having a global tracer singleton, every library needs to create its own tracer, which also has a proper name that identifies the library / logical component that uses this tracer. +Instead of having a global tracer singleton, every instrumentation library needs to create its own tracer, which also has a proper name that identifies the library / logical component that uses this tracer. If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10), but the term "components" was quickly found to being too generic and possibly misleading, since it is already used frequently in differing contexts and connotations. The purpose of _Named Tracers_ is the ability to allow for a more fine-grained control of the amount of tracing data being generated by a library or application. Associating a name (e.g. _"io.opentelemetry.contrib.mongodb"_) with a tracer allows for a logical coupling of this tracer and a certain technology or library (like _MongoDB_ in this example). -By using *Named Tracers* a library can: -* Identify the spans it created, by automatically setting e.g. a `component` (usually the tracer's name) on each newly created span. -* Enable / Disable tracing of a specific library, which might be necessary in case: - * A library causes too much runtime or memory overhead. - * A library has issues or bugs (e.g. does not call `span.end()` in every case). - * "Double-Tracing" becomes a problem. This can be the case if a vendor (e.g. Dynatrace) might already have built-in auto-instrumentation for a certain library. In this case the vendor might want to decide (automatically or configuration-based) which of the implementations should be enabled or disabled. +By using *Named Tracers* a library can enable / disable tracing of a specific library, which might be necessary in case: +* A library causes too much runtime or memory overhead. +* A library has issues or bugs (e.g. does not call `span.end()` in every case). +* "Double-Tracing" becomes a problem. This can be the case if a vendor (e.g. Dynatrace) might already have built-in auto-instrumentation for a certain library. In this case the vendor might want to decide (automatically or configuration-based) which of the implementations should be enabled or disabled. ## Explanation @@ -38,12 +36,9 @@ In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing tracers and can decide whether or not to produce spans for a specific traced component and even change this behavior at runtime. -In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do no want/need to: -* Set the according `component` on the produced spans. -* Enable or disable a tracer. +In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do no want/need to enable or disable a tracer. -Alternatively, an implementation can provide different tracers per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to: -* Enable / Disable a tracer based on a custom configuration. +Alternatively, an implementation can provide different tracers per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to enable / disable a tracer based on a custom configuration. * Automatically set the `component` ("the component being traced") on every span being produced. ## Trade-offs and mitigations From 92104bd5a628c6ec4c0de64d037113339d0e36c8 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Mon, 12 Aug 2019 10:53:38 +0200 Subject: [PATCH 03/22] Move named tracers proposal into text folder --- 0000-named-tracers.md => text/0000-named-tracers.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 0000-named-tracers.md => text/0000-named-tracers.md (100%) diff --git a/0000-named-tracers.md b/text/0000-named-tracers.md similarity index 100% rename from 0000-named-tracers.md rename to text/0000-named-tracers.md From 5f7f2a0e57676b46eec81be45f266c2a7c87d788 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 13 Aug 2019 07:45:17 +0200 Subject: [PATCH 04/22] Apply suggestions from code review Co-Authored-By: Armin Ruech --- text/0000-named-tracers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index bc33fa3ea..94bd6069c 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -36,7 +36,7 @@ In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing tracers and can decide whether or not to produce spans for a specific traced component and even change this behavior at runtime. -In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do no want/need to enable or disable a tracer. +In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do not want/need to enable or disable a tracer. Alternatively, an implementation can provide different tracers per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to enable / disable a tracer based on a custom configuration. * Automatically set the `component` ("the component being traced") on every span being produced. @@ -45,7 +45,7 @@ Alternatively, an implementation can provide different tracers per specified tra ## Prior art and alternatives -Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return and additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. +Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder("io.opentelemetry.contrib.mongodb"); @@ -59,4 +59,4 @@ Overall, this would not change a lot since the levels of indirection until produ ## Future possibilities -By adapting this proposal, current implementations that do not honour the specified tracer name and provide a single global tracer, do not required much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracer* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. \ No newline at end of file +By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracer*s is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. From f628980d7305cb97e4be0a9ae0b15bdf711c67fd Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 13 Aug 2019 17:24:57 +0200 Subject: [PATCH 05/22] Apply suggestions from code review Co-Authored-By: Armin Ruech --- text/0000-named-tracers.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 94bd6069c..3d3fba239 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -1,5 +1,7 @@ # Named Tracers +**Status:** `proposed` + _Creating tracers using a factory mechanism and naming those tracers in accordance with the library that provides the instrumentation for a traced component._ ## Suggested reading @@ -15,7 +17,7 @@ This proposal originates from an `opentelemetry-specification` proposal on [comp The purpose of _Named Tracers_ is the ability to allow for a more fine-grained control of the amount of tracing data being generated by a library or application. Associating a name (e.g. _"io.opentelemetry.contrib.mongodb"_) with a tracer allows for a logical coupling of this tracer and a certain technology or library (like _MongoDB_ in this example). -By using *Named Tracers* a library can enable / disable tracing of a specific library, which might be necessary in case: +*Named Tracers* allow enabling and disabling tracing of a specific library, which might be necessary in case: * A library causes too much runtime or memory overhead. * A library has issues or bugs (e.g. does not call `span.end()` in every case). * "Double-Tracing" becomes a problem. This can be the case if a vendor (e.g. Dynatrace) might already have built-in auto-instrumentation for a certain library. In this case the vendor might want to decide (automatically or configuration-based) which of the implementations should be enabled or disabled. From 0a676a5f2ab4e00245d3df0ea6432fe3253b18f3 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 13 Aug 2019 17:52:49 +0200 Subject: [PATCH 06/22] Add examples section. --- text/0000-named-tracers.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 3d3fba239..204b86335 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -1,4 +1,4 @@ -# Named Tracers +# Named Tracers **Status:** `proposed` @@ -40,25 +40,30 @@ By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry impl In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do not want/need to enable or disable a tracer. -Alternatively, an implementation can provide different tracers per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to enable / disable a tracer based on a custom configuration. -* Automatically set the `component` ("the component being traced") on every span being produced. +Alternatively, an implementation can provide different tracer instances per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to enable / disable a tracer based on a custom configuration. ## Trade-offs and mitigations ## Prior art and alternatives -Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. +Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return and additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder("io.opentelemetry.contrib.mongodb"); Span span = traceComponent.spanBuilder("someMethod").startSpan(); ``` -Overall, this would not change a lot since the levels of indirection until producing an actual span are the same. +Overall, this would not change a lot compared to the `TracerFactory` since the levels of indirection until producing an actual span are the same. ## Open questions ## Future possibilities -By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracer*s is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. +By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. + +## Examples (for Tracer names) + +Since tracer names describe the libraries which use the tracers, those names should be defined in a way that makes them as unique as possible. + +Proposed naming is in analogy to Java package names, e.g: "io.opentelemetry.contrib.mongodb". From 3c4d1503312415ccc5e82fbf52c81e12db837343 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 13 Aug 2019 17:57:49 +0200 Subject: [PATCH 07/22] Update 0000-named-tracers.md --- text/0000-named-tracers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 204b86335..91d8df553 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -46,7 +46,7 @@ Alternatively, an implementation can provide different tracer instances per spec ## Prior art and alternatives -Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return and additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. +Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder("io.opentelemetry.contrib.mongodb"); From eba822048b14862ce3fdf1825cddcdc1e40a30f0 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Wed, 28 Aug 2019 08:29:17 +0200 Subject: [PATCH 08/22] Implement feedback from code review --- text/0000-named-tracers.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 91d8df553..1be10a8df 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -25,10 +25,10 @@ The purpose of _Named Tracers_ is the ability to allow for a more fine-grained c ## Explanation -From a user perspective, working with *Named Tracers* and *TracerFactories* is very similar to how logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. +From a user perspective, working with *Named Tracers* and *TracerFactories* is very similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. ```java -Tracer tracer = OpenTelemetry.Tracing.getTracerFactory().getTracer("io.opentelemetry.contrib.mongodb"); +Tracer tracer = OpenTelemetry.getTracerFactory().getTracer("io.opentelemetry.contrib.mongodb"); ``` In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a tracer instance. @@ -62,8 +62,21 @@ Overall, this would not change a lot compared to the `TracerFactory` since the l By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. -## Examples (for Tracer names) +## Examples (of Tracer names) -Since tracer names describe the libraries which use the tracers, those names should be defined in a way that makes them as unique as possible. +Since tracer names describe the libraries which use the tracers, those names should be defined in a way that makes them as unique as possible. The name of the tracer should represent the identity of the library, class or package that provides the instrumentation. + +Examples (based on existing contribution libraries from OpenTracing and OpenCensus): + +* _io.opentracing.contrib.spring.rabbitmq_ +* _io.opentracing.contrib.jdbc_ +* _io.opentracing.thrift_ +* _io.opentracing.contrib.asynchttpclient_ +* _io.opencensus.contrib.http.servlet_ +* _io.opencensus.contrib.spring.sleuth.v1x_ +* _io.opencensus.contrib.http.jaxrs_ +* _github.com/opentracing-contrib/go-amqp_ (Go) +* _github.com/opentracing-contrib/go-grpc_ (Go) +* _OpenTracing.Contrib.NetCore.AspNetCore_ (.NET) +* _OpenTracing.Contrib.NetCore.EntityFrameworkCore_ (.NET) -Proposed naming is in analogy to Java package names, e.g: "io.opentelemetry.contrib.mongodb". From 368f6fd6d1b686963c9ccfa9dc295592255d6588 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Mon, 16 Sep 2019 15:44:50 +0200 Subject: [PATCH 09/22] Remove the implementation details about enabling / disabling ... of sensors and reduced the proposal the actual core of associating names with tracers.:q --- text/0000-named-tracers.md | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 1be10a8df..e0313ba2f 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -11,16 +11,11 @@ _Creating tracers using a factory mechanism and naming those tracers in accordan ## Motivation -Instead of having a global tracer singleton, every instrumentation library needs to create its own tracer, which also has a proper name that identifies the library / logical component that uses this tracer. If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. +Instead of having a global tracer singleton, every instrumentation library needs to create its own tracer, which also has a proper name that identifies the library / logical component that uses this tracer. If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. In this sense, this proposal suggests the introduction of a "semantic namespace" concept for tracers and the resulting spans. -This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10), but the term "components" was quickly found to being too generic and possibly misleading, since it is already used frequently in differing contexts and connotations. +The purpose of _Named Tracers_ is the ability to allow for associating an identifier (e.g. _"io.opentelemetry.contrib.mongodb"_) with a tracer. This further allows for logical and semantic coupling of this tracer and a certain technology or library (like _MongoDB_ in this example). Having named tracers enables support for having a dedicated property (component) depending on this name on a tracer that is different for different libraries. -The purpose of _Named Tracers_ is the ability to allow for a more fine-grained control of the amount of tracing data being generated by a library or application. Associating a name (e.g. _"io.opentelemetry.contrib.mongodb"_) with a tracer allows for a logical coupling of this tracer and a certain technology or library (like _MongoDB_ in this example). - -*Named Tracers* allow enabling and disabling tracing of a specific library, which might be necessary in case: -* A library causes too much runtime or memory overhead. -* A library has issues or bugs (e.g. does not call `span.end()` in every case). -* "Double-Tracing" becomes a problem. This can be the case if a vendor (e.g. Dynatrace) might already have built-in auto-instrumentation for a certain library. In this case the vendor might want to decide (automatically or configuration-based) which of the implementations should be enabled or disabled. +This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) since having a concept of named tracers would automatically enable determining this semantic `component` property. ## Explanation @@ -36,13 +31,11 @@ In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a ## Internal details -By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing tracers and can decide whether or not to produce spans for a specific traced component and even change this behavior at runtime. - -In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer regardless of the name specified. This could be the case for implementations that do not want/need to enable or disable a tracer. +By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing tracers and which attributes they set in the resulting spans that are produced. -Alternatively, an implementation can provide different tracer instances per specified tracer name, thus being able to associate this tracer with the component being traced. This allows for the possibility to enable / disable a tracer based on a custom configuration. +In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer, regardless of the name specified as long as the name given for the tracer -## Trade-offs and mitigations +Alternatively, an implementation can provide different tracer instances per specified tracer name, thus being able to associate this tracer with the `component` being traced. ## Prior art and alternatives @@ -55,12 +48,11 @@ Alternatively, instead of having a `TracerFactory`, existing (global) tracers co Overall, this would not change a lot compared to the `TracerFactory` since the levels of indirection until producing an actual span are the same. - -## Open questions +Instead of setting the `component` property based on the given tracer names, those names could also be used as *prefixes* for produced span names (e.g. ``). However, with regard to data quality and semantic conventions, a dedicated `component` set on spans is probably preferred. ## Future possibilities -By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. +By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. ## Examples (of Tracer names) From 890fd79564010a4d1b2b6acfca6cdf2fefc8d8b0 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 17 Sep 2019 08:19:00 +0200 Subject: [PATCH 10/22] Update text/0000-named-tracers.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Christian Neumüller --- text/0000-named-tracers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index e0313ba2f..f0a0423ad 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -52,7 +52,7 @@ Instead of setting the `component` property based on the given tracer names, tho ## Future possibilities -By adapting this proposal, current implementations that do not honor the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. +By adapting this proposal, current implementations that do not make use of the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. ## Examples (of Tracer names) From c905402e75d112f932ac416e5ed203c5367fae04 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 17 Sep 2019 08:23:25 +0200 Subject: [PATCH 11/22] Update text/0000-named-tracers.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Christian Neumüller --- text/0000-named-tracers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index f0a0423ad..dc4b88ee0 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -60,7 +60,7 @@ Since tracer names describe the libraries which use the tracers, those names sho Examples (based on existing contribution libraries from OpenTracing and OpenCensus): -* _io.opentracing.contrib.spring.rabbitmq_ +* `io.opentracing.contrib.spring.rabbitmq` * _io.opentracing.contrib.jdbc_ * _io.opentracing.thrift_ * _io.opentracing.contrib.asynchttpclient_ From db2f617f8daef1f150c57b7e13d9c10e4424c69a Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 19 Sep 2019 16:29:43 +0200 Subject: [PATCH 12/22] Reworked this RFC based on feedback on GitHub. --- text/0000-named-tracers.md | 49 +++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index dc4b88ee0..680625ed7 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -2,65 +2,80 @@ **Status:** `proposed` -_Creating tracers using a factory mechanism and naming those tracers in accordance with the library that provides the instrumentation for a traced component._ +_Creating Tracers using a factory mechanism and naming those Tracers in accordance with the library that provides the instrumentation for a traced component._ ## Suggested reading * [Proposal: Tracer Components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) * [Global Instance discussions](https://github.com/open-telemetry/opentelemetry-specification/labels/global%20instance) +* [Proposal: Add a version resource](https://github.com/open-telemetry/oteps/pull/38) ## Motivation -Instead of having a global tracer singleton, every instrumentation library needs to create its own tracer, which also has a proper name that identifies the library / logical component that uses this tracer. If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. In this sense, this proposal suggests the introduction of a "semantic namespace" concept for tracers and the resulting spans. +The mechanism of "Named Tracers" proposed here is motivated by following scenarios: -The purpose of _Named Tracers_ is the ability to allow for associating an identifier (e.g. _"io.opentelemetry.contrib.mongodb"_) with a tracer. This further allows for logical and semantic coupling of this tracer and a certain technology or library (like _MongoDB_ in this example). Having named tracers enables support for having a dedicated property (component) depending on this name on a tracer that is different for different libraries. +* As a consumer of OpenTelemetry instrumentation libraries, there is currently no possibility of influencing the amount of the data produced by such libraries. Instrumentation libraries can easily "spam" backend systems, deliver bogus data or - in the worst case - crash or slow down applications. These problems might even occur suddenly in production environments caused by external factors such as increasing load or unexpected input data. -This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) since having a concept of named tracers would automatically enable determining this semantic `component` property. +* If a library hasn't implemented semantic conventions correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot associated with those instrumentation libraries later. +This proposal attempts to solve the stated problems by introducing the concept of _Named Tracers_. These associate a given identifier (e.g. _"io.opentelemetry.contrib.mongodb"_, _"1.0.0"_) with a Tracer and its produced Spans. + +Based on such an identifier, a Sampler could be implemented that discards Spans from certain libraries. Also, by providing a custom Exporter, Span data could be sanitized before it gets processed in a back-end system. However, this is beyond the scope of this proposal, which only provides the fundamental mechanisms. ## Explanation -From a user perspective, working with *Named Tracers* and *TracerFactories* is very similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. +From a user perspective, working with *Named Tracers* and *TracerFactories* is conceptually similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. + +Instead of using simple strings as an argument for creating new Tracers a Resource identifying an instrumentation library is used. Such resources must have a _version_ and _name_ labels (there could be semantic convention definitions for those). + ```java -Tracer tracer = OpenTelemetry.getTracerFactory().getTracer("io.opentelemetry.contrib.mongodb"); +// Create resource for given instrumentation library information (name + version) +Map libraryLabels = new HashMap<>(); +libraryLabels.put("name", "io.opentelemetry.contrib.mongodb"); +libraryLabels.put("version", "1.0.0"); +Resource libraryResource = Resource.create(libraryLabels); +// Create tracer for given instrumentation library. +Tracer tracer = OpenTelemetry.getTracerFactory().getTracer(libraryResource); ``` -In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a tracer instance. - +In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a Tracer instance. ## Internal details -By providing a TracerFactory and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing tracers and which attributes they set in the resulting spans that are produced. +By providing a `TracerFactory` and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing Tracers and which attributes they set in the resulting spans that are produced. -In the simplest case, an OpenTelemetry implementation can return a single instance for a requested tracer, regardless of the name specified as long as the name given for the tracer +The span API is extended with a `getLibraryResource` function that returns the resource associated with the Tracer that created the span. -Alternatively, an implementation can provide different tracer instances per specified tracer name, thus being able to associate this tracer with the `component` being traced. +If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. ## Prior art and alternatives -Alternatively, instead of having a `TracerFactory`, existing (global) tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. +This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) since having a concept of named Tracers would automatically enable determining this semantic `component` property. + + +Alternatively, instead of having a `TracerFactory`, existing (global) Tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java - TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder("io.opentelemetry.contrib.mongodb"); + TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder(libraryResource); Span span = traceComponent.spanBuilder("someMethod").startSpan(); ``` Overall, this would not change a lot compared to the `TracerFactory` since the levels of indirection until producing an actual span are the same. -Instead of setting the `component` property based on the given tracer names, those names could also be used as *prefixes* for produced span names (e.g. ``). However, with regard to data quality and semantic conventions, a dedicated `component` set on spans is probably preferred. +Instead of setting the `component` property based on the given Tracer names, those names could also be used as *prefixes* for produced span names (e.g. ``). However, with regard to data quality and semantic conventions, a dedicated `component` set on spans is probably preferred. ## Future possibilities -By adapting this proposal, current implementations that do not make use of the specified tracer name and provide a single global tracer, would not require much change. However they could change that behavior in future versions and provide more specific tracer implementations then. On the other side, if the mechanism of *Named Tracers* is not a part of the initial specification, such scenarios will be prevented and hard to retrofit in future version, should they be deemed necessary then. +Based on the Resource information identifying a Tracer these could be configured (enabled / disabled) programmatically or via external configuration sources (e.g. environment). ## Examples (of Tracer names) -Since tracer names describe the libraries which use the tracers, those names should be defined in a way that makes them as unique as possible. The name of the tracer should represent the identity of the library, class or package that provides the instrumentation. +Since Tracer names describe the libraries which use the Tracers, those names should be defined in a way that makes them as unique as possible. The name of the Tracer should represent the identity of the library, class or package that provides the instrumentation. Examples (based on existing contribution libraries from OpenTracing and OpenCensus): -* `io.opentracing.contrib.spring.rabbitmq` +* _io.opentracing.contrib.spring.rabbitmq_ * _io.opentracing.contrib.jdbc_ * _io.opentracing.thrift_ * _io.opentracing.contrib.asynchttpclient_ From c74770300aa0939542c0d24aabfbb7356a23e3b9 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Fri, 20 Sep 2019 13:19:29 +0200 Subject: [PATCH 13/22] Implement latest review suggestions --- text/0000-named-tracers.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 680625ed7..186556c27 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -14,11 +14,13 @@ _Creating Tracers using a factory mechanism and naming those Tracers in accordan The mechanism of "Named Tracers" proposed here is motivated by following scenarios: -* As a consumer of OpenTelemetry instrumentation libraries, there is currently no possibility of influencing the amount of the data produced by such libraries. Instrumentation libraries can easily "spam" backend systems, deliver bogus data or - in the worst case - crash or slow down applications. These problems might even occur suddenly in production environments caused by external factors such as increasing load or unexpected input data. +* For a consumer of OpenTelemetry instrumentation libraries, there is currently no possibility of influencing the amount of the data produced by such libraries. Instrumentation libraries can easily "spam" backend systems, deliver bogus data or - in the worst case - crash or slow down applications. These problems might even occur suddenly in production environments caused by external factors such as increasing load or unexpected input data. -* If a library hasn't implemented semantic conventions correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot associated with those instrumentation libraries later. +* If a library hasn't implemented [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md) correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot associated with those instrumentation libraries later. -This proposal attempts to solve the stated problems by introducing the concept of _Named Tracers_. These associate a given identifier (e.g. _"io.opentelemetry.contrib.mongodb"_, _"1.0.0"_) with a Tracer and its produced Spans. +This proposal attempts to solve the stated problems by introducing the concept of: + * _Named Tracers_ identified via a Resource (e.g. _"io.opentelemetry.contrib.mongodb"_, _"1.0.0"_) which is associated with the Tracer and the Spans it produces. + * A `TracerFactory` as the only means of creating a Tracer. Based on such an identifier, a Sampler could be implemented that discards Spans from certain libraries. Also, by providing a custom Exporter, Span data could be sanitized before it gets processed in a back-end system. However, this is beyond the scope of this proposal, which only provides the fundamental mechanisms. @@ -26,7 +28,7 @@ Based on such an identifier, a Sampler could be implemented that discards Spans From a user perspective, working with *Named Tracers* and *TracerFactories* is conceptually similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. -Instead of using simple strings as an argument for creating new Tracers a Resource identifying an instrumentation library is used. Such resources must have a _version_ and _name_ labels (there could be semantic convention definitions for those). +Instead of using plain strings as an argument for creating new Tracers a Resource identifying an instrumentation library is used. Such resources must have a _version_ and _name_ labels (there could be semantic convention definitions for those labels). Version values will follow the conventions proposed [here](https://github.com/open-telemetry/oteps/pull/38). ```java @@ -39,13 +41,13 @@ Resource libraryResource = Resource.create(libraryLabels); Tracer tracer = OpenTelemetry.getTracerFactory().getTracer(libraryResource); ``` -In a way, the `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a Tracer instance. +This `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a Tracer instance. ## Internal details By providing a `TracerFactory` and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing Tracers and which attributes they set in the resulting spans that are produced. -The span API is extended with a `getLibraryResource` function that returns the resource associated with the Tracer that created the span. +The SpanData class is extended with a `getLibraryResource` function that returns the resource associated with the Tracer that created the span. If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. From cfde11946cb7e10b10344c2160f31eb8ce536a84 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Sun, 22 Sep 2019 21:14:53 +0200 Subject: [PATCH 14/22] Removed formatting --- text/0000-named-tracers.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 186556c27..f3b1e2ee2 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -77,15 +77,15 @@ Since Tracer names describe the libraries which use the Tracers, those names sho Examples (based on existing contribution libraries from OpenTracing and OpenCensus): -* _io.opentracing.contrib.spring.rabbitmq_ -* _io.opentracing.contrib.jdbc_ -* _io.opentracing.thrift_ -* _io.opentracing.contrib.asynchttpclient_ -* _io.opencensus.contrib.http.servlet_ -* _io.opencensus.contrib.spring.sleuth.v1x_ -* _io.opencensus.contrib.http.jaxrs_ -* _github.com/opentracing-contrib/go-amqp_ (Go) -* _github.com/opentracing-contrib/go-grpc_ (Go) -* _OpenTracing.Contrib.NetCore.AspNetCore_ (.NET) -* _OpenTracing.Contrib.NetCore.EntityFrameworkCore_ (.NET) +* io.opentracing.contrib.spring.rabbitmq +* io.opentracing.contrib.jdbc +* io.opentracing.thrift +* io.opentracing.contrib.asynchttpclient +* io.opencensus.contrib.http.servlet +* io.opencensus.contrib.spring.sleuth.v1x +* io.opencesus.contrib.http.jaxrs +* github.com/opentracing-contrib/go-amqp (Go) +* github.com/opentracing-contrib/go-grpc (Go) +* OpenTracing.Contrib.NetCore.AspNetCore (.NET) +* OpenTracing.Contrib.NetCore.EntityFrameworkCore (.NET) From f83fb874e41ba6acf9ccbdac48095b998eccf0bb Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Tue, 24 Sep 2019 14:23:09 +0200 Subject: [PATCH 15/22] Re-introduce plain string factory and move Resource-based approach to alternatives --- text/0000-named-tracers.md | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index f3b1e2ee2..93069ad4d 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -19,7 +19,7 @@ The mechanism of "Named Tracers" proposed here is motivated by following scenari * If a library hasn't implemented [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md) correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot associated with those instrumentation libraries later. This proposal attempts to solve the stated problems by introducing the concept of: - * _Named Tracers_ identified via a Resource (e.g. _"io.opentelemetry.contrib.mongodb"_, _"1.0.0"_) which is associated with the Tracer and the Spans it produces. + * _Named Tracers_ identified via a name (e.g. _"io.opentelemetry.contrib.mongodb"_) and a version (e.g._"semver:1.0.0"_) which is associated with the Tracer and the Spans it produces. * A `TracerFactory` as the only means of creating a Tracer. Based on such an identifier, a Sampler could be implemented that discards Spans from certain libraries. Also, by providing a custom Exporter, Span data could be sanitized before it gets processed in a back-end system. However, this is beyond the scope of this proposal, which only provides the fundamental mechanisms. @@ -28,21 +28,22 @@ Based on such an identifier, a Sampler could be implemented that discards Spans From a user perspective, working with *Named Tracers* and *TracerFactories* is conceptually similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. -Instead of using plain strings as an argument for creating new Tracers a Resource identifying an instrumentation library is used. Such resources must have a _version_ and _name_ labels (there could be semantic convention definitions for those labels). Version values will follow the conventions proposed [here](https://github.com/open-telemetry/oteps/pull/38). +New Tracers can be created by providing the name and version of an instrumentation library. The version (following the convention proposed in https://github.com/open-telemetry/oteps/pull/38) is basically optional but *should* be supplied since only this information enables following scenarios: +* Only a specific range of versions of a given instrumentation library need to be suppressed, while other versions are allowed (e.g. due to a bug in those specific versions). +* Go modules allow multiple versions of the same middleware in a single build so those need to be determined at runtime. +Instead of using plain strings as an argument for creating new Tracers a Resource identifying an instrumentation library is used. Such resources must have a _version_ and _name_ labels (there could be semantic convention definitions for those labels). Version values will follow the conventions proposed [here](https://github.com/open-telemetry/oteps/pull/38). ```java -// Create resource for given instrumentation library information (name + version) -Map libraryLabels = new HashMap<>(); -libraryLabels.put("name", "io.opentelemetry.contrib.mongodb"); -libraryLabels.put("version", "1.0.0"); -Resource libraryResource = Resource.create(libraryLabels); -// Create tracer for given instrumentation library. -Tracer tracer = OpenTelemetry.getTracerFactory().getTracer(libraryResource); +// Create a tracer for given instrumentation library in a specific version. +Tracer tracer = OpenTelemetry.getTracerFactory().getTracer("io.opentelemetry.contrib.mongodb", "semver:1.0.0"); ``` This `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a Tracer instance. +If no tracer name (null or empty string) is specified, following the suggestions in ["error handling proposal"](open-telemetry/opentelemetry-specification#153), a "smart default" will be applied and a default tracer implementation is returned. + + ## Internal details By providing a `TracerFactory` and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing Tracers and which attributes they set in the resulting spans that are produced. @@ -55,7 +56,6 @@ If there are two different instrumentation libraries for the same technology (e. This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) since having a concept of named Tracers would automatically enable determining this semantic `component` property. - Alternatively, instead of having a `TracerFactory`, existing (global) Tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java @@ -67,10 +67,24 @@ Overall, this would not change a lot compared to the `TracerFactory` since the l Instead of setting the `component` property based on the given Tracer names, those names could also be used as *prefixes* for produced span names (e.g. ``). However, with regard to data quality and semantic conventions, a dedicated `component` set on spans is probably preferred. +Instead of using plain strings as an argument for creating new Tracers, a `Resource` identifying an instrumentation library could be used. Such resources must have a _version_ and a _name_ label (there could be semantic convention definitions for those labels). This implementation alternative mainly depends on the availability of the `Resource` data type on an API level (see https://github.com/open-telemetry/opentelemetry-specification/pull/254). + +```java +// Create resource for given instrumentation library information (name + version) +Map libraryLabels = new HashMap<>(); +libraryLabels.put("name", "io.opentelemetry.contrib.mongodb"); +libraryLabels.put("version", "1.0.0"); +Resource libraryResource = Resource.create(libraryLabels); +// Create tracer for given instrumentation library. +Tracer tracer = OpenTelemetry.getTracerFactory().getTracer(libraryResource); +``` + ## Future possibilities Based on the Resource information identifying a Tracer these could be configured (enabled / disabled) programmatically or via external configuration sources (e.g. environment). +Based on this proposal, other "signal producers" (i.e. metrics and logs) can use the same or a similar creation approach. + ## Examples (of Tracer names) Since Tracer names describe the libraries which use the Tracers, those names should be defined in a way that makes them as unique as possible. The name of the Tracer should represent the identity of the library, class or package that provides the instrumentation. From 8a882f2135df3c67f92762805c62007d7396eb5c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 24 Sep 2019 08:36:13 -0700 Subject: [PATCH 16/22] Use ` to format the names in the examples. --- text/0000-named-tracers.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 93069ad4d..a304e45d2 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -91,15 +91,14 @@ Since Tracer names describe the libraries which use the Tracers, those names sho Examples (based on existing contribution libraries from OpenTracing and OpenCensus): -* io.opentracing.contrib.spring.rabbitmq -* io.opentracing.contrib.jdbc -* io.opentracing.thrift -* io.opentracing.contrib.asynchttpclient -* io.opencensus.contrib.http.servlet -* io.opencensus.contrib.spring.sleuth.v1x -* io.opencesus.contrib.http.jaxrs -* github.com/opentracing-contrib/go-amqp (Go) -* github.com/opentracing-contrib/go-grpc (Go) -* OpenTracing.Contrib.NetCore.AspNetCore (.NET) -* OpenTracing.Contrib.NetCore.EntityFrameworkCore (.NET) - +* `io.opentracing.contrib.spring.rabbitmq` +* `io.opentracing.contrib.jdbc` +* `io.opentracing.thrift` +* `io.opentracing.contrib.asynchttpclient` +* `io.opencensus.contrib.http.servlet` +* `io.opencensus.contrib.spring.sleuth.v1x` +* `io.opencesus.contrib.http.jaxrs` +* `github.com/opentracing-contrib/go-amqp` (Go) +* `github.com/opentracing-contrib/go-grpc` (Go) +* `OpenTracing.Contrib.NetCore.AspNetCore` (.NET) +* `OpenTracing.Contrib.NetCore.EntityFrameworkCore` (.NET) From 617f5f80ae95b373f70fe8487bdc15c989e98813 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Wed, 25 Sep 2019 11:09:57 +0200 Subject: [PATCH 17/22] Fix typo and broken link --- text/0000-named-tracers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 93069ad4d..43ba4f646 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -16,7 +16,7 @@ The mechanism of "Named Tracers" proposed here is motivated by following scenari * For a consumer of OpenTelemetry instrumentation libraries, there is currently no possibility of influencing the amount of the data produced by such libraries. Instrumentation libraries can easily "spam" backend systems, deliver bogus data or - in the worst case - crash or slow down applications. These problems might even occur suddenly in production environments caused by external factors such as increasing load or unexpected input data. -* If a library hasn't implemented [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md) correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot associated with those instrumentation libraries later. +* If a library hasn't implemented [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md) correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot be associated with those instrumentation libraries later. This proposal attempts to solve the stated problems by introducing the concept of: * _Named Tracers_ identified via a name (e.g. _"io.opentelemetry.contrib.mongodb"_) and a version (e.g._"semver:1.0.0"_) which is associated with the Tracer and the Spans it produces. @@ -41,7 +41,7 @@ Tracer tracer = OpenTelemetry.getTracerFactory().getTracer("io.opentelemetry.con This `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a Tracer instance. -If no tracer name (null or empty string) is specified, following the suggestions in ["error handling proposal"](open-telemetry/opentelemetry-specification#153), a "smart default" will be applied and a default tracer implementation is returned. +If no tracer name (null or empty string) is specified, following the suggestions in ["error handling proposal"](https://github.com/open-telemetry/opentelemetry-specification/pull/153), a "smart default" will be applied and a default tracer implementation is returned. ## Internal details From 005cfa2e40d346140134fbaed2f18524985414bb Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 26 Sep 2019 10:17:29 +0200 Subject: [PATCH 18/22] Extended the OTEP to included Metrics as well. --- text/0000-named-tracers.md | 48 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index ce4a02e47..d84747a0a 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -1,8 +1,8 @@ -# Named Tracers +# Named Tracers and Meters **Status:** `proposed` -_Creating Tracers using a factory mechanism and naming those Tracers in accordance with the library that provides the instrumentation for a traced component._ +_Creating Tracers and Meters using a factory mechanism and naming those Tracers / Meters in accordance with the library that provides the instrumentation for those components._ ## Suggested reading @@ -12,43 +12,45 @@ _Creating Tracers using a factory mechanism and naming those Tracers in accordan ## Motivation -The mechanism of "Named Tracers" proposed here is motivated by following scenarios: +The mechanism of "Named Tracers and Meters" proposed here is motivated by following scenarios: * For a consumer of OpenTelemetry instrumentation libraries, there is currently no possibility of influencing the amount of the data produced by such libraries. Instrumentation libraries can easily "spam" backend systems, deliver bogus data or - in the worst case - crash or slow down applications. These problems might even occur suddenly in production environments caused by external factors such as increasing load or unexpected input data. -* If a library hasn't implemented [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md) correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans cannot be associated with those instrumentation libraries later. +* If a library hasn't implemented [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md) correctly or those conventions change over time, it's currently hard to interpret and sanitize these data selectively. The produced Spans or Metrics cannot be associated with those instrumentation libraries later. This proposal attempts to solve the stated problems by introducing the concept of: - * _Named Tracers_ identified via a name (e.g. _"io.opentelemetry.contrib.mongodb"_) and a version (e.g._"semver:1.0.0"_) which is associated with the Tracer and the Spans it produces. - * A `TracerFactory` as the only means of creating a Tracer. + * _Named Tracers and Meters_ identified via a **name** (e.g. _"io.opentelemetry.contrib.mongodb"_) and a **version** (e.g._"semver:1.0.0"_) which is associated with the Tracer / Meter and the Spans / Metrics it produces. + * A `TracerFactory` / `MeterFactory` as the only means of creating a Tracer or Meter. -Based on such an identifier, a Sampler could be implemented that discards Spans from certain libraries. Also, by providing a custom Exporter, Span data could be sanitized before it gets processed in a back-end system. However, this is beyond the scope of this proposal, which only provides the fundamental mechanisms. +Based on such an identifier, a Sampler could be implemented that discards Spans or Metrics from certain libraries. Also, by providing custom Exporters, Span or Metric data could be sanitized before it gets processed in a back-end system. However, this is beyond the scope of this proposal, which only provides the fundamental mechanisms. ## Explanation -From a user perspective, working with *Named Tracers* and *TracerFactories* is conceptually similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific 'Tracer' objects through a 'TracerFactory'. +From a user perspective, working with *Named Tracers / Meters* and `TracerFactory` / `MeterFactory` is conceptually similar to how e.g. the [Java logging API](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)) and logging frameworks like [log4j](https://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html) work. In analogy to requesting Logger objects through LoggerFactories, a tracing library would create specific Tracer / Meter objects through a TracerFactory / MeterFactory. -New Tracers can be created by providing the name and version of an instrumentation library. The version (following the convention proposed in https://github.com/open-telemetry/oteps/pull/38) is basically optional but *should* be supplied since only this information enables following scenarios: +New Tracers or Meters can be created by providing the name and version of an instrumentation library. The version (following the convention proposed in https://github.com/open-telemetry/oteps/pull/38) is basically optional but *should* be supplied since only this information enables following scenarios: * Only a specific range of versions of a given instrumentation library need to be suppressed, while other versions are allowed (e.g. due to a bug in those specific versions). * Go modules allow multiple versions of the same middleware in a single build so those need to be determined at runtime. -Instead of using plain strings as an argument for creating new Tracers a Resource identifying an instrumentation library is used. Such resources must have a _version_ and _name_ labels (there could be semantic convention definitions for those labels). Version values will follow the conventions proposed [here](https://github.com/open-telemetry/oteps/pull/38). - ```java -// Create a tracer for given instrumentation library in a specific version. +// Create a tracer/meter for a given instrumentation library in a specific version. Tracer tracer = OpenTelemetry.getTracerFactory().getTracer("io.opentelemetry.contrib.mongodb", "semver:1.0.0"); +Meter meter = OpenTelemetry.getMeterFactory().getMeter("io.opentelemetry.contrib.mongodb", "semver:1.0.0"); ``` -This `TracerFactory` replaces the global `Tracer` singleton object as a ubiquitous point to request a Tracer instance. +These factories (`TracerFactory` and `MeterFactory`) replace the global `Tracer` / `Meter` singleton objects as ubiquitous points to request Tracer and Meter instances. + + The *name* used to create a Tracer or Meter explicitly refers to the *instrumentation* libraries (also referred to as *integrations*) and not the instrumented libraries. These instrumentation libraries could be libraries developed in an OpenTelemetry repository, a 3rd party implementation or even auto-injected code (see [Open Telemetry Without Manual Instrumentation OTEP](https://github.com/open-telemetry/oteps/blob/master/text/0001-telemetry-without-manual-instrumentation.md)). See also the examples for identifiers at the end. +If a library (or application) has instrumentation built-in, it is of course both the instrumenting and instrumented library and can pass its own name here. In all other cases (and to distinguish them from that case), the distinction between instrumenting and instrumented library is very important. For example, if an HTTP library `com.example.http` is instrumented by either `io.opentelemetry.contrib.examplehttp` or `com.example.company.examplehttpintegration`, then it is important that the Tracer is not named `com.example.http` but after the actual instrumentation library. -If no tracer name (null or empty string) is specified, following the suggestions in ["error handling proposal"](https://github.com/open-telemetry/opentelemetry-specification/pull/153), a "smart default" will be applied and a default tracer implementation is returned. +If no name (null or empty string) is specified, following the suggestions in ["error handling proposal"](https://github.com/open-telemetry/opentelemetry-specification/pull/153), a "smart default" will be applied and a default Tracer / Meter implementation is returned. ## Internal details -By providing a `TracerFactory` and *Named Tracers*, a vendor or OpenTelemetry implementation gains more flexibility in providing Tracers and which attributes they set in the resulting spans that are produced. +By providing a `TracerFactory` / `MeterFactory` and *Named Tracers / Meters*, a vendor or OpenTelemetry implementation gains more flexibility in providing Tracers and Meters and which attributes they set in the resulting Spans and Metrics that are produced. -The SpanData class is extended with a `getLibraryResource` function that returns the resource associated with the Tracer that created the span. +On an SDK level, the SpanData class and its Metrics counterpart are extended with a `getLibraryResource` function that returns the resource associated with the Tracer / Meter that created it. If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. @@ -59,8 +61,8 @@ This proposal originates from an `opentelemetry-specification` proposal on [comp Alternatively, instead of having a `TracerFactory`, existing (global) Tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java - TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder(libraryResource); - Span span = traceComponent.spanBuilder("someMethod").startSpan(); +TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder(libraryResource); +Span span = traceComponent.spanBuilder("someMethod").startSpan(); ``` Overall, this would not change a lot compared to the `TracerFactory` since the levels of indirection until producing an actual span are the same. @@ -79,15 +81,17 @@ Resource libraryResource = Resource.create(libraryLabels); Tracer tracer = OpenTelemetry.getTracerFactory().getTracer(libraryResource); ``` +Those given alternatives could be applied to Meters and Metrics in the same way. + ## Future possibilities -Based on the Resource information identifying a Tracer these could be configured (enabled / disabled) programmatically or via external configuration sources (e.g. environment). +Based on the Resource information identifying a Tracer or Meter these could be configured (enabled / disabled) programmatically or via external configuration sources (e.g. environment). -Based on this proposal, other "signal producers" (i.e. metrics and logs) can use the same or a similar creation approach. +Based on this proposal, future "signal producers" (i.e. logs) can use the same or a similar creation approach. -## Examples (of Tracer names) +## Examples (of Tracer and Meter names) -Since Tracer names describe the libraries which use the Tracers, those names should be defined in a way that makes them as unique as possible. The name of the Tracer should represent the identity of the library, class or package that provides the instrumentation. +Since Tracer and Meter names describe the libraries which use those Tracers and Meters, their namess should be defined in a way that makes them as unique as possible. The name of the Tracer / Meter should represent the identity of the library, class or package that provides the instrumentation. Examples (based on existing contribution libraries from OpenTracing and OpenCensus): From 124bc830315785e8c0283b6ed995742a49196cb4 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 26 Sep 2019 13:34:49 +0200 Subject: [PATCH 19/22] Update text/0000-named-tracers.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Christian Neumüller --- text/0000-named-tracers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index d84747a0a..2a6cd9c34 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -40,7 +40,7 @@ Meter meter = OpenTelemetry.getMeterFactory().getMeter("io.opentelemetry.contrib These factories (`TracerFactory` and `MeterFactory`) replace the global `Tracer` / `Meter` singleton objects as ubiquitous points to request Tracer and Meter instances. - The *name* used to create a Tracer or Meter explicitly refers to the *instrumentation* libraries (also referred to as *integrations*) and not the instrumented libraries. These instrumentation libraries could be libraries developed in an OpenTelemetry repository, a 3rd party implementation or even auto-injected code (see [Open Telemetry Without Manual Instrumentation OTEP](https://github.com/open-telemetry/oteps/blob/master/text/0001-telemetry-without-manual-instrumentation.md)). See also the examples for identifiers at the end. + The *name* used to create a Tracer or Meter must identify the *instrumentation* libraries (also referred to as *integrations*) and not the instrumented libraries. These instrumentation libraries could be libraries developed in an OpenTelemetry repository, a 3rd party implementation or even auto-injected code (see [Open Telemetry Without Manual Instrumentation OTEP](https://github.com/open-telemetry/oteps/blob/master/text/0001-telemetry-without-manual-instrumentation.md)). See also the examples for identifiers at the end. If a library (or application) has instrumentation built-in, it is of course both the instrumenting and instrumented library and can pass its own name here. In all other cases (and to distinguish them from that case), the distinction between instrumenting and instrumented library is very important. For example, if an HTTP library `com.example.http` is instrumented by either `io.opentelemetry.contrib.examplehttp` or `com.example.company.examplehttpintegration`, then it is important that the Tracer is not named `com.example.http` but after the actual instrumentation library. If no name (null or empty string) is specified, following the suggestions in ["error handling proposal"](https://github.com/open-telemetry/opentelemetry-specification/pull/153), a "smart default" will be applied and a default Tracer / Meter implementation is returned. From f618455b5aac655e5a1fdce902ffb26d780c77d9 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 26 Sep 2019 13:34:58 +0200 Subject: [PATCH 20/22] Update text/0000-named-tracers.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Christian Neumüller --- text/0000-named-tracers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index 2a6cd9c34..cd67a38d3 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -41,7 +41,7 @@ Meter meter = OpenTelemetry.getMeterFactory().getMeter("io.opentelemetry.contrib These factories (`TracerFactory` and `MeterFactory`) replace the global `Tracer` / `Meter` singleton objects as ubiquitous points to request Tracer and Meter instances. The *name* used to create a Tracer or Meter must identify the *instrumentation* libraries (also referred to as *integrations*) and not the instrumented libraries. These instrumentation libraries could be libraries developed in an OpenTelemetry repository, a 3rd party implementation or even auto-injected code (see [Open Telemetry Without Manual Instrumentation OTEP](https://github.com/open-telemetry/oteps/blob/master/text/0001-telemetry-without-manual-instrumentation.md)). See also the examples for identifiers at the end. -If a library (or application) has instrumentation built-in, it is of course both the instrumenting and instrumented library and can pass its own name here. In all other cases (and to distinguish them from that case), the distinction between instrumenting and instrumented library is very important. For example, if an HTTP library `com.example.http` is instrumented by either `io.opentelemetry.contrib.examplehttp` or `com.example.company.examplehttpintegration`, then it is important that the Tracer is not named `com.example.http` but after the actual instrumentation library. +If a library (or application) has instrumentation built-in, it is both the instrumenting and instrumented library and should pass its own name here. In all other cases (and to distinguish them from that case), the distinction between instrumenting and instrumented library is very important. For example, if an HTTP library `com.example.http` is instrumented by either `io.opentelemetry.contrib.examplehttp` or `com.example.company.examplehttpintegration`, then it is important that the Tracer is not named `com.example.http` but after the actual instrumentation library. If no name (null or empty string) is specified, following the suggestions in ["error handling proposal"](https://github.com/open-telemetry/opentelemetry-specification/pull/153), a "smart default" will be applied and a default Tracer / Meter implementation is returned. From 595f19dd70e34730f989e98177f0a0b88d2d58ff Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 26 Sep 2019 13:41:16 +0200 Subject: [PATCH 21/22] Implement latest feedback. --- text/0000-named-tracers.md | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/text/0000-named-tracers.md b/text/0000-named-tracers.md index cd67a38d3..7b72633b2 100644 --- a/text/0000-named-tracers.md +++ b/text/0000-named-tracers.md @@ -45,6 +45,24 @@ If a library (or application) has instrumentation built-in, it is both the instr If no name (null or empty string) is specified, following the suggestions in ["error handling proposal"](https://github.com/open-telemetry/opentelemetry-specification/pull/153), a "smart default" will be applied and a default Tracer / Meter implementation is returned. +### Examples (of Tracer and Meter names) + +Since Tracer and Meter names describe the libraries which use those Tracers and Meters, their names should be defined in a way that makes them as unique as possible. +The name of the Tracer / Meter should represent the identity of the library, class or package that provides the instrumentation. + +Examples (based on existing contribution libraries from OpenTracing and OpenCensus): + +* `io.opentracing.contrib.spring.rabbitmq` +* `io.opentracing.contrib.jdbc` +* `io.opentracing.thrift` +* `io.opentracing.contrib.asynchttpclient` +* `io.opencensus.contrib.http.servlet` +* `io.opencensus.contrib.spring.sleuth.v1x` +* `io.opencesus.contrib.http.jaxrs` +* `github.com/opentracing-contrib/go-amqp` (Go) +* `github.com/opentracing-contrib/go-grpc` (Go) +* `OpenTracing.Contrib.NetCore.AspNetCore` (.NET) +* `OpenTracing.Contrib.NetCore.EntityFrameworkCore` (.NET) ## Internal details @@ -52,8 +70,6 @@ By providing a `TracerFactory` / `MeterFactory` and *Named Tracers / Meters*, a On an SDK level, the SpanData class and its Metrics counterpart are extended with a `getLibraryResource` function that returns the resource associated with the Tracer / Meter that created it. -If there are two different instrumentation libraries for the same technology (e.g. MongoDb), these instrumentation libraries should have distinct names. - ## Prior art and alternatives This proposal originates from an `opentelemetry-specification` proposal on [components](https://github.com/open-telemetry/opentelemetry-specification/issues/10) since having a concept of named Tracers would automatically enable determining this semantic `component` property. @@ -61,7 +77,7 @@ This proposal originates from an `opentelemetry-specification` proposal on [comp Alternatively, instead of having a `TracerFactory`, existing (global) Tracers could return additional indirection objects (called e.g. `TraceComponent`), which would be able to produce spans for specifically named traced components. ```java -TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder(libraryResource); +TraceComponent traceComponent = OpenTelemetry.Tracing.getTracer().componentBuilder("io.opentelemetry.contrib.mongodb", "semver:1.0.0"); Span span = traceComponent.spanBuilder("someMethod").startSpan(); ``` @@ -89,20 +105,3 @@ Based on the Resource information identifying a Tracer or Meter these could be c Based on this proposal, future "signal producers" (i.e. logs) can use the same or a similar creation approach. -## Examples (of Tracer and Meter names) - -Since Tracer and Meter names describe the libraries which use those Tracers and Meters, their namess should be defined in a way that makes them as unique as possible. The name of the Tracer / Meter should represent the identity of the library, class or package that provides the instrumentation. - -Examples (based on existing contribution libraries from OpenTracing and OpenCensus): - -* `io.opentracing.contrib.spring.rabbitmq` -* `io.opentracing.contrib.jdbc` -* `io.opentracing.thrift` -* `io.opentracing.contrib.asynchttpclient` -* `io.opencensus.contrib.http.servlet` -* `io.opencensus.contrib.spring.sleuth.v1x` -* `io.opencesus.contrib.http.jaxrs` -* `github.com/opentracing-contrib/go-amqp` (Go) -* `github.com/opentracing-contrib/go-grpc` (Go) -* `OpenTracing.Contrib.NetCore.AspNetCore` (.NET) -* `OpenTracing.Contrib.NetCore.EntityFrameworkCore` (.NET) From 995819d583e3ea3e10f86d178e613d4633026777 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 26 Sep 2019 08:08:32 -0700 Subject: [PATCH 22/22] Rename 0000-named-tracers.md to 0016-named-tracers.md --- text/{0000-named-tracers.md => 0016-named-tracers.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename text/{0000-named-tracers.md => 0016-named-tracers.md} (100%) diff --git a/text/0000-named-tracers.md b/text/0016-named-tracers.md similarity index 100% rename from text/0000-named-tracers.md rename to text/0016-named-tracers.md