Skip to content
This repository was archived by the owner on Jul 1, 2022. It is now read-only.

Define some classes internal#470

Merged
jpkrohling merged 1 commit intojaegertracing:masterfrom
jpkrohling:396-Define-classes-as-internal
Jul 4, 2018
Merged

Define some classes internal#470
jpkrohling merged 1 commit intojaegertracing:masterfrom
jpkrohling:396-Define-classes-as-internal

Conversation

@jpkrohling
Copy link
Copy Markdown
Collaborator

@jpkrohling jpkrohling commented Jul 2, 2018

Which problem is this PR solving?

Short description of the changes

  • Moved everything under the newly created internal package, except for:
    • Configuration object
    • Zipkin sender and reporter
    • MicrometerMetricsFactory

Decide

  • What to do with JaegerTracer.Builder. It should really be public, but it belongs to the JaegerTracer class, which is internal. Should this builder be moved out of the class, or should we make this builder internal? My preference would be to extract it to io.jaegertracing.TracerBuilder class.

@ghost ghost assigned jpkrohling Jul 2, 2018
@ghost ghost added the review label Jul 2, 2018
@codecov
Copy link
Copy Markdown

codecov bot commented Jul 2, 2018

Codecov Report

Merging #470 into master will decrease coverage by 0.02%.
The diff coverage is 100%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #470      +/-   ##
============================================
- Coverage     88.12%   88.09%   -0.03%     
+ Complexity      493      489       -4     
============================================
  Files            63       62       -1     
  Lines          1852     1848       -4     
  Branches        241      241              
============================================
- Hits           1632     1628       -4     
  Misses          142      142              
  Partials         78       78
Impacted Files Coverage Δ Complexity Δ
...jaegertracing/zipkin/internal/V2SpanConverter.java 87.83% <ø> (ø) 21 <0> (?)
...egertracing/internal/propagation/TextMapCodec.java 89.7% <ø> (ø) 18 <0> (?)
...xceptions/MalformedTracerStateStringException.java 100% <ø> (ø) 1 <0> (?)
...rtracing/internal/reporters/CompositeReporter.java 71.42% <ø> (ø) 5 <0> (?)
...ain/java/io/jaegertracing/zipkin/ZipkinSender.java 65.67% <ø> (ø) 17 <0> (?)
...a/io/jaegertracing/internal/utils/RateLimiter.java 100% <ø> (ø) 5 <0> (?)
...ertracing/micrometer/MicrometerMetricsFactory.java 100% <ø> (ø) 6 <0> (ø) ⬇️
.../tracerresolver/internal/JaegerTracerResolver.java 100% <ø> (ø) 2 <0> (?)
...exceptions/BaggageRestrictionManagerException.java 100% <ø> (ø) 2 <0> (?)
...al/exceptions/EmptyTracerStateStringException.java 100% <ø> (ø) 1 <0> (?)
... and 52 more

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 46b64d5...dfb9d8b. Read the comment docs.

@jpkrohling
Copy link
Copy Markdown
Collaborator Author

@objectiser I believe this PR follows what was discussed last Friday during the bi-weekly meeting. Would you mind reviewing it ?

package io.jaegertracing.baggage;
package io.jaegertracing.spi;

import io.jaegertracing.internal.baggage.Restriction;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What should we do in these cases - the Restriction class is part of the SPI - we shouldn't really be returning or passing instances of internal classes in a public API?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Last Friday we talked briefly about this: providers (those who will consume the SPI) are expected to depend on internal classes, like JaegerSpan (we discussed it when talking about the Reporters and Senders).

End consumes of our code will only ever be required to deal with the Configuration object and OpenTracing API, at least for this initial version. If we later decide that some class should really be part of the public API, we'll white list that specific one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah agree that was what we discussed - but on reflection I'm thinking that if a class is part of the "public" API/SPI, then it should also be public - as end users may contribute SPI implementations.
I'll have a look through the current SPI interfaces to see how many current internal classes are affected - if not many, it may be worth moving them to be public again.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

as end users may contribute SPI implementations.

Then they are wearing the "provider" hat on this code/module. Their "consumer" code shouldn't make use of the Restriction class, only their provider implementation. And provider implementations are expected to deal with internal classes.

It's still not my first choice, as I'd rather have clear compatibility expectations not only for end consumers (public API) but also for providers: as a provider, can I rely on the getTracer() method from JaegerSpan?

But, the current arrangement is already better than the status quo :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure I agree with providers having to deal with internal classes. If the provider is defined independent of the jaeger code base, it should expect a stable SPI, which is not guaranteed in relation to the internal classes.

+1 I would prefer JaegerSpan was a public interface, with internal JaegerSpanImpl - even if for now JaegerSpan had no other methods other than derived from Span.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it should expect a stable SPI, which is not guaranteed in relation to the internal classes.

Agreed.

+1 I would prefer JaegerSpan was a public interface, with internal JaegerSpanImpl - even if for now JaegerSpan had no other methods other than derived from Span.

The other suggestion made during the call was to indeed have this split, but with empty interfaces, like public interface JaegerSpan extends Span {}.

@objectiser
Copy link
Copy Markdown
Contributor

@jpkrohling If JaegerTracer doesn't being a public interface, then the next best solution would be to have a public TracerBuilder.

In terms of the internal implementations of (for example) samplers - are they going to be made public based on request? Otherwise not sure the tracer builder approach is going to be useful, if the app needs to then use internal sampler implementations?

@jpkrohling
Copy link
Copy Markdown
Collaborator Author

are they going to be made public based on request?

That's my understanding, yes. The idea is that our implementations would be assigned based on configuration options like it is currently being done with UdpSender/HttpSender. If an application wants to make use of a special Sender (ZipkinSender, for instance), then that sender is public API.

@yurishkuro
Copy link
Copy Markdown
Member

I am not seeing a lot of requests from people to provide a stable SPI. In the absence of said requests I would be comfortable saying that we simply do not have a stable SPI at this point, and our semver guarantees only apply to public APIs.

@jpkrohling jpkrohling force-pushed the 396-Define-classes-as-internal branch from 27f348b to 96ad3b0 Compare July 2, 2018 16:07
Copy link
Copy Markdown
Member

@yurishkuro yurishkuro left a comment

Choose a reason for hiding this comment

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

it would be really good to have some eyes on this from people who actually extend the client.

### Production

Tracer can be created via `io.jaegertracing.JaegerTracer.Builder` or `io.jaegertracing.Configuration`.
Tracer can be created via `io.jaegertracing.internal.JaegerTracer.Builder` or `io.jaegertracing.Configuration`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

mention Configuration first, and add (preferred).

import io.opentracing.Tracer;
import io.jaegertracing.internal.JaegerTracer;
import io.jaegertracing.internal.metrics.Metrics;
import io.jaegertracing.internal.metrics.MetricsFactory;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MetricsFactory and NoopMetricsFactory are part of SPI

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I actually left the MetricsFactory out of the SPI on purpose, as I thought this was too internal to be customized. Given that we already delegate to an abstraction (Micrometer), it means people can just build a Micrometer reporter instead.

About NoopMetricsFactory, I don't think it belongs to the SPI. Would you mind sharing why you think it would?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You're probably right about noop factory, it's just used as a default. But I think MetricsFactory belongs to an SPI because we don't know upfront which metrics API people want to use with the client. Does Micrometer really support everything?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's an abstraction with tons of providers already implemented: http://micrometer.io/docs

If a provider is not there, people would either have to implement a micrometer provider or a MetricsFactory provider, so, pretty much the same work (but their Micrometer might be reused by other applications and in other scenarios).

I'd really encourage our users to use Micrometer with their own provider than implementing their own MetricsFactory provider.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's assuming people use oss frameworks. For example, we internally have a Java client for Uber's m3db metrics system. Rather than implementing an adapter through Micrometer, it makes more sense for us to bind directly to jaeger's MetricsFactory (which we already do).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That's assuming people use oss frameworks

In general, like, Jaeger? :-) Or do you mean for the metrics backend, like Prometheus?

Rather than implementing an adapter through Micrometer, it makes more sense for us to bind directly to jaeger's MetricsFactory (which we already do).

I would argue that this is like using the (internal) JaegerTracer.Builder: there are valid use cases, but it's not the usual case. The usual case is for an application to be using a framework like Micrometer to make data available to a backend like Prometheus.

How about we keep this internal first and, if there's demand, we make it part of the SPI?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In general, like, Jaeger? :-) Or do you mean for the metrics backend, like Prometheus?

I mean oss frameworks for reporting metrics. Organizations adopting Jaeger may be running all kinds of custom metrics backends, respectively with custom libraries for sending metrics to those backends, which is the case at Uber, as I don't think our metrics client for Java is even open source.

I am not suggesting making MetricsFactory a public interface, but moving it to spi. You already have a bunch of interfaces there, which in my view are actually a lot less likely to be implemented by other people, e.g. who would need to implement Sampler or Sender? If people do implement those, they are doing something very tracing-specific, whereas implement MetricsFactory is simply adapting Jaeger lib to run in a custom enterprise environment.

@pavolloffay
Copy link
Copy Markdown
Member

I think TracerBuilder should belong to the public API with all dependent classes e.g. samplers, reporters and so on.

Are we assuming nobody is extending Jaeger tracer, sampler, sender?

#435 (comment)

@jpkrohling
Copy link
Copy Markdown
Collaborator Author

I think TracerBuilder should belong to the public API with all dependent classes e.g. samplers, reporters and so on.

We have decided last week to not go this route.

Are we assuming nobody is extending Jaeger tracer, sampler, sender?

I don't think we are assuming that. At this point, we are not aware of people doing that and we'll open up the API based on the demand. The most important right now is signal to end consumers that Jaeger APIs aren't public API, other than the Configuration object.

Sampler/Sender are part of the SPI, and we decided last week that it's OK for providers to have access to internal classes, like they do today. If providers need better stability in the classes that they consume (like, JaegerSpan), then we might make them part of a public API in the future.

@jpkrohling
Copy link
Copy Markdown
Collaborator Author

jpkrohling commented Jul 3, 2018

Only one of the links you provided is for a usage of Tracer.Builder. And still, it's for a case where Configuration could be appropriate.

We are certainly going to break current clients, but with that, we hope to provide a better expectation around backwards compatibility.

Edit: I just noticed you said builders, not tracer builder. But the main message remains.

@pavolloffay
Copy link
Copy Markdown
Member

Only one of the links you provided is for a usage of Tracer.Builder. And still, it's for a case where Configuration could be appropriate.

There are way more references to tracer builder, I wanted to pick others too like extending a reporter.

Copy link
Copy Markdown
Member

@yurishkuro yurishkuro left a comment

Choose a reason for hiding this comment

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

lgtm

import io.opentracing.Tracer;
import io.jaegertracing.internal.JaegerTracer;
import io.jaegertracing.internal.metrics.Metrics;
import io.jaegertracing.internal.metrics.MetricsFactory;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In general, like, Jaeger? :-) Or do you mean for the metrics backend, like Prometheus?

I mean oss frameworks for reporting metrics. Organizations adopting Jaeger may be running all kinds of custom metrics backends, respectively with custom libraries for sending metrics to those backends, which is the case at Uber, as I don't think our metrics client for Java is even open source.

I am not suggesting making MetricsFactory a public interface, but moving it to spi. You already have a bunch of interfaces there, which in my view are actually a lot less likely to be implemented by other people, e.g. who would need to implement Sampler or Sender? If people do implement those, they are doing something very tracing-specific, whereas implement MetricsFactory is simply adapting Jaeger lib to run in a custom enterprise environment.

*/

package io.jaegertracing;
package io.jaegertracing.internal;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

some of these technically could be considered public, e.g.

  • TRACER_IP_TAG_KEY - there have been requests to allow providing IP manually via tracer tag.
  • SAMPLER_TYPE_TAG_KEY, SAMPLER_PARAM_TAG_KEY - analytics jobs often need to read and interpret these span tags
  • DEBUG_ID_HEADER_KEY - feels like public, but not sure what the exact use case is.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'll open a new follow-up PR with a new constants class, to discuss and move the candidates.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

*/

package io.jaegertracing.utils;
package io.jaegertracing.internal.utils;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: internal.clock

@jpkrohling jpkrohling mentioned this pull request Jul 4, 2018
9 tasks
Moved everything into internal packages, except for a few selected classes.
Most of the interfaces were moved to the SPI package.

Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
@jpkrohling jpkrohling force-pushed the 396-Define-classes-as-internal branch from 113022e to dfb9d8b Compare July 4, 2018 09:16
@jpkrohling jpkrohling merged commit dfb9d8b into jaegertracing:master Jul 4, 2018
@ghost ghost removed the review label Jul 4, 2018
@quaff
Copy link
Copy Markdown
Contributor

quaff commented Jul 6, 2018

Classes in package "io.jaegertracing.internal.clock" declare wrong package name, such as:
https://github.com/jaegertracing/jaeger-client-java/pull/470/files#diff-5a50b378c49d82672d34ebb327a5578d
The declared package "io.jaegertracing.internal.utils" does not match the expected package "io.jaegertracing.internal.clock"

quaff added a commit to quaff/jaeger-client-java that referenced this pull request Jul 6, 2018
PR jaegertracing#470 brings inconsistent package name.

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
quaff added a commit to quaff/jaeger-client-java that referenced this pull request Jul 6, 2018
PR jaegertracing#470 brings inconsistent package name.

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
jpkrohling pushed a commit that referenced this pull request Jul 6, 2018
PR #470 brings inconsistent package name.

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Define some classes internal

5 participants