-
Notifications
You must be signed in to change notification settings - Fork 846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First cut at a Zipkin Span Exporter #1106
First cut at a Zipkin Span Exporter #1106
Conversation
@adriancole would love your eyes on this one! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I think I saw this code when in census, just a few clarifications
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Outdated
Show resolved
Hide resolved
} | ||
Status status = spanData.getStatus(); | ||
if (status != null) { | ||
spanBuilder.putTag(STATUS_CODE, status.getCanonicalCode().toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a chance this can be an HTTP code? or is this RPC only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the statuses are defined here:
public final class Status { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this appears RPC status, can you confirm HTTP is not mapped to this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can confirm that HTTP is definitely mapped to these: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#status
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Show resolved
Hide resolved
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Show resolved
Hide resolved
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Outdated
Show resolved
Hide resolved
.../zipkin/src/test/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfigurationTest.java
Show resolved
Hide resolved
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some README help
Not an expert of Zipkin, but overall looks great @jkwatson You need to add the new artifact to |
@adriancole I think I got all of your questions/cleanups addressed but the one that I don't understand. Can you take a look? |
Codecov Report
@@ Coverage Diff @@
## master #1106 +/- ##
============================================
- Coverage 85.56% 85.51% -0.06%
- Complexity 1097 1134 +37
============================================
Files 139 141 +2
Lines 4136 4245 +109
Branches 372 392 +20
============================================
+ Hits 3539 3630 +91
- Misses 454 463 +9
- Partials 143 152 +9
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most important feedback is to not leak tentative tag keys unless they are already in use. The suggestion is to use only "grpc.status_code" and "error" for now.
This gives time to understand the nature of this, how widely used these status codes are etc, prior to adding load to people's indexes. Someone who wants to add more tags meanwhile can do that by wrapping this exporter in another one that adds a bunch of other tags.
...ters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java
Outdated
Show resolved
Hide resolved
ZipkinExporterConfiguration() {} | ||
|
||
/** | ||
* Returns the service name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing the project has rules that require filler javadoc statements? These don't seem to add value otherwise, except for maybe the version once it is correct. If you want better descriptions let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was directly copied from the opencensus exporter. Better descriptions would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And, I agree with you on the usefulness of much of the javadoc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in that case, is it within the rules of the project to remove them? Less fluff to write, and we can focus on single-sentence explanations. lemme know and then I'll respond accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll poke at this tomorrow. I'm not 100% sure of the rules, myself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like javadoc is not required, but if it's there, it needs to be complete and well-formed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I'll give you some text in another review round
...ters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java
Outdated
Show resolved
Hide resolved
...ters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java
Outdated
Show resolved
Hide resolved
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Outdated
Show resolved
Hide resolved
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Outdated
Show resolved
Hide resolved
exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java
Outdated
Show resolved
Hide resolved
exporters/zipkin/src/test/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporterTest.java
Show resolved
Hide resolved
// The naming follows Zipkin convention. As an example see: | ||
// https://github.com/openzipkin/brave/blob/eee993f998ae57b08644cc357a6d478827428710/instrumentation/http/src/main/java/brave/http/HttpTags.java | ||
// Note: these 3 fields are non-private for testing | ||
static final String STATUS_CODE = "grpc.status_code"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jkwatson PS I was assuming grpc "only" sets status vs adding a different tag also like "rpc.status" or "grpc.status" attribute per https://github.com/open-telemetry/opentelemetry-specification/blob/bfb060b23113ba9af492f8c63dd89ecfc500810b/specification/trace/semantic_conventions/rpc.md#status
In this case, I think the logic below can be simplified.. only when the mandatory "rpc.service" attribute exists, set "grpc.status_code" as we aren't likely to use the status values for any other reason.
The follow-up comment can refer to openzipkin/brave#999 which is likely to have the outcome of setting a tag like "rpc.status" (not yet decided) when the status is not OK. That is assuming there's no heuristic way to identify if the service in otel is grpc or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool. I think I've got it in the right shape now!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here ya go.
Glad I looked at this again (and you have patience for it) Noticed 2 glitches
- v2Url is non conventional and misleading.. replace with "endpoint"
SpanBytesEncoder
is unnecessarily narrow. Replace withBytesEncoder<Span>
* @return the service name. | ||
* @since 0.4.0 | ||
*/ | ||
public abstract String getServiceName(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete need to expose this as it is conditional anyway by marking package private (delete javadoc)
* @return the Zipkin V2 URL. | ||
* @since 0.4.0 | ||
*/ | ||
public abstract String getV2Url(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete need to expose this as it is conditional anyway by marking package private (delete javadoc)
* @return the Zipkin sender. | ||
* @since 0.4.0 | ||
*/ | ||
@Nullable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this actually nullable? or would this just be UrlSender by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can delete the javadoc by making this package private..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. This isn't actually nullable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BUT, autovalue needs it to be marked as such so that the builder will let me check to see if it's been set. 🤦
* @return this Builder instance. | ||
* @since 0.4.0 | ||
*/ | ||
public abstract Builder setServiceName(String serviceName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From brave. (PS you will very likely end up needing localIP override. implicit lookups are a nice default, but users set this to the well-known-address sometimes.
/**
* Label of the remote node in the service graph, such as "favstar". Avoid names with variables
* or unique identifiers embedded. Defaults to "unknown".
*
* <p>This is a primary label for trace lookup and aggregation, so it should be intuitive and
* consistent. Many use a name from service discovery.
*/
*/ | ||
@AutoValue | ||
@Immutable | ||
public abstract class ZipkinExporterConfiguration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider adding a static factory method to simplify this.
ex
/**
* Builds a HTTP exporter for <a href="https://zipkin.io/zipkin-api/#/">Zipkin V2</a> format.
*
* @param endpoint See {@link Builder#setEndpoint(String)}, ex. "http://zipkinhost:9411/api/v2/spans".
*/
public static ZipkinExporterConfiguration create(String endpoint) {
... newbuilder.endpoint().build()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact.. if you do this, you can probably get out of the complex statements in the builder. remove the "endpoint" variant, and require anyone using the builder to supply their own sender and encoder. SOOO much simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would you have an overload for the serviceName
, or just require people who want to set that to use the builder directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this out, including the serviceName
option. Let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the local service name is still not a otel concept right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think(?) this is the service.name
resource attribute: https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/resource/semantic_conventions#service
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the same thing as the Resource service.name
, then that is a property that is available to the exporter via the Resource attached to the SpanData
instance. It's not generally something you configure at the exporter level, at least not from what I've seen so far.
...ters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java
Outdated
Show resolved
Hide resolved
public abstract Builder setV2Url(String v2Url); | ||
|
||
/** | ||
* Sets the Zipkin sender. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implements the client side of the span transport. Defaults to {@link UrlConnectionSender}.
* @return this Builder instance | ||
* @since 0.4.0 | ||
*/ | ||
public abstract Builder setEncoder(SpanBytesEncoder encoder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to BytesEncoder<Span>
as otherwise you'll break non-zipkin formats like https://github.com/openzipkin/zipkin-gcp/blob/master/sender-stackdriver/src/main/java/zipkin2/reporter/stackdriver/StackdriverEncoder.java
(ack that they would make their own exporter, but anyway no need to narrow the type)
* Sets the {@link SpanBytesEncoder}. | ||
* | ||
* @param encoder the {@code SpanBytesEncoder}. | ||
* @return this Builder instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @return this Builder instance | |
* @return this Builder instance | |
* @see SpanBytesEncoder |
public abstract Builder setSender(Sender sender); | ||
|
||
/** | ||
* Sets the {@link SpanBytesEncoder}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry John. I suspect hat otel doesnt currently have a standard tag or property for the service name so it would only end up valid if also specified here. this is a but of a dilemma but can be punted. fwiw I have noticed many vendors and certainly jaeger have a local service name property. if this could be back filled into the core api then the factory here would be far simpler as it would just note this inherits the service name property into the local endpoint by default. this is far better than "unknown" eventhough a builder override should still be possible for that. assuming there isnt a standard property the way i would handle it is newBuilder(sender) and newBuilder(endpoint) overloads vs a create method that has two strings. once the model can have a standard way to get the local service name we can add the simplified factory method then. wdyt? |
So, as mentioned above, the Thoughts on dropping the local endpoint code, and just attaching the service name provided via the |
We use a model instead of tags for this, if we don't map anything, not just search but aggregations won't work. IOTW "service.name" as far as I can understand would map to localEndpoint.serviceName (and should not also be added as a tag as that wastes overhead). If that's in, it sounds fine to take out builder-related code for setting a default endpoint. In brave, for example, we just use builder stuff as a default anyway. You can expect a request at some point to override this due to well-known historical problems with making service span-scoped as opposed to local-root scoped *. However, sounds fine to me to do that later provided
|
ps I suppose another way vs a setting here could be that just a decorating span exporter. I suspect that the random service name problem, which wreaks havoc on dependency trees, search indexes etc, will be not just limited to Zipkin. If there's no way to default the tracer (maybe there is) an example (or institutional knowledge) of a wrapping SpanExporter that overrides the service tag would also work fine once folks see everything broken. |
TL;DR; minimum: map "service.name" -> localEndpoint.serviceName and drop the tag the inconsistent "service.name" problem is out of scope for the exporter anyway, and should be watched carefully, especially if never set. once minimum is in, it is time to move past the "eyeball code" phase into seeing it work. Basically whatever simple app you have that generates a trace across two services, invoke that and either paste a screenshot of lens, or the actual trace json sent from both the nodes. I can verify personally on behalf of the team, and you can sg? |
Once we get this merged, I can point a test service at New Relic's zipkin span ingest and see how it all looks. |
ok. I got rid of the exporter-level Endpoint code, and just use the Resource to populate an Endpoint.serviceName . This is probably down the bare-bones implementation at this point, which is probably a good starting point. Additional features can definitely be requested & added in the future! |
} | ||
|
||
static Span generateSpan(SpanData spanData) { | ||
Endpoint endpoint = EMPTY_ENDPOINT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please don't add an empty endpoint
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The zipkin API just sets null when you pass in an empty one. Are you saying that if we can't make an endpoint, we shouldn't send spans?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is distracting to set an empty endpoint for reasons including what you mentioned. that's the main point. just call the endpoint builder when you have one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the longer answer is that it would be easy for this code to drift to adding more data into the span for no reason. For example, if you change codec later, it would likely serialize "localEndpoint": {}
which is useless overhead, plus adding empty is already confusing.
hope this makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to add a service name fallback
static Span generateSpan(SpanData spanData) { | ||
Endpoint endpoint = EMPTY_ENDPOINT; | ||
Map<String, AttributeValue> resourceAttributes = spanData.getResource().getAttributes(); | ||
AttributeValue serviceNameValue = resourceAttributes.get("service.name"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
opentelemetry-java/sdk/src/main/java/io/opentelemetry/sdk/resources/ResourceConstants.java
Line 32 in 6330901
public static final String SERVICE_NAME = "service.name"; |
|
||
static Span generateSpan(SpanData spanData) { | ||
Endpoint endpoint = EMPTY_ENDPOINT; | ||
Map<String, AttributeValue> resourceAttributes = spanData.getResource().getAttributes(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand where this is coming from and the discussions around it, but I still haven't heard any reason to believe "service.name" would be set by default. I suspect that's why the jaeger export was written to have a gear for this.
Line 85 in c32c776
.setServiceName(SERVICE_NAME) |
Recall the main thing we've done recently is dodge a 2 arg factory method. To make data unqueryable is a more bitter pill than just deleting that discussion and having no factory methods. Basically if this is all about the single arg factory method, it really isn't worth it to cause damage.
A different point.. the whole thing started about the choice between endpoint and a different sender. This is not a complex enough problem to make us want to damage the data model by removing something more important for. If it is, simply remove the endpoint arg to "buy us" a service name one.
If it isn't a problem to have three methods (one for service, one for endpoint shortcut and one for the sender that uses) do an overload? Ex we do similarly in our okhttp sender (also autovalue)
/**
* No default. The POST URL for zipkin's <a href="https://zipkin.io/zipkin-api/#/">v2 api</a>,
* usually "http://zipkinhost:9411/api/v2/spans"
*/
// customizable so that users can re-map /api/v2/spans ex for browser-originated traces
public Builder endpoint(String endpoint) {
if (endpoint == null) throw new NullPointerException("endpoint == null");
HttpUrl parsed = HttpUrl.parse(endpoint);
if (parsed == null) throw new IllegalArgumentException("invalid post url: " + endpoint);
return endpoint(parsed);
}
The reason I'm so concerned basically is I cannot see anything in this repo that sets this and we know lack thereof results in unqueryable and unaggregatable data. Using a dummy name which cannot be set at a level people are likely to control will result in an unfairly bad experience vs jaeger who have a setting. This is not worth waiting for complaints about (which likely would dump into zipkin's channel)
Regardless, if we want to suggest to prioritize the "service.name", knowing we have a fallback, both should be in the README. When there's a normalized way to set the "service.name" in the span resource above this tier, both jaeger and zipkin exporters can get a README update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my first stab at writing that comment was crap.. hopefully my rewording above is more coherent (coffee is setting in)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea, as I understand it, is that the person configuring the SDK will add the Resource to the TracerProvider once, at startup. It's not code that would exist in the SDK itself, but written by the SDK user.
I'm not sure about that jaeger exporter, and why it might have been written that way. My guess is that it predates the semantic convention of putting service.name in the Resource.
I'll put an exporter-level serviceName back and have it be the fallback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an issue to use the resource for that in Jaeger
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool maybe link to that in a TODO. regardless it seems a fallback is prudent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some concerns that you also pointed. We should resolve both exporters when we do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we have this defined in specs as well:
open-telemetry/opentelemetry-specification#472
@adriancole may want to confirm that it is what you expect :). Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I restored the serviceName option, but have it be superceded by the service.name set in the Resource, if it's there. Phew.
If this is an ok approach for now, then let's get this bad boy merged and see if it works!
…in/ZipkinExporterConfiguration.java Co-Authored-By: Adrian Cole <[email protected]>
…in/ZipkinExporterConfiguration.java Co-Authored-By: Adrian Cole <[email protected]>
528e204
to
8112b7a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fan of most things, except the factory methods, but that you continue putting them back suggests you feel otherwise :)
I'll leave it up to you vs tie you up on another round.
...ters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java
Outdated
Show resolved
Hide resolved
...ters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java
Outdated
Show resolved
Hide resolved
ok! I think I've got it in a good state. Looking forward to kicking the tires and see how it works. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update top-level README, QUICKSTART and CHANGELOG files?
Also, the jaeger example seems extremely copy/paste find replace, why not do that with a default endpoint of http://localhost:9411/api/v2/spans?
I think in the jaeger exporter README they link to this example, which would allow others to see if it works or not for lack of something more integrated.
I created an issue for the zipkin example: #1137 |
ok, I think this is ready to go. @approvers Can you give it a once over, so we can make this a part of the 0.4.0 release next week? |
@bogdandrutu @carlosalberto review, please, so we can get this merged for 0.4.0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for this @jkwatson!
* basic zipkin span exporter with some unit tests * add tests for the configuration class, hook up a create method and clean up other unit tests * add a README * Update exporters/zipkin/README.md Co-Authored-By: Adrian Cole <[email protected]> * Update exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java Co-Authored-By: Adrian Cole <[email protected]> * Update exporters/zipkin/README.md Co-Authored-By: Adrian Cole <[email protected]> * apply PR review comments * Update build.gradle Co-Authored-By: Adrian Cole <[email protected]> * a little bit of cleanup from PR review * implement shutdown and provide javadoc about the closing of the Sender * don't set attributes if they're already set. * formatting * grpc tweaks, and an exception thrown * Update the comment to be a little more accurate. * formatting * Update exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java Co-Authored-By: Adrian Cole <[email protected]> * Update exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java Co-Authored-By: Adrian Cole <[email protected]> * doc/naming cleanup * simplify the builder, provide two simple factory methods * strip out the endpoint logic and instead get it from the Resource * formatting * restore the serviceName option, but keep the Resource-based override. * update for changes from master. * remove factory methods on the configuration, and update the README * update the docs to match the requirements * fix a typo * tiny re-arrange of javadoc * Add zipkin to the top-level docs Co-authored-by: Adrian Cole <[email protected]>
Resolves #534
Note: this code is heavily copied from the OpenCensus zipkin implementation.