Skip to content
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

Merged
merged 28 commits into from
May 1, 2020

Conversation

jkwatson
Copy link
Contributor

@jkwatson jkwatson commented Apr 13, 2020

Resolves #534

Note: this code is heavily copied from the OpenCensus zipkin implementation.

@jkwatson
Copy link
Contributor Author

@adriancole would love your eyes on this one!

build.gradle Outdated Show resolved Hide resolved
build.gradle Outdated Show resolved Hide resolved
Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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

}
Status status = spanData.getStatus();
if (status != null) {
spanBuilder.putTag(STATUS_CODE, status.getCanonicalCode().toString());
Copy link
Contributor

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?

Copy link
Contributor Author

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:

Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build.gradle Show resolved Hide resolved
exporters/zipkin/build.gradle Outdated Show resolved Hide resolved
Copy link
Contributor

@codefromthecrypt codefromthecrypt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some README help

exporters/zipkin/README.md Outdated Show resolved Hide resolved
exporters/zipkin/README.md Outdated Show resolved Hide resolved
@carlosalberto
Copy link
Contributor

Not an expert of Zipkin, but overall looks great @jkwatson You need to add the new artifact to all/build.gradle too, btw ;)

@jkwatson
Copy link
Contributor Author

@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-io
Copy link

codecov-io commented Apr 14, 2020

Codecov Report

Merging #1106 into master will decrease coverage by 0.05%.
The diff coverage is 85.32%.

Impacted file tree graph

@@             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     
Impacted Files Coverage Δ Complexity Δ
...telemetry/exporters/zipkin/ZipkinSpanExporter.java 84.61% <84.61%> (ø) 35.00 <35.00> (?)
.../exporters/zipkin/ZipkinExporterConfiguration.java 100.00% <100.00%> (ø) 2.00 <2.00> (?)
...elemetry/sdk/trace/export/BatchSpansProcessor.java 88.48% <0.00%> (-1.05%) 10.00% <0.00%> (ø%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6e7f34d...813fb95. Read the comment docs.

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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.

https://github.com/openzipkin/brave/blob/master/instrumentation/grpc/src/main/java/brave/grpc/GrpcParser.java#L66

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.

exporters/zipkin/build.gradle Show resolved Hide resolved
exporters/zipkin/build.gradle Outdated Show resolved Hide resolved
ZipkinExporterConfiguration() {}

/**
* Returns the service name.
Copy link
Contributor

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.

Copy link
Contributor Author

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!

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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

// 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";
Copy link
Contributor

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.

Copy link
Contributor Author

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!

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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 with BytesEncoder<Span>

* @return the service name.
* @since 0.4.0
*/
public abstract String getServiceName();
Copy link
Contributor

@codefromthecrypt codefromthecrypt Apr 18, 2020

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();
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Contributor

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..

Copy link
Contributor Author

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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.

https://github.com/openzipkin/brave/blob/master/brave/src/main/java/brave/Tracing.java#L163

    /**
     * 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 {
Copy link
Contributor

@codefromthecrypt codefromthecrypt Apr 18, 2020

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()

Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

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.

public abstract Builder setV2Url(String v2Url);

/**
* Sets the Zipkin sender.
Copy link
Contributor

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);
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @return this Builder instance
* @return this Builder instance
* @see SpanBytesEncoder

public abstract Builder setSender(Sender sender);

/**
* Sets the {@link SpanBytesEncoder}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controls the format used by the {@link Sender}. Defaults to {@link SpanBytesEncoder#JSON_V2}

@codefromthecrypt
Copy link
Contributor

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?

@jkwatson
Copy link
Contributor Author

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 service.name is not a global thing in OTel, but provided via the Resource that is attached to each Span for export. That doesn't really jive with the code to look up the local endpoint, since that's more exporter-scoped, rather than span scoped.

Thoughts on dropping the local endpoint code, and just attaching the service name provided via the Resource object?

@codefromthecrypt
Copy link
Contributor

Thoughts on dropping the local endpoint code, and just attaching the service name provided via the Resource object?

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
localEndpoint.serviceName is set (and you are sure that "service.name" is routinely defaulted in tracer setup)

  • servicename was set at tracer scope default to help users out of very big holes dug by setting service names randomly and sporadically throughout a local root. IOTW we used to do the tag based approach and it resulted in chaos

@codefromthecrypt
Copy link
Contributor

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.

@codefromthecrypt
Copy link
Contributor

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 :shipit:

sg?

@jkwatson
Copy link
Contributor Author

Once we get this merged, I can point a test service at New Relic's zipkin span ingest and see how it all looks.

@jkwatson
Copy link
Contributor Author

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;
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use

public static final String SERVICE_NAME = "service.name";
?


static Span generateSpan(SpanData spanData) {
Endpoint endpoint = EMPTY_ENDPOINT;
Map<String, AttributeValue> resourceAttributes = spanData.getResource().getAttributes();
Copy link
Contributor

@codefromthecrypt codefromthecrypt Apr 22, 2020

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.

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.

Copy link
Contributor

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)

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

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.

Copy link
Member

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

Copy link
Contributor Author

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!

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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.

@jkwatson
Copy link
Contributor Author

ok! I think I've got it in a good state. Looking forward to kicking the tires and see how it works.

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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.

https://github.com/open-telemetry/opentelemetry-java/blob/8a0ec1d42dbb39e24507b75c629ce44f6dfd9ba5/examples/jaeger/src/main/java/io/opentelemetry/example/JaegerExample.java

@jkwatson
Copy link
Contributor Author

I created an issue for the zipkin example: #1137

@jkwatson
Copy link
Contributor Author

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?

@jkwatson
Copy link
Contributor Author

@bogdandrutu @carlosalberto review, please, so we can get this merged for 0.4.0.

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a 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!

@bogdandrutu bogdandrutu merged commit 0ce1a38 into open-telemetry:master May 1, 2020
@jkwatson jkwatson added this to the May Release milestone May 1, 2020
jkwatson added a commit to newrelic-forks/opentelemetry-java that referenced this pull request May 18, 2020
* 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 <adriancole@users.noreply.github.com>

* Update exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporter.java

Co-Authored-By: Adrian Cole <adriancole@users.noreply.github.com>

* Update exporters/zipkin/README.md

Co-Authored-By: Adrian Cole <adriancole@users.noreply.github.com>

* apply PR review comments

* Update build.gradle

Co-Authored-By: Adrian Cole <adriancole@users.noreply.github.com>

* 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 <adriancole@users.noreply.github.com>

* Update exporters/zipkin/src/main/java/io/opentelemetry/exporters/zipkin/ZipkinExporterConfiguration.java

Co-Authored-By: Adrian Cole <adriancole@users.noreply.github.com>

* 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 <adriancole@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SDK: Port the OC Zipkin exporter
6 participants