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

feat!: use semver to determine API compatibility #1772

Closed

Conversation

dyladan
Copy link
Member

@dyladan dyladan commented Dec 21, 2020

This removes the manual step of the API compatibility version and replaces it with a proper semver check. The expected range is ^${VERSION} where VERSION is the version of the API instance attempting to acquire the global API.

/cc @Flarna since this was your idea I would appreciate your 👀

THIS IS INCOMPATIBLE WITH PAST API VERSIONS AND IS A HARD BREAKING CHANGE

@codecov
Copy link

codecov bot commented Dec 22, 2020

Codecov Report

Merging #1772 (8310269) into master (b4c9e40) will decrease coverage by 0.13%.
The diff coverage is 95.00%.

@@            Coverage Diff             @@
##           master    #1772      +/-   ##
==========================================
- Coverage   92.18%   92.05%   -0.14%     
==========================================
  Files         167      164       -3     
  Lines        5845     5560     -285     
  Branches     1256     1208      -48     
==========================================
- Hits         5388     5118     -270     
+ Misses        457      442      -15     
Impacted Files Coverage Δ
packages/opentelemetry-api/src/api/metrics.ts 78.94% <50.00%> (+15.31%) ⬆️
...ges/opentelemetry-api/src/internal/global-utils.ts 92.00% <92.00%> (ø)
packages/opentelemetry-api/src/api/context.ts 88.88% <100.00%> (+1.79%) ⬆️
packages/opentelemetry-api/src/api/propagation.ts 100.00% <100.00%> (+7.14%) ⬆️
packages/opentelemetry-api/src/api/trace.ts 95.83% <100.00%> (+2.97%) ⬆️
packages/opentelemetry-api/src/internal/semver.ts 100.00% <100.00%> (ø)
...emetry-core/src/platform/node/RandomIdGenerator.ts 87.50% <0.00%> (-6.25%) ⬇️
...emetry-instrumentation-xml-http-request/src/xhr.ts
...mentation-xml-http-request/src/enums/EventNames.ts
packages/opentelemetry-plugin-fetch/src/fetch.ts
... and 3 more

packages/opentelemetry-api/src/api/metrics.ts Outdated Show resolved Hide resolved
packages/opentelemetry-api/src/api/context.ts Outdated Show resolved Hide resolved
packages/opentelemetry-api/src/api/propagation.ts Outdated Show resolved Hide resolved
packages/opentelemetry-api/src/api/trace.ts Outdated Show resolved Hide resolved
packages/opentelemetry-api/package.json Outdated Show resolved Hide resolved
Copy link
Member

@obecny obecny left a comment

Choose a reason for hiding this comment

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

generally looks fine, I have just concerns with regards the error handling which should be imho changed, so we don't break / stop the end user functionality

const api = _global[GLOBAL_OPENTELEMETRY_API_KEY]!;
if (api[type]) {
// already registered an API of this type
throw new Error(
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't we warn here only instead of throwing an error ?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah does the spec require us to never throw on the API ?

Copy link
Member Author

Choose a reason for hiding this comment

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

The spec strongly discourages throwing. I can change it, but the behavior of doing nothing is potentially confusing. This should only be called during trace setup and never again so it seems unlikely to throw. I thought it would be fine in this case. I can change it to warn though if that's better.

Copy link
Member

Choose a reason for hiding this comment

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

I would prefer a warn since users generally think there are errors anyway (since the console logger doesn't log the level by default)

Copy link
Member Author

Choose a reason for hiding this comment

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

there is no logger here because we're in the API. It has to be console.warn. Is that OK?

Copy link
Member Author

Choose a reason for hiding this comment

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

any CLI tool written in nodejs could potentially have an expected output to be parsed by other tools. If we log unexpectedly we change that output.

Simple example, a cli that scrapes the github API and outputs the open issues on a project as JSON to be consumed by jq and other tools.

Copy link
Member

Choose a reason for hiding this comment

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

Exactly. It's not nodejs which runs into issues it's the specific user application.
I remember at least one case where I broke an application by logging to stderr because this was seen as error by the caller.
And logging to sdtout tends to break everything where a caller reads result from stdout.

If documentation clearly states that an API may throw it's up to the user (and all our samples) to add a try/catch and log/exit/...
A log to console can't be catched by user (except by monkey patching console but I don't think we want users to do this).

We could change the API to return a boolean instead of throwing. But this results in loosing the reason why it failed. We could return an error string or similar but I don't think these are nice APIs.

This is an API only used once during startup. Throwing there doesn't force users to clutter their whole codebase with try/catches. Therefore I think it's ok to throw here.

Copy link
Member

Choose a reason for hiding this comment

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

If documentation clearly states that an API may throw it's up to the user (and all our samples) to add a try/catch and log/exit/...

I don't think expecting users to try/catch when trying to setup the sdk or a instrumentation would be a good solution either.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see it as analogous to something like http server setup. If you try to bind to a port which is already bound, it throws. Because duplicate registration is startup/setup time it is most likely never throws or throws every time, not flaky or sometimes happening.

Copy link
Member

Choose a reason for hiding this comment

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

Guys we can't break user application just because the otel configuration is wrong or because otel is missing something. Imagine the simple situation when you release a new version on production you then restart all the nodes and suddenly all production is down because the otel has wrong configuration. We can't do this. If otel fails all what should happen is to show user the error but never stop or break the application. The application should work fine in any situation.


if (api.version != VERSION) {
// All registered APIs must be of the same version exactly
throw new Error(
Copy link
Member

Choose a reason for hiding this comment

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

ditto


const myVersionMatch = ownVersion.match(re);
if (!myVersionMatch) {
throw new Error('Cannot parse own version');
Copy link
Member

Choose a reason for hiding this comment

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

I think that the whole function should work as typical boolean check and in this case it should return false and maybe just log warning. Otherwise it might stop / break the user system

Copy link
Member Author

Choose a reason for hiding this comment

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

If it can't parse it's own version that is something that will fail every single time and nothing the user can do about it. In this case I think throwing is the appropriate response since it's a bug that must be fixed. The throw should make this trip in tests and never allow us to release with a version which can't be parsed.

return false;
}

acceptedVersions.add(version);
Copy link
Member

Choose a reason for hiding this comment

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

Is it intended to ignore the pre-release part in comparison?
The semver module doesn't do this on default, only if includePrerelease is specified.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes the prerelease part is ignored. A prereleased version should be treated by the comparison as if it was the released version. I may want to release 2.3.1-rc to ensure it works as expected before releasing 2.3.1 and I would not want the check to behave differently for the released v prereleased version.

@dyladan
Copy link
Member Author

dyladan commented Feb 19, 2021

@dyladan dyladan closed this Feb 19, 2021
pichlermarc pushed a commit to dynatrace-oss-contrib/opentelemetry-js that referenced this pull request Dec 15, 2023
…pen-telemetry#1772)

* feat(auto-instrumentations-node): Expose getting resource detectors

The auto instrumentation package provides users with a very easy way to
instrument their application, either from the commandline or
programatically. Users wishing the configure these instrumentations can also
call `getNodeAutoInstrumentations`.

This commit also exposes `getResourceDetectorsFromEnv`, so that users
configuring or somehow wishing to change the easy to use autoinstrumentation
entrypoint can also use the preconfigured resource detectors. Since the
autoinstrumentation package sets its exports, this function was previously
inaccessible.

Usage can look like this:

```js
const { getNodeAutoInstrumentations, getResourceDetectorsFromEnv } = require('@opentelemetry/auto-instrumentations-node');
const opentelemetry = require('@opentelemetry/sdk-node');

const sdk = new opentelemetry.NodeSDK({
  instrumentations: getNodeAutoInstrumentations({
    '@opentelemetry/instrumentation-fs': { enabled: false },
  }),
  resourceDetectors: getResourceDetectorsFromEnv(),
});

// use the sdk
```

Workarounds can be found [elsewhere in the opentelemetry repos](https://github.com/open-telemetry/opentelemetry-demo/blob/855bde3588b0fe85e500bec185dc2f311b15f98a/src/paymentservice/opentelemetry.js#L28-L38).
These can be fixed once a release is made.

Resolves open-telemetry#1531.

* style: Align indentation

---------

Co-authored-by: Amir Blum <amirgiraffe@gmail.com>
pichlermarc pushed a commit to dynatrace-oss-contrib/opentelemetry-js that referenced this pull request Dec 15, 2023
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.

4 participants