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

Include line info for steps that raise exceptions #77

Merged
merged 13 commits into from
Jul 29, 2021

Conversation

philomates
Copy link
Contributor

@philomates philomates commented Feb 3, 2020

An attempt to help address #74

Given a flow that raises an exception, like:

(ns state-flow.scratch
  (:require [state-flow.core :as state-flow]
            [state-flow.cljtest :refer [match?]]
            [state-flow.state :as state]))

(defn inc-a [s]
  (update s :a inc))

(defn change-state-buggy []
  (state/modify inc-a))

(state-flow/run!
  (state-flow/flow "buggy flow"
                   (change-state-buggy)
                   (match? "never run" 1 2)))

the result used to be like the following, which doesn't help pinpoint that (change-state-buggy) is the offending step:

                state-flow.state/reify/fn       state.clj:   63
                 state-flow.scratch/inc-a     scratch.clj:    7
                      clojure.core/update        core.clj: 6196
                         clojure.core/inc        core.clj:  927
                                      ...
java.lang.NullPointerException:

Syntax error (ExceptionInfo) compiling at (state_flow/scratch.clj:12:1).
Flow "buggy flow (scratch.clj:13)" failed with exception

With the changes in this PR:

                state-flow.state/reify/fn       state.clj:   63
                 state-flow.scratch/inc-a     scratch.clj:    7
                      clojure.core/update        core.clj: 6196
                         clojure.core/inc        core.clj:  927
                                      ...
java.lang.NullPointerException:

Syntax error (ExceptionInfo) compiling at (state_flow/scratch.clj:12:1).
Flow "buggy flow (scratch.clj:13) -> (change-state-buggy) (line 14)" failed with exception

Note:

we don't have line metadata info for variable references, so

(state-flow/run!
  (state-flow/flow "buggy flow"
                   change-state-buggy))

results in


Syntax error (ExceptionInfo) compiling at (state_flow/scratch.clj:12:1).
Flow "buggy flow (scratch.clj:13) -> change-state-buggy" failed with exception

@philomates philomates added the wip label Feb 3, 2020
`(m/do-let
(push-meta ~description ~flow-meta)
[ret# (m/do-let ~@flows')]
~@but-last-flows
~(push-abbr-meta last-flow)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

adding both the outer flow desc and the actual call sight info can be very useful. For example

(state-flow/run!
  (state-flow/flow "buggy flow"




                   (change-state-buggy)))

correctly shows

Syntax error (ExceptionInfo) compiling at (state_flow/scratch.clj:12:1).
Flow "buggy flow (line 13) -> `(change-stat...)` (line 18)" failed with exception

@philomates philomates removed the wip label Feb 4, 2020
@sovelten
Copy link
Collaborator

sovelten commented Feb 6, 2020

You can also do (flow "my-buggy-flow" (change-state-buggy)) whenever you need for debugging purposes and you would get correct line numbering then.

It seems like a better trade off than a complicated solution just to provide line number tracking for primitive steps.

@caioaao
Copy link
Contributor

caioaao commented Feb 20, 2020

This is a more contrived issue. I came across an interesting article about it, though, and might be a good direction to follow: https://pepeiborra.wordpress.com/2009/11/01/monadic-stack-traces-that-make-a-lot-of-sense/

I've only skimmed through the article, but the proposed solution is basically implementing an error monad that carries the stack trace

@philomates philomates force-pushed the pm/line-number-for-exceptions branch from cb5e314 to 640e2ee Compare June 23, 2021 08:29
@philomates
Copy link
Contributor Author

I've cleaned the implementation and it should be ready to review again

(or (= 'flow (first expr))
(= `flow (first expr)))))

(defn annote-with-line-meta [flows]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
(defn annote-with-line-meta [flows]
(defn annotate-with-line-meta [flows]


(testing "after nested flows complete"
(testing "within nested flows "
(is (re-matches #"level 1 \(core_test.clj:\d+\)"
(is (re-matches #"level 1 \(core_test.clj:\d+\) -> \(state-flow\/current-description\) \(line \d+\)"
Copy link
Contributor

Choose a reason for hiding this comment

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

If I run this I get

=> "level 1 (core_test.clj:2) -> (state-flow/current-description) (line 4)"

Where line 4 is coming from?

@gabrielgiussi
Copy link
Contributor

I couldn't find any test when a flow is throwing an exception and the line is included. I guess we are testing current-description instead and probably we use current-description when an exception is caught but then are not relaying on internal impl details? 🤔

Shouldn't we have a test covering the case where an exception is raised and we have line information?

@philomates
Copy link
Contributor Author

Thanks for the suggestion @gabrielgiussi, updated with a test

@philomates philomates merged commit b59ff03 into master Jul 29, 2021
@philomates philomates deleted the pm/line-number-for-exceptions branch July 29, 2021 14:23
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.

4 participants