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

add stdout log record exporter #6675

Merged
merged 47 commits into from
Sep 18, 2024

Conversation

zeitlinger
Copy link
Member

split off from #6632 - only for logs, and no memory mode

@zeitlinger zeitlinger requested a review from a team August 27, 2024 07:35
Copy link

codecov bot commented Aug 27, 2024

Codecov Report

Attention: Patch coverage is 88.59649% with 13 lines in your changes missing coverage. Please review.

Project coverage is 90.09%. Comparing base (8fb169e) to head (44de5ea).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...logging/otlp/internal/writer/StreamJsonWriter.java 81.25% 5 Missing and 1 partial ⚠️
...logging/otlp/internal/writer/LoggerJsonWriter.java 78.94% 4 Missing ⚠️
...tlp/internal/logs/OtlpStdoutLogRecordExporter.java 92.85% 1 Missing and 1 partial ⚠️
...logging/otlp/OtlpJsonLoggingLogRecordExporter.java 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##               main    #6675   +/-   ##
=========================================
  Coverage     90.09%   90.09%           
- Complexity     6390     6423   +33     
=========================================
  Files           711      717    +6     
  Lines         19333    19422   +89     
  Branches       1891     1894    +3     
=========================================
+ Hits          17418    17499   +81     
- Misses         1335     1341    +6     
- Partials        580      582    +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@zeitlinger zeitlinger self-assigned this Aug 27, 2024
@zeitlinger zeitlinger mentioned this pull request Aug 27, 2024
@zeitlinger
Copy link
Member Author

@jack-berg can you take a look?

@jack-berg
Copy link
Member

Thanks for breaking out - this was more manageable to review.

@zeitlinger
Copy link
Member Author

zeitlinger commented Aug 29, 2024

@jack-berg thanks for the thorough review - I hope I've addressed everything

(build fails because of link checker)

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

We've got to get the delegation model right. We have a new OtlpStdoutLogRecordExporter / OtlpStdOutLogRecordExporterBuilder which we think is going to be the standard going forward, but is internal and experimental for this. This supports a variety of configuration options, include the ability to specify your own output stream and wether you want the "wrapper json object". The old OtlpJsonLoggingLogRecordExporter is just a OtlpStdoutLogRecordExporter with a very specific configuration which is non-configurable. This means that OtlpJsonLoggingLogRecordExporter should delegate to OtlpStdoutLogRecordExporter, since OtlpStdoutLogRecordExporter is a superset of the capabilities of OtlpJsonLoggingLogRecordExporter.

Its flipped right now and I think its requiring some wonky stuff with reflection which makes this more complicated that it needs to be. This is hard to communicate via comments, so I sketched it out quickly in a commit. Note the tests don't pass yet, but I think those have an unnecessary abstract class, as I've mentioned in comments.

jack-berg@7e40c2e

@zeitlinger
Copy link
Member Author

Its flipped right now and I think its requiring some wonky stuff with reflection which makes this more complicated that it needs to be.

I really like the solution you found! I'll use it. 💯

Note the tests don't pass yet

You can't set the builder to use a logger.
The tests pass once setLogger is added.

@zeitlinger
Copy link
Member Author

@jack-berg all suggestions incorporated now 😄

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

Looks pretty good! Smaller number of lingering questions. I made it all the way through the code this time so I think this is likely the last set of comments to resolve.

buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts Outdated Show resolved Hide resolved

public StreamJsonWriter(OutputStream originalStream, String type) {
this.originalStream = originalStream;
this.outputStream = new IgnoreCloseOutputStream(originalStream);
Copy link
Member

Choose a reason for hiding this comment

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

What's going on here? What close are we trying to ignore?

Also, what do you think in general about the resource management of the output stream? Should OtlpStdoutLogRecordExporter be responsible for calling OutputStream.close()? I think probably yes, since otherwise it would be complicated for a user to detect shutdown and close the output stream themselves. On the otherhand, closing System.out is not correct. I wonder if we need a boolean configuration option to indicate whether the OutputStream should be closed on LogRecordExporter#shutdown():

setOutputStream(os, true);

Copy link
Member Author

Choose a reason for hiding this comment

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

very good point - there's not even a test for using a file.

Copy link
Member Author

Choose a reason for hiding this comment

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

turned out that we can skip the boolean flag if we just call flush in close

Copy link
Member

Choose a reason for hiding this comment

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

Flushing on close will ensure that any unwritten bytes are flushed to the outputstream, but doesn't allow any outputstream resources to be released on shutdown.

Copy link
Member Author

Choose a reason for hiding this comment

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

we could call close on shutdown instead - but maybe that's too surprising

another option is that we specifically check for System.out and System.err - and only then not call close (I like that).

Copy link
Member

Choose a reason for hiding this comment

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

we could call close on shutdown instead - but maybe that's too surprising

That was my point with adding a boolean on setOutputStream where the user could specify whether they want to be responsible for closing the stream or if they want the exporter to be responsible.

another option is that we specifically check for System.out and System.err

True.. That would probably cover most of the cases. But I wonder if there are other cases where you would want to skip closing the OutputStream. We could always start with this suggestion and later add a boolean overload to setOutputStream if needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

another option is that we specifically check for System.out and System.err

I implemented this now

Copy link
Member

Choose a reason for hiding this comment

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

I see code in IgnoreCloseOutputStream#close() which checks if the stream is System.out or System.err, but I don't see where close() is being called anywhere in OtlpStdoutLogRecordExporter#shutdown().

Also, we should add javadoc to OtlpStdoutLogRecordExporterBuilder#setOutput(OutputStream) which indicates that the stream will be closed if its not System.out or System.err.

Copy link
Member Author

Choose a reason for hiding this comment

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

Great catch - I also found a better way to implement this I hope.

I couldn't find where flush is being called - and if I need to flush the stream manually.

Copy link
Member Author

Choose a reason for hiding this comment

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

@zeitlinger
Copy link
Member Author

@jack-berg please have another look

if you're ok with a separate experimental module, let me know which module would be appropriate

@zeitlinger
Copy link
Member Author

@jack-berg please have another look 😄

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

Blocking on this comment: #6675 (comment)

Otherwise, just a few nits.

@zeitlinger
Copy link
Member Author

Blocking on this comment: #6675 (comment)

Otherwise, just a few nits.

blocker is resolved @jack-berg 😄

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

Some nits, but 👍

zeitlinger and others added 4 commits September 11, 2024 17:26
…/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java

Co-authored-by: jack-berg <[email protected]>
…/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java

Co-authored-by: jack-berg <[email protected]>
@jack-berg jack-berg merged commit d899702 into open-telemetry:main Sep 18, 2024
18 checks passed
@zeitlinger
Copy link
Member Author

thanks @jack-berg - should I add the other signals next, or the memory mode for logs?

@jack-berg
Copy link
Member

No preference from me

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.

3 participants