-
Notifications
You must be signed in to change notification settings - Fork 8
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
Exporter packages #115
Conversation
64355ca
to
d27aae3
Compare
d27aae3
to
7633563
Compare
5c3f1a7
to
d4de8af
Compare
d4de8af
to
a984b82
Compare
d550697
to
46af537
Compare
There was a problem hiding this 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
examples/react-app/README.md
Outdated
@@ -0,0 +1,68 @@ | |||
## Example React App set up with Vite.js and configured with Autometrics |
There was a problem hiding this comment.
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>" }); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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." |
There was a problem hiding this comment.
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}`); |
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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>" }); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 🤣
examples/react-app/src/App.tsx
Outdated
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", |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
a834977
to
b85cf02
Compare
442d180
to
9296f10
Compare
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.)
autometrics
convenience package.strict
settings in TypeScript.Checklist
autometrics
package.@autometrics/on-demand-metric-reader
.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 packageGiven 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 aPushGatewayExporter
(could maybe be upstreamed to as acontrib
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
andconcurrencyLimit
.Implemented OTLP/HTTP exporter
That's what it all started with. I'll soon test if it actually works 😅
Enabled
strict
settings in TypeScriptWhile I would generally advise anyone using TS to enable the
strict
settings, this is especially true for libraries. Otherwise consumers withstrict
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 aMeterProvider
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 :)