google / jsonnet

Jsonnet - The data templating language
http://jsonnet.org
Apache License 2.0
6.99k stars 440 forks source link

[feature request] Hide std.jsonnet in tracebacks #673

Open ekimekim opened 5 years ago

ekimekim commented 5 years ago

Many of the functions in the stdlib result in a large number of stack frames.

In some circumstances, usage of foldl, comprehensions, etc, can cause the vast majority of a large stack trace to be std.jsonnet frames only.

In one example we've encountered, the stack trace looked like so:

    std.jsonnet:731:15-42   thunk <val>
    std.jsonnet:736:27-30   thunk <val>
    std.jsonnet:560:22-25   thunk <a>
    std.jsonnet:36:17   
    std.jsonnet:36:8-19 thunk <a>
    std.jsonnet:36:8-31 function <anonymous>
    std.jsonnet:36:8-31 function <anonymous>
    std.jsonnet:560:9-26    function <format_code>
    std.jsonnet:736:15-50   thunk <s>
    std.jsonnet:741:24  thunk <str>
    std.jsonnet:475:30-33   
    std.jsonnet:475:19-34   thunk <w>
    std.jsonnet:471:11  thunk <w>
    std.jsonnet:467:12  function <aux>
    std.jsonnet:471:7-17    function <padding>
    std.jsonnet:475:7-38    function <pad_left>
    std.jsonnet:741:15-35   thunk <s_padded>
    std.jsonnet:742:51-59   thunk <v>
    std.jsonnet:742:11-60   function <format_codes_obj>
    std.jsonnet:742:11-60   function <format_codes_obj>
    std.jsonnet:747:7-43    function <anonymous>
    std.jsonnet:227:7-23    function <anonymous>
    <user code> thunk <failures>
    <user code> object <obj>
    std.jsonnet:729:15-21   thunk <val>
    std.jsonnet:736:27-30   thunk <val>
    std.jsonnet:560:22-25   thunk <a>
    std.jsonnet:36:17   
    std.jsonnet:36:8-19 thunk <a>
    std.jsonnet:36:8-31 function <anonymous>
    std.jsonnet:36:8-31 function <anonymous>
    std.jsonnet:560:9-26    function <format_code>
    std.jsonnet:736:15-50   thunk <s>
    std.jsonnet:741:24  thunk <str>
    std.jsonnet:475:30-33   
    std.jsonnet:475:19-34   thunk <w>
    std.jsonnet:471:11  thunk <w>
    std.jsonnet:467:12  function <aux>
    std.jsonnet:471:7-17    function <padding>
    std.jsonnet:475:7-38    function <pad_left>
    std.jsonnet:741:15-35   thunk <s_padded>
    std.jsonnet:742:51-59   thunk <v>
    std.jsonnet:742:11-60   function <format_codes_obj>
    std.jsonnet:742:11-60   function <format_codes_obj>
    std.jsonnet:747:7-43    function <anonymous>
    std.jsonnet:227:7-23    function <anonymous>
    <user code> object <patch>
    std.jsonnet:1161:66-74  thunk <a>
    std.jsonnet:1161:66-82  function <anonymous>
    std.jsonnet:1161:66-82  thunk <null_fields>
    std.jsonnet:1172:43-54  thunk <b>
    std.jsonnet:1151:12 thunk <b>
    std.jsonnet:1151:5-24   function <aux>
    std.jsonnet:1151:5-24   function <anonymous>
    std.jsonnet:1172:18-55  thunk <a>
    std.jsonnet:(1164:7)-(1173:8)   function <anonymous>
    std.jsonnet:(1164:7)-(1173:8)   function <anonymous>
    std.jsonnet:1169:13-43  object <args>
    <user code>
    <user code> thunk <a>
    <user code> function <anonymous>
    <user code> thunk <targets_as_list>
    <user code> thunk <a>
    <user code> function <anonymous>
    <user code> thunk <resolved_target_values>
    <user code> thunk <arr>
    std.jsonnet:765:15-18   thunk <arr>
    std.jsonnet:761:28-31   
    std.jsonnet:761:17-32   function <aux>
    std.jsonnet:765:5-28    function <anonymous>
    <user code> object <anonymous>
    <user code> thunk <array_element>
    <user code> object <anonymous>
    <user code> thunk <array_element>
    <user code> <anonymous>

which makes the actual problems in user code extremely difficult to find among the noise.

(this particular case was a format string error, similar to "%(foo)s" % {bar: ""})

Users are almost never interested in the details of the call path through std.jsonnet when debugging their code.

It would be extremely handy to have an option to evaluate_file() (we're using the python bindings, but I'd expect this could be applied generally) to elide all but the first and last frame in a sequence of std.jsonnet frames. The above stack trace would then look like:

    std.jsonnet:731:15-42   thunk <val>
    ...
    std.jsonnet:227:7-23    function <anonymous>
    <user code> thunk <failures>
    <user code> object <obj>
    std.jsonnet:729:15-21   thunk <val>
    ...
    std.jsonnet:227:7-23    function <anonymous>
    <user code> object <patch>
    std.jsonnet:1161:66-74  thunk <a>
    ...
    std.jsonnet:1169:13-43  object <args>
    <user code>
    <user code> thunk <a>
    <user code> function <anonymous>
    <user code> thunk <targets_as_list>
    <user code> thunk <a>
    <user code> function <anonymous>
    <user code> thunk <resolved_target_values>
    <user code> thunk <arr>
    std.jsonnet:765:15-18   thunk <arr>
    ...
    std.jsonnet:765:5-28    function <anonymous>
    <user code> object <anonymous>
    <user code> thunk <array_element>
    <user code> object <anonymous>
    <user code> thunk <array_element>
    <user code> <anonymous>

We can implement this ourselves in our tooling that wraps the evaluate_file() call, but it would be very handy to have supported by jsonnet natively.

sbarzowski commented 5 years ago

I see, it could be quite cool.

Perhaps it could be even more general and allow distinguishing between "your code" and "third party code" somehow (with stack trace reduced for third party code, not only for stdlib in particular).

Thanks for the suggestion!