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

API prototype #11

Merged
merged 17 commits into from
Jul 12, 2019
Merged

API prototype #11

merged 17 commits into from
Jul 12, 2019

Conversation

fbogsany
Copy link
Contributor

This is an early prototype of the OpenTelemetry Ruby API based on the API spec so far. Very much WIP, but feedback and discussion about any of this is strongly encouraged.


def add_link(span_context_or_link, **attrs)
check_not_nil(span_context_or_link, "span_context_or_link")
check_empty(attrs, "attrs") unless span_context_or_link.instance_of?(SpanContext)
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 instance_of? is OK here because SpanContext is specified to be a "final" class and add_link is specified to either take a SpanContext + attributes or a Link without additional attributes.

api/lib/opentelemetry.rb Outdated Show resolved Hide resolved
api/lib/opentelemetry.rb Outdated Show resolved Hide resolved
@mwear
Copy link
Member

mwear commented Jun 28, 2019

I was reading through the specification in order to understand exactly what is expected of the API portion of this project. Bullet point #2 under the requirements section says:

  1. Third party libraries and frameworks that add instrumentation to their code will have a dependency only on the API of OpenTelemetry language library. The developers of third party libraries and frameworks do not care (and cannot know) what specific implementation of OpenTelemetry is used in the final application.

From this, I gather that an instrumentation author should only need to depend on the opentelemety-ruby-api gem and be able to write code such as:

span = tracer.create_span('blogs#index')
span.set_attribute 'component', 'rails'
...

In order for this to work, the API will have to ship with a no-op tracer, since a valid, usable span will need to be returned by Tracer#create_span.

This is how the API is packaged for OpenTracing. See https://github.com/opentracing/opentracing-ruby and the tracer.

Since Ruby doesn't have a notion of interfaces, it's not clear if there should be an additional set of empty classes showing the expected method signatures. For OpenTracing the no-op Tracer is all that was packaged with the API library. I'm wondering if it's possible for us to do the same for this project's API.

I took a look through several of the OpenTelemetry libraries in order to see how they're structured and this is what I found:

Java's API Library contains both interfaces, as well as a default no-op Tracer implementation

I looked at Python as well, and the situation there was a little bit unclear to me. Perhaps somebody can shed some light on it.

Its API imports the typing module. I only see method signatures with type hints, but nothing indicating that the API returns a usable object. Which, seems like it wouldn't satisfy the requirement I listed at the beginning of this comment.

I also looked at the Javascript repo. It ships with interfaces, available by way of type script, and it appears as though it will ship with a no-op tracer, given at least some of the open PRs.

Based on this, I think it is a requirement that the OpenTelemetry Ruby API ships with a no-op Tracer implementation. I'm not sure if that is sufficient, but I think it might be. Since Ruby does not have interfaces, shipping a set of empty classes does not seem valuable.

I think we need to clarify what is expected, but ultimately, if packaging a no-op Tracer implementation is sufficient for the Ruby API, perhaps we should shift gears slightly, and start heading that direction.

@fbogsany
Copy link
Contributor Author

Based on this, I think it is a requirement that the OpenTelemetry Ruby API ships with a no-op Tracer implementation. I'm not sure if that is sufficient, but I think it might be. Since Ruby does not have interfaces, shipping a set of empty classes does not seem valuable.

I think we need to clarify what is expected, but ultimately, if packaging a no-op Tracer implementation is sufficient for the Ruby API, perhaps we should shift gears slightly, and start heading that direction.

The requirement for a minimal implementation in the API package is spelled out below. I agree it doesn't make sense to 🚢 a set of empty classes. I've updated the PR to provide a minimal implementation instead.

For alternative implementations, I think we should provide a conformance test suite alongside the API package.

https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/library-guidelines.md#api-and-minimal-implementation

The API dependency will contain a minimal implementation of the API. When no other implementation is explicitly included in the application no telemetry data will be collected. Here is what active components will look like in this case:
Minimal Operation Diagram
It is important that values returned from this minimal implementation of API are valid and do not require the caller to perform extra checks (e.g. createSpan() method should not fail and should return a valid non-null Span object). The caller should not need to know and worry about the fact that minimal implementation is in effect. This minimizes the boilerplate and error handling in the instrumented code.

end

def start_root_span(name, sampler: nil, links: nil, recording_events: nil, kind: nil)
raise ArgumentError if name.nil?
Copy link
Member

@mwear mwear Jul 3, 2019

Choose a reason for hiding this comment

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

I'm not sure what we should do for invalid arguments in the minimal implementation, and am somewhat torn on the issue.

I just wanted to point out that there is a proposal currently in PR form here: open-telemetry/opentelemetry-specification#153.

There seem to be various opinions as you read through the comments. This comment proposed a somewhat pragmatic approach of falling back to a default when an argument is invalid. Quote (from the comment)

Specific case: I do think using a null name for Span could fallback to using a default name, instead of throwing. Documenting it is nice, but providing defaults for these kind of things is a good alternative ;)

It might be too early to make a final call on how to deal exceptions in the minimal implementation, but we should keep an eye on that PR and the specification repo for guidance.

module Trace
# SpanData is an immutable object that is used to report out-of-band completed spans.
#
# TODO: consider whether to copy collections to a known internal form and expose only enumerations.
Copy link
Member

Choose a reason for hiding this comment

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

I really like this idea. I think the no-op implementation should try to expose the smallest possible interface. That will help users ensure their usage is correct (e.g. they aren't inadvertently depending on the returned objects implementing obscure methods of Array or Hash), and relieve implementors of the burden of implementing a larger surface.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Opened #15 for this. I don't want to invest effort until there's some clarity around SpanData (open-telemetry/opentelemetry-specification#71) and enumerable vs. hash attributes (open-telemetry/opentelemetry-specification#92).

api/lib/opentelemetry/trace/span_context.rb Outdated Show resolved Hide resolved
api/lib/opentelemetry/trace/span_data.rb Show resolved Hide resolved
api/lib/opentelemetry/context.rb Outdated Show resolved Hide resolved
api/lib/opentelemetry/trace/span.rb Outdated Show resolved Hide resolved
# TODO: This is a helper for the default use-case of extending the current trace with a span.
#
# The spec-ed API seems a little clunky. Default use-case looks like:
# OpenTelemetry.tracer.with_span(OpenTelemetry.tracer.start_span('do-the-thing')) do ... end
Copy link
Member

Choose a reason for hiding this comment

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

I like this helper 👍

The spec assumes Java -- looks like in the reference impl, scope implements Closeable interface and used along with try-with-resources.. We don't need to follow that pattern.

api/lib/opentelemetry/trace/tracer.rb Outdated Show resolved Hide resolved
@fbogsany fbogsany requested review from luvtechno and bai July 11, 2019 18:18
@fbogsany
Copy link
Contributor Author

Updated with review suggestions. This needs a 👍 from a codeowner to merge.

Copy link
Member

@luvtechno luvtechno left a comment

Choose a reason for hiding this comment

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

Thank you @fbogsany ! I think we've made a good starting point.

Copy link
Member

@bai bai left a comment

Choose a reason for hiding this comment

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

Great job 🎉

Copy link
Member

@mwear mwear left a comment

Choose a reason for hiding this comment

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

This looks good! Thanks for all the hard work!

@bai
Copy link
Member

bai commented Jul 12, 2019

Oh quick nitpick: might want to change PR title before merging, just to keep things clean.

@fbogsany fbogsany changed the title WIP prototype API prototype Jul 12, 2019
@fbogsany fbogsany merged commit f6c2e3f into open-telemetry:master Jul 12, 2019
@fbogsany fbogsany deleted the prototyping branch July 12, 2019 14:02
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.

None yet

6 participants