-
Notifications
You must be signed in to change notification settings - Fork 2
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
Add log target and l2met transform #21
Add log target and l2met transform #21
Conversation
5f76c34
to
b3db4e5
Compare
cb376b6
to
7e6c0e6
Compare
I'll try to properly review tomorrow morning 👍 |
This is a bit of a big PR for a quick review, I will quickly create a ticket for ourselves to go through it and test it. |
c8e709c
to
b60bbc6
Compare
I just realised that I removed @driv3r from the reviewer. |
fb478bf
to
51cd788
Compare
|
||
The `transform:` options are | ||
|
||
* `:cloud_watch` _(default)_ - Transforms telemetry keys, replacing dots with dashes to support AWS CloudWatch Log Metrics filters. |
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.
This does keep things backward compatible, though I wonder if it's a bit surprising and changing the default, as part of a breaking-change 2.0 release, might be the way to go?
I could see the :noop
transform being a sensible default. Then only if you're using CloudWatch Log Metrics, or L2Met, would you need to opt for a different transform. Thoughts?
51cd788
to
cfba3e3
Compare
|
||
* `:json` _(default)_ - Print the logs in JSON. | ||
* `:logfmt` - Print the logs in key/value pairs, as per `logfmt`. | ||
* `:noop` - A NOOP formatter which returns the telemetry `Hash` unaltered, passing it directly to the `io:` instance. |
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'm not sure I fully like the name noop, I think passthrough might be a better option for naming, but I'm really open minded about this
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 don't really love it either. :passthrough
seems a reasonable alternative to me. Anyone have other alternatives or thoughts?
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.
Any further thoughts? I'm happy to rename to :passthrough
; it is a bit more explicit of how it's not doing anything. 😄
First of all, thanks again for the contribution 👊 I really like the modularity and concepts you've introduced here. However, I feel this PR is bringing in quite a few changes, and I'm not fully sold on some of them yet. If you're open for it, I would propose you to split this PR into 3 separate PRs:
I think this contribution would make it for an awesome base, and people could start using their transformers without forking the code, and without constant rebasing, therefore reducing overall maintenance. Does this approach make sense to you? I'm happy to discuss further! |
@unsign3d yeah, if you'd rather see it broken up (1 & 2) and then potentially pass on the FWIW, if this was accepted my plan was to then work on adding the right amount of |
@stevenharman that sounds good :) |
Happy to take this to a different medium (GitHub Discussions?), but the gist on L2Met is it was primarily created/evolved as a way to emit metrics via log streams. The largest use case I know of is Librato (now SolarWinds), and it's pretty much the current standard for anything deployed to Heroku. That happens to be where all of our stuff is deployed, and we're currently using Librato. Hence, the need/desire for these logs to be emitted in L2Met format. Does it belong in the main repo? I don't have a particularly strong opinion either way. That said, it's extremely stable (and pretty much in maintenance mode), and I'd expect very little carrying cost for this repo. It's also such a simple |
Let's start by pushing it to upstream, and then if it becomes too much maintenance we can create a new major and move it into a plugin :) |
Making the formatter available outside the IOTarget means other targets can also use it. This will be helpful when I add a LogTarget. This also adds some very basic tests (for my own sanity) for the IOTarget and JSONFormatter classes.
As it was, the formatters were doing both transforms on the keys (specific to a particular service) AND formatting the telemetry data. By separating those responsibilities, we can mix and match different Targets, Formatters, and Transforms to get the output needed for different consumers.
This also extracts a shared BaseFormattingTarget to consolidate translating options.
This is useful when using a custom logger: with the LogTarget. For example, a `Logfmt::Logger` logger will take a Hash and correctly format it to the Logfmt format. When using that logger in a Rails app, this allows this plugin's config to look like this: ```ruby Puma::Plugin::Telemetry.configure do |config| config.add_target(:log, logger: Rails.logger, transform: :l2met, formatter: :noop) end ``` see: https://github.com/cyberdelia/logfmt-ruby?tab=readme-ov-file#writing-log-lines
It will pull from the ENV `L2MET_SOURCE` and then `DYNO`, falling back to building a string based on the current Host name and executing program name.
cfba3e3
to
d904b84
Compare
This builds atop #20. If/when it's merged, I'll rebase these changes atop
main
to make these changes more clear.This PR adds a new
LogTarget
, and splits outFormatters
andTransforms
into their own objects, so they can be mixed and matched. TheLogTarget
defaults to using the Ruby stdlib::Logger
pointed at$stdout
, using an Logfmtformatter
. We can then use the new L2Met transform to get the metrics in our logs, exactly as we need them!These also work with the
IOTarget
:The default
formatter:
andtransform:
options forIOTarget
keep it backward compatible with the way that target worked before.I've tried to make each step along the way an atomic commit. It might be helpful to quickly look commit-by-commit if you're curious. Or not - most of the churn is just reorganizing the code that was here.
Phew! Thanks so much for this tooling, and for your consideration.