run-elm icon indicating copy to clipboard operation
run-elm copied to clipboard

Trim Debug.log from stdout?

Open kachkaev opened this issue 6 years ago • 4 comments

I noticed that if the Elm module we run produces any Debug output, run-elm's stdout does not look as expected. As a consequence, there is a chance that a script that uses this output can get unparsable data and crash.

Perhaps, we could solve this by introducing a new flag that --exclude-debug would trim any output that ends up in stdout before the value of the --output symbol. We may approach this by adding Debug.log "===== run-elm output start =====" to RunElmMain*.elm.template and call output.substring(...) later in JavaScript.

Current behaviour can remain default to avoid a breaking change.

Do there exist any other means to clutter stdout except Debug.log? What shall we do with Debug.crash?

I'm happy to add tests and submit a PR that covers these cases.

kachkaev avatar Mar 06 '18 14:03 kachkaev

As a temporary workaround I managed to encode the output variable into a JSON string and print it. Because this JSON is guaranteed not to have \n, I can throw away any other output by simply looking into stdoutLines[stdoutLines.length - 2]. I take length - 2 because length - 1 is an empty line in the end of stdout.

kachkaev avatar Mar 06 '18 19:03 kachkaev

I'm finding it hard to see why we should worry about Debug output. If a user includes it, then they are likely using it to debug a function, etc., so they need the debug output. If a user forgets to remove Debug from their code, then that's on them if the output looks weird.

Do you have a use case with an example that can help me understand why we would want this feature?

jfairbank avatar Mar 17 '18 20:03 jfairbank

IMO Debug.log and the value of an output symbol that we are trying to evaluate semantically belong to two different information channels. And so writing something into one of them should not affect the other.

Say I have this simple module that calculates a factorial:

module Factorial exposing (factorial)

import Debug exposing (log)

factorial : Int -> Int
factorial n =
    if n < 1 then
        1
    else
        -- factorial (n - 1) * n
        (log "value" (factorial (n - 1))) * (log "for n" n)

And another one that I use for run-elm:

module RunElm exposing (output)

import Factorial exposing (..)

output =
    toString <| factorial 10

When I execute run-elm RunElm.elm and see that the exit code is zero, I want to be sure I only get the value of 10! in stdout because otherwise there may be problems using it further in my pipeline.

Now given that I have temporary replaced factorial (n - 1) * n with (log "value" (factorial (n - 1))) * (log "for n" n) to test the internal logic of my Elm project, run-elm's stdout becomes:

value: 1
for n: 1
value: 1
for n: 2
value: 2
for n: 3
value: 6
for n: 4
value: 24
for n: 5
value: 120
for n: 6
value: 720
for n: 7
value: 5040
for n: 8
value: 40320
for n: 9
value: 362880
for n: 10
3628800

So, the result I expect to parse after checking the exit code is no longer an integer. If we had --exclude-debug option, there'd be an opportunity to wipe everything but the last line and thus avoid the issue. While in this mode, there'll be guarantee that any side-effects caused by Debug.log in any part of my program do not break the format of the output symbol we extract.

Technically, we can heal side effects from Debug.log by calling Debug.log ourselves and then trimming anything that gets printed before this special line. See my first comment for details.

kachkaev avatar Mar 17 '18 21:03 kachkaev

Wouldn't it be more elegant to simply pipe Debug.log to stderr?

Qu4tro avatar May 28 '21 17:05 Qu4tro