Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In java streams using .peek() is regarded as to be used for debugging purposes only, would logging be considered as debugging? [duplicate]

So I have a list of objects which I want part or whole to be processed, and I would want to log those objects that were processed.

consider a fictional example:

List<ClassInSchool> classes;
classes
.stream()
.filter(verifyClassInSixthGrade())
.filter(classHasNoClassRoom())
.peek(classInSchool -> log.debug("Processing classroom {} in sixth grade without classroom.", classInSchool)
.forEach(findMatchingClassRoomIfAvailable());

Would using .peek() in this instance be regarded as unintended use of the API?

To further explain, in this question the key takeaway is: "Don't use the API in an unintended way, even if it accomplishes your immediate goal." My question is whether or not every use of peek, short from debugging your stream until you have verified the whole chain works as designed and removed the .peek() again, is unintended use. So if using it as a means to log every object actually processed by the stream is considered unintended use.

like image 916
Jonas Avatar asked Jan 28 '19 05:01

Jonas


3 Answers

The documentation of peek describes the intent as

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline.

An expression of the form .peek(classInSchool -> log.debug("Processing classroom {} in sixth grade without classroom.", classInSchool) fulfills this intend, as it is about reporting the processing of an element. It doesn’t matter whether you use the logging framework or just print statements, as in the documentation’s example, .peek(e -> System.out.println("Filtered value: " + e)). In either case, the intent matters, not the technical approach. If someone used peek with the intent to print all elements, it would be wrong, even if it used the same technical approach as the documentation’s example (System.out.println).

The documentation doesn’t mandate that you have to distinguish between production environment or debugging environment, to remove the peek usage for the former. Actually, your use would even fulfill that, as the logging framework allows you to mute that action via the configurable logging level.

I would still suggest to keep in mind that for some pipelines, inserting a peek operation may insert more overhead than the actual operation (or hinder the JVM’s loop optimizations to such degree). But if you do not experience performance problems, you may follow the old advice to not try to optimize unless you have a real reason…

like image 192
Holger Avatar answered Nov 15 '22 18:11

Holger


Peek should be avoided as for certain terminal operations it may not be called, see this answer. In that example it would probably be better to do the logging inside the action of forEach rather than using peek. Debugging in this situation means temporary code used for fixing a bug or diagnosing an issue.

like image 30
tterrag Avatar answered Nov 15 '22 17:11

tterrag


In java streams using .peek() is regarded as to be used for debugging purposes only, would logging be considered as debugging?

It depends on whether your logging code is going to be a permanent fixture of your code, or not.

Only you can really know the real purpose of your logging ...

Also note that the javadoc says:

In cases where the stream implementation is able to optimize away the production of some or all the elements (such as with short-circuiting operations like findFirst, or in the example described in count()), the action will not be invoked for those elements.

So, you are liable to find that in some circumstances peek won't be a reliable way to log (or debug) your pipeline.

In general, adding peek is liable to change the behavior of the pipeline and / or the JVM's ability to optimize it ... in a current or future generation JVM.

like image 34
Stephen C Avatar answered Nov 15 '22 16:11

Stephen C