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

Allow logging to a file (besides logging to the console) #1023

Closed
dhendriks opened this issue Feb 16, 2025 · 17 comments
Closed

Allow logging to a file (besides logging to the console) #1023

dhendriks opened this issue Feb 16, 2025 · 17 comments
Labels

Comments

@dhendriks
Copy link

According to the documentation at https://docs.asciidoctor.org/maven-tools/latest/plugin/goals/process-asciidoc/#configuration-logHandler, we can configure the logHandler. We can configure outputToConsole, by setting it to true or false. However, I'd like to log to both the console and to a file (to generate a composite report of all problems of various Maven plugins/goals). Could an option named outputFile be added for the logHandler, that gives the path to the output file, such that logging is (also) written there?

What do you think?

@abelsromero
Copy link
Member

I assumed this could be done with common shell tools like tee. Isn't that an option?

@dhendriks
Copy link
Author

A problem is that I then need to go parse Maven output/logs in a reliable way. If I just get the problems/output logged by this plugin, in the target folder of the particular project that is part of a multi-project build, that is much easier and more reliable.

Also, the aggregate reporter is a Maven plugin executed during the same build, so it would need to read a file that is currently being written, which could also cause problems.

And it would mean that whoever/whatever calls the build needs to tee to a specific path that we then know during the build and pick up. If that doesn't tee, the file doesn't exist and the build crashes. In an open-source project I'd prefer if mvn clean verify just works, to lower the threshold for contributions.

@abelsromero
Copy link
Member

abelsromero commented Feb 17, 2025

Not saying no outright, but outputting to a file won't work. I want to make sure the feature makes sense in the long term.

The main problem is that the current feature is not thought of as a reporting tool, instead, to fail-fast builds. We collect the messages for the latest converted doc and fail if there are any. If you have 10 files, and the first one is the one with errors, that's the only information you are going to get.
And I understand that's not the desired behavior here. Something structured should be generated, no need for HTML. But at least XML or JSON? (like junits).

The motivation was to ensure that if the build succeeds, it contains no errors (based on the configuration). In that regard, you can run mvn verify and be confident all is OK.

My assumptions for that approach were:

  1. Most errors should have been caught during writing.
    IDE plugins provide help for that. Or you can use auto-refresh, http plugin goals to get faster feedback loops with a 100% accurate conversion. Here, the user knows what is being modified and there's no need to report or convert all docs, any error should be related to something recently modified.
  2. process-asciidoc should be run for verification and final conversion in automated environments.
    I see how the current fail-fast is an issue, and having an option to not fail-fast makes sense, to be able to see all issues and fix them at once. But that's still a process that's based on plain output, not restructured reports.

I think those still hold. Can you explain more about the writing workflow? I don't mean to be rude, but I don't think the user is writing 3 or 4 pages, running a conversion, and then looking at a xml/json report 🙇

PD: there's some mention of multi-modules, I am not considering that, unless we go the rabbit hole of creating a reporting via maven-site. But that would complicate configuration for users imo.
PD2: as a workaround, one can add a custom LogHandler https://docs.asciidoctor.org/asciidoctorj/latest/logs-handling/#logs-handling-spi, the same way an extension and do whatever desired with the messages. But we'd still need to add a way to disable the fail-fast for sure.

@dhendriks
Copy link
Author

Thanks for listing your thoughts on this! Here are some replies to the points you raise:

  • Ideally, it would indeed collect all problems and not fail. Since you can already collect problems, and have configuration for which message severities fail the build, it shouln't be hard to collect them all and never fail, right?
  • XML or JSON output would be fine. Ideally, it includes not only the problem message, but also the file and position in the file (line/column).
  • Some people in our project use an AsciiDoc plugin for the Eclipse IDE. Some use a browser plugin. I don't know if the browser plugin reports any problems. The Eclipse-based editor does, but my experiences with it are mixed. Some people like to use plain text editors, or Vim, or what not. They focus on the text first, and only check how it is rendered later on. Typically, documentation is updated along with various other changes, like code and tests. Just running the build and collecting all problems is then useful, to be able to fix them all at once. There is no 'one size fits all' way of working in open source projects. People have their own way of working, and I can't force another way on them.
  • With multi-module, I just mean the following: we have a reactor with may projects, including multiple projects with documentation. Each is built separately using the AsciiDoctor Maven plugin's process-asciidoc goal. I would assume that since we render them separately, the problems will be reported separately. That is fine. I don't need the AsciiDoctor Maven plugin to collect all problems over multiple invocations of the process-asciidoc goal.
  • I'll try to find some time to experiment with a custom log handler. But, I agree it is more of a workaround than a proper solution.

@abelsromero
Copy link
Member

abelsromero commented Feb 24, 2025

Thanks, I'll have a look. Since it seems ppl use that as validation for local builds I'd not bother with formatting, same output we redirect to console should suffice.

This could be a dedicated goal run during verify phase. That would also allow having the configuration for the build and verification in the pom without needed profiles.
Not sure how code will look and I need to check if I can share state between goals, I don't like the idea of running the build twice.

Some people in our project use an AsciiDoc plugin for the Eclipse IDE.

Offtopic, I'd would suggest to give a try to the IDEA plugin. IMO the best experience and includes Antora support.

@dhendriks
Copy link
Author

[...] I'll have a look.

Thanks!

Offtopic, I'd would suggest to give a try to the IDEA plugin. IMO the best experience and includes Antora support.

We develop plugins for the Eclipse IDE, so we also do our development in the Eclipse IDE. I don't think people want to switch to another IDE just for the documentation.

@abelsromero
Copy link
Member

I was implementing the changes as a new mojo, and I see I am simply re-implementing the default behavior in a separate Mojo.
By default, not setting <logHandler> skips aborting on error and prints all messages for all files in the console like this:

[INFO] --- asciidoctor:3.1.1:process-asciidoc (asciidoc-to-html) @ asciidoc-to-html-example ---
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/example-manual.adoc
[INFO] asciidoctor: ERROR: document-with-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: WARN: document-with-errors.adoc: line 25: no callout found for <1>
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors.adoc
[INFO] asciidoctor: ERROR: document-with-errors-2.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors-2.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors-2.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: WARN: document-with-errors-2.adoc: line 25: no callout found for <1>
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-2.adoc

I don't see much value. By default, a user can see the file converted and the errors found in it (each error, shows the message and source line). The only things missing are:

The first is something the user can configure (aka, a docs issue), for the later, I am thinking about simply tuning when to fail. With a new failFast option, we could support:

  • "true" -> current behavior, will fail on first error and print the messages for that file.
  • "false" -> converts all files and prints all messages.

With the following, we can make the build and show all errors.

<logHandler>
    <outputToConsole>true</outputToConsole> 
    <failFast>true|false</failFast>
</logHandler>

@abelsromero
Copy link
Member

Looking for feedback here and taking notes for myself too.
Handling when and how to show the errors is a bit tricky and makes the code complicated if we want to split messages based on the file where they occur.

My current branch, prints all messages at the end of the conversion process.
So you see all the Converted {file} lines, then the errors, then the messages with the total number of errors at the end (see Found 17 issue(s) ...). Almost all errors show the file and line, the exception being the missing attributes due to how Asciidoctor core treats those cases (tldr, the callback does not get that data).
So I think we have covered the requirements.

[INFO] --- asciidoctor:3.1.2-SNAPSHOT:process-asciidoc (asciidoc-to-html) @ asciidoc-to-html-example ---
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/example-manual.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-23.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-22.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-2.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-23.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-23.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-23.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: WARN: document-with-errors-23.adoc: line 25: no callout found for <1>
[ERROR] asciidoctor: WARN: skipping reference to missing attribute: this-is-missing
[ERROR] asciidoctor: ERROR: document-with-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: WARN: document-with-errors.adoc: line 25: no callout found for <1>
[ERROR] asciidoctor: WARN: skipping reference to missing attribute: this-is-missing
[ERROR] asciidoctor: ERROR: document-with-errors-22.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-22.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-22.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: WARN: document-with-errors-22.adoc: line 25: no callout found for <1>
[ERROR] asciidoctor: WARN: skipping reference to missing attribute: this-is-missing
[ERROR] asciidoctor: ERROR: _mini-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/from-mini.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-2.adoc: line 7: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.267 s
[INFO] Finished at: 2025-03-02T22:53:38+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.asciidoctor:asciidoctor-maven-plugin:3.1.2-SNAPSHOT:process-asciidoc (asciidoc-to-html) on project asciidoc-to-html-example: Found 17 issue(s) of severity DEBUG or higher during conversion -> [Help 1]

For comparison, when not configuring to fail, that is, no <logHandler> block at all, errors are shown after the Converted {file} line, because in that case we print errors directly from the callback without buffering.

[INFO] --- asciidoctor:3.1.2-SNAPSHOT:process-asciidoc (asciidoc-to-html) @ asciidoc-to-html-example ---
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/example-manual.adoc
[INFO] asciidoctor: ERROR: document-with-errors-23.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors-23.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors-23.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: WARN: document-with-errors-23.adoc: line 25: no callout found for <1>
[INFO] asciidoctor: WARN: skipping reference to missing attribute: this-is-missing
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-23.adoc
[INFO] asciidoctor: ERROR: document-with-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: WARN: document-with-errors.adoc: line 25: no callout found for <1>
[INFO] asciidoctor: WARN: skipping reference to missing attribute: this-is-missing
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors.adoc
[INFO] asciidoctor: ERROR: document-with-errors-22.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors-22.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: ERROR: document-with-errors-22.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] asciidoctor: WARN: document-with-errors-22.adoc: line 25: no callout found for <1>
[INFO] asciidoctor: WARN: skipping reference to missing attribute: this-is-missing
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-22.adoc
[INFO] asciidoctor: ERROR: _mini-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/from-mini.adoc
[INFO] asciidoctor: ERROR: document-with-errors-2.adoc: line 7: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-2.adoc
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ asciidoc-to-html-example ---
[INFO] skip non existing resourceDirectory /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/main/resources
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

To get the same output, we'd need to buffer all information (log messages and filenames). The downsides are:

  • If some other unknown error happens, we get no output at all because the Maven process would abort.
  • All output Converted {file} + error lines will appear at the end. Once we have processed all files. Making Converted fake, that is, appearing not when the conversion has completed.
    For those reasons, I think the best approach is to maintain the current branch model.

@abelsromero
Copy link
Member

After doing some tests, I found more cases where no file is provided.
For that I am going to change the approach to capture the files during the build and add it when it's not provided by asciidoctor.

@dhendriks
Copy link
Author

PD2: as a workaround, one can add a custom LogHandler https://docs.asciidoctor.org/asciidoctorj/latest/logs-handling/#logs-handling-spi, the same way an extension and do whatever desired with the messages. But we'd still need to add a way to disable the fail-fast for sure.

I tried using a custom log handler. I also removed the <logHandler> configuration part in pom.xml completely. It then doesn't fail the build and reports all problems to my custom log handler and to the console. That is nice.

In the log handler, I don't know what the Maven project is that is being built. The Java current working directory is the root of the multi-module project. I couldn't figure out how to get the Maven session from the log handler. So, for now I solved that by writing with an Ant taks ${project.basedir} to ${maven.multiModuleProjectDirectory}/some_file.txt in the plugin that also runs AsciiDoctor, in a phase before AsciiDoctor is asked to run. I can then read that file in the log handler, once AsciiDoctor is kicked off afterwards in the same project. I can then determine the filename to which to write log records in my custom log handler, relative to that project.basedir path that I read from the file.

After doing some tests, I found more cases where no file is provided. For that I am going to change the approach to capture the files during the build and add it when it's not provided by asciidoctor.

I also noticed such cases while testing this.

@abelsromero
Copy link
Member

Thanks for the effort!
The current approach #1032 outputs all to the console with the config below.
As nice extras:

  • Sources as orderder before conversion, that should make the experience consistent across operating systems. Fun fact, not all OS return the files in the same order.
  • In the Maven Mojo we can capture what doc is being converted, and the filename is used as a fallback if the original error does not provide it. The only issue is when file A includes B, and an error in B does not return file, in that case, the message will show A, but I think it's better than nothing.
  <logHandler>
      <outputToConsole>false</outputToConsole>
      <failFast>false</failFast> <!-- 👈  the new option -->
      <failIf>
          <severity>DEBUG</severity>
      </failIf>
  </logHandler>

The output.

[INFO] --- asciidoctor:3.1.2-SNAPSHOT:process-asciidoc (asciidoc-to-html) @ asciidoc-to-html-example ---
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-2.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-22.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors-23.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/document-with-errors.adoc
[INFO] Converted /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/example-manual.adoc
[ERROR] asciidoctor: ERROR: _mini-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/from-mini.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-2.adoc: line 7: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-22.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-22.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-22.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: WARN: document-with-errors-22.adoc: line 25: no callout found for <1>
[ERROR] asciidoctor: WARN: document-with-errors-22.adoc: skipping reference to missing attribute: this-is-missing
[ERROR] asciidoctor: ERROR: document-with-errors-23.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-23.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors-23.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: WARN: document-with-errors-23.adoc: line 25: no callout found for <1>
[ERROR] asciidoctor: WARN: document-with-errors-23.adoc: skipping reference to missing attribute: this-is-missing-from_included
[ERROR] asciidoctor: ERROR: document-with-errors.adoc: line 3: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors.adoc: line 5: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: ERROR: document-with-errors.adoc: line 9: include file not found: /home/asalgadr/github/asciidoctor-maven-examples/asciidoc-to-html-example/src/docs/asciidoc/unexistingdoc.adoc
[ERROR] asciidoctor: WARN: document-with-errors.adoc: line 25: no callout found for <1>
[ERROR] asciidoctor: WARN: document-with-errors.adoc: skipping reference to missing attribute: this-is-missing
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.569 s
[INFO] Finished at: 2025-03-11T19:14:40+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.asciidoctor:asciidoctor-maven-plugin:3.1.2-SNAPSHOT:process-asciidoc (asciidoc-to-html) on project asciidoc-to-html-example: Found 17 issue(s) of severity DEBUG or higher during conversion -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

I think it covers alls, for human review we don't need a formatted ouput file.
My idea is to merge during the week and release on Saturday.

@dhendriks
Copy link
Author

In the log handler, I don't know what the Maven project is that is being built. [...]

I found another gotcha. In a multi-module Maven build, if you use AsciiDoctor multiple times, in different projects, still only one instance of the log handler is ever created by AsciiDoctorJ during the entire Maven build. I assumed I could determine the file to write to in the constructor of my log handler, thinking a new one would be created for every use of AsciiDoctor. However, since it is only created once, I have to determine the file to write to for each call to the log method. Not really great for performance, but it does work now.

@abelsromero
Copy link
Member

I found another gotcha. In a multi-module Maven build, if you use AsciiDoctor multiple times, in different projects, still only one instance of the log handler is ever created by AsciiDoctorJ during the entire Maven build.

Do you have a full project to reproduce? In theory that should not be possible because each execution creates a new instance of both Asciidoctor and LogHandler.

@abelsromero
Copy link
Member

Release v3.2.0 is out and should be available in Maven Central in a few minutes.

@dhendriks
Copy link
Author

I found another gotcha. In a multi-module Maven build, if you use AsciiDoctor multiple times, in different projects, still only one instance of the log handler is ever created by AsciiDoctorJ during the entire Maven build.

Do you have a full project to reproduce? In theory that should not be possible because each execution creates a new instance of both Asciidoctor and LogHandler.

I made this small test project: log-handler-test.zip

It has a project with a custom log handler. The constructor of this log handler prints Log handler created to stdout. Then it has two projects that run AsciiDoctor. If you look at the output of mvn clean verify, you'll see:

Click to expand Maven output
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] test.root                                                          [pom]
[INFO] test.loghandler                                                    [jar]
[INFO] test.proj1                                                         [pom]
[INFO] test.proj2                                                         [pom]
[INFO]
[INFO] ---------------------------< test:test.root >---------------------------
[INFO] Building test.root 1.0.0-SNAPSHOT                                  [1/4]
[INFO]   from pom.xml
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ test.root ---
[INFO]
[INFO] ------------------------< test:test.loghandler >------------------------
[INFO] Building test.loghandler 1.0.0-SNAPSHOT                            [2/4]
[INFO]   from test.loghandler\pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ test.loghandler ---
[INFO] Deleting <anonymized>\test.loghandler\target
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ test.loghandler ---
[INFO] Copying 1 resource from src\main\resources to target\classes
[INFO]
[INFO] --- compiler:3.11.0:compile (default-compile) @ test.loghandler ---
[INFO] Changes detected - recompiling the module! :source
[INFO] Compiling 1 source file with javac [debug release 17] to target\classes
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ test.loghandler ---
[INFO] skip non existing resourceDirectory <anonymized>\test.loghandler\src\test\resources
[INFO]
[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ test.loghandler ---
[INFO] No sources to compile
[INFO]
[INFO] --- surefire:3.1.2:test (default-test) @ test.loghandler ---
[INFO] No tests to run.
[INFO]
[INFO] --- jar:3.3.0:jar (default-jar) @ test.loghandler ---
[INFO] Building jar: <anonymized>\test.loghandler\target\test.loghandler-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --------------------------< test:test.proj1 >---------------------------
[INFO] Building test.proj1 1.0.0-SNAPSHOT                                 [3/4]
[INFO]   from test.proj1\pom.xml
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ test.proj1 ---
[INFO] Deleting <anonymized>\test.proj1\target
[INFO]
[INFO] --- asciidoctor:3.0.0:process-asciidoc (default) @ test.proj1 ---
Log handler created
[INFO] Converted <anonymized>\test.proj1\asciidoc\test.asciidoc
[INFO]
[INFO] --------------------------< test:test.proj2 >---------------------------
[INFO] Building test.proj2 1.0.0-SNAPSHOT                                 [4/4]
[INFO]   from test.proj2\pom.xml
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ test.proj2 ---
[INFO] Deleting <anonymized>\test.proj2\target
[INFO]
[INFO] --- asciidoctor:3.0.0:process-asciidoc (default) @ test.proj2 ---
[INFO] Converted <anonymized>\test.proj2\asciidoc\test.asciidoc
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for test.root 1.0.0-SNAPSHOT:
[INFO]
[INFO] test.root .......................................... SUCCESS [  0.147 s]
[INFO] test.loghandler .................................... SUCCESS [  1.457 s]
[INFO] test.proj1 ......................................... SUCCESS [  2.776 s]
[INFO] test.proj2 ......................................... SUCCESS [  0.634 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.130 s
[INFO] Finished at: 2025-03-29T20:26:39+01:00

Log handler created is only printed once, on the first invocation of AsciiDoctor.

@abelsromero
Copy link
Member

I see, AsciidoctorJ uses a ServiceLoader and since both executions run in the same thread it returns the same instance (even when there are two separated Asciidoctor instances) 🤔
Running in parallel (mvn -T 2 verify) works as expected since then each execution runs in a different thread.

I get the expectation is that it should behave the same in both cases (single-thread and parallel) but with the current model, it won't be possible on the plugin side. AsciidoctorJ should provide a way to make it so the LogHandler is instantiated when registered. Two quick ideas come to me now:

  1. Something similar to how we do it for extensions where the user can provide a registry.
  2. Add a way to provide a factory method.

@dhendriks may I ask you to open an issue in AsciidoctorJ? I can join the conversation and add more details if necessary.

@dhendriks
Copy link
Author

@dhendriks may I ask you to open an issue in AsciidoctorJ? I can join the conversation and add more details if necessary.

I've created asciidoctor/asciidoctorj#1297.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants