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

Exporter packages #115

Merged
merged 23 commits into from
Sep 6, 2023
Merged

Exporter packages #115

merged 23 commits into from
Sep 6, 2023

Conversation

arendjr
Copy link
Collaborator

@arendjr arendjr commented Aug 30, 2023

This turned out to be much more than I thought, so I haven't actually gotten to testing yet. Still, I think it's due for a first round of review.

Summary

(Detailed explanations below.)

Checklist

Details

Split all the exporters into separate packages

Since I would be adding another exporter, and different exporters rely on different packages, it only made sense to split the exporters themselves into packages as well.

This also resolved the issue where we decided we don't want to automatically start a webserver anymore. This behavior is now explicitly limited to the Prometheus exporter only, and clearly documented as such.

Dropped the autometrics convenience package

Given that users now need to make an explicit choice regarding the exporter to use, the convenience package didn't make much sense anymore.

Rewrote the logic for push exporters

I initially tried to implement my new OTLP/HTTP exporter on the existing push gateway support, but I slowly discovered that we were misusing the Otel APIs. In order to fix it "the right way", I had to implement a new OnDemandMetricReader (in a separate package for now, but I think it makes sense to upstream this to the OpenTelemetry-js project) and a PushGatewayExporter (could maybe be upstreamed to as a contrib package? I dunno). Everything feels horribly over-engineered, but that seems to be the way of the Otel project.

Since I was copying/reusing some bits from the Otel libraries anyway, I brought in a few more options that wouldn't hurt to have either, such as timeout and concurrencyLimit.

Implemented OTLP/HTTP exporter

That's what it all started with. I'll soon test if it actually works 😅

Enabled strict settings in TypeScript

While I would generally advise anyone using TS to enable the strict settings, this is especially true for libraries. Otherwise consumers with strict settings may run into trouble consuming our APIs since we didn't strict-check them.

Switched from NPM to Yarn

After running into another NPM issue with unnecessarily duplicated packages and NPM's failure to install Rome I was fed up and decided to swap it out for Yarn. All our other TS projects use Yarn anyway.

I quickly realized there's another important advantage for libraries, since Yarn actually warns when peer dependencies aren't specified correctly and is generally more strict with how dependencies are specified. Similar to the strict settings, if we don't verify our packages are specified correctly, downstream Yarn (and PNPM) consumers may run into issues instead.

Updated all the examples and READMEs

Since there's quite some breaking changes in the API, I had to run through everything.

Please double-check I didn't miss anything.

Fixes #113

Given that the init() functions now come from separate packages anyway, I had to make things a bit more lenient to avoid a big footgun here. So now we always create a MeterProvider immediately, so metrics recording can work before the exporter is even registered. The situation of accidentally spinning up the webserver for the Prometheus scrape endpoint is simply impossible now because that server is in a separate package.

Resolves #114

I think this resolves everything I set out to do, and more :)

Copy link
Collaborator

@brettimus brettimus left a comment

Choose a reason for hiding this comment

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

approving but i haven't done any e2e tests yet! would still like to try that before merging

@@ -0,0 +1,68 @@
## Example React App set up with Vite.js and configured with Autometrics
Copy link
Collaborator

Choose a reason for hiding this comment

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

might be good to highlight the experimental nature of doing something like this! since we haven't worked out all the kinks oursevles

import { autometrics } from "@autometrics/autometrics";
import { init } from "@autometrics/exporter-otlp-http";

init({ url: "https://<your-otel-collector>" });
Copy link
Collaborator

Choose a reason for hiding this comment

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

same comment as above: i think this was a copy-paste from the otel readme. not sure if we want to include init as an example of generic usage

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

How do you mean, "want to include [...] as an example of generic usage"? Calling init() is mandatory now.

"contributors": [
"Laurynas Keturakis",
"Evan Schwartz",
"Jacco Flenter",
"Oscar van Zijverden",
"Stephan Lagerwaard"
"Stephan Lagerwaard",
"Arend van Beelen jr."
Copy link
Collaborator

Choose a reason for hiding this comment

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

🎉

timeout = 1000,
buildInfo,
}: InitOptions) {
amLogger.info(`Exporter will push to the OLTP/HTTP endpoint at ${url}`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: OTLP 🙈

private _export(serializedMetrics: string): Promise<void> {
const promise = fetch(this._options.url, {
method: "POST",
mode: "cors",
Copy link
Collaborator

Choose a reason for hiding this comment

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

note to self: will "cors" have an effect in node? i remember getting typescript complaints from using this in a node app once

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good question! I did a little search, at least node-fetch says they haven't implemented it (https://www.npmjs.com/package/node-fetch). I would expect them to ignore it, but I can't know for sure without testing. Of course, Node has native fetch() nowadays, but MDN makes no mention of Node's support for the mode property: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
It does say Deno doesn't support it, but just like with node-fetch, I would assume it gets ignored...

import { autometrics } from "@autometrics/autometrics";
import { init } from "@autometrics/exporter-otlp-http";

init({ url: "https://<your-otel-collector>" });
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think this was a copy-paste from the otel readme. not sure if we want to include init as an example of generic usage

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy-paste?! I'm no AI 🤣

pushGateway: "http://0.0.0.0:8080/metrics",
// A proxy configured in `vite.config.ts` forwards the `/metrics` endpoint
// to the Otel Collector.
url: "https://wercker.fmp.fiberplane.dev/otel/http/v1/metrics",
Copy link
Collaborator

Choose a reason for hiding this comment

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

we'll probably want to change this example URL before merging

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, that was an accidental check-in because Benno asked me to test something. I'll revert that :D

@arendjr arendjr merged commit 90400cd into main Sep 6, 2023
1 check passed
@arendjr arendjr deleted the exporter-packages branch September 6, 2023 08:40
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.

OTLP export support 🐛 Class decorators break in the browser when using the init function
2 participants