Replace ::Mux.var"***" closure types from stacktraces with a simple ::MuxClosure "type"
This pr provides a prettystderrcatch middleware that removes the unreadable closure type and replaces that with a fancy ::MuxClosure.
Also uses the cleaning in the basiccatch function.
Another approach toward #87 can be to remove the stackframes with ::MuxClosures completely, but this is more invasive.
Thanks for looking into this! Could you paste in here an example stack trace with and without this PR?
There you go:
Example stack
Before
KeyError: key :test13 not found
Stacktrace:
[1] getindex
@ ./dict.jl:481 [inlined]
[2] test
@ ./REPL[10]:3 [inlined]
[3] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[4] prettystderrcatch(app::Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}, req::Dict{Any, Any})
@ Main ./REPL[14]:4
[5] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[6] beautifulStacktrace(app::Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}, req::Dict{Any, Any})
@ Main ./REPL[12]:4
[7] (::Mux.var"#1#2"{typeof(beautifulStacktrace), Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}})(x::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[8] (::Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#46#49"{Bool, Mux.var"#absdir#48"{Vector{String}}}, Mux.var"#47#50"{Mux.var"#absdir#48"{Vector{String}}}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}})(f::Function, x::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:17
[9] (::Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#46#49"{Bool, Mux.var"#absdir#48"{Vector{String}}}, Mux.var"#47#50"{Mux.var"#absdir#48"{Vector{String}}}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{typeof(beautifulStacktrace), Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}}})(x::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[10] (::Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#51#54"{Bool, Mux.var"#absdir#53"}, Mux.var"#52#55"{Mux.var"#absdir#53"}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}})(f::Function, x::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:17
[11] (::Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#51#54"{Bool, Mux.var"#absdir#53"}, Mux.var"#52#55"{Mux.var"#absdir#53"}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#46#49"{Bool, Mux.var"#absdir#48"{Vector{String}}}, Mux.var"#47#50"{Mux.var"#absdir#48"{Vector{String}}}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{typeof(beautifulStacktrace), Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}}}})(x::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[12] toresponse(app::Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#51#54"{Bool, Mux.var"#absdir#53"}, Mux.var"#52#55"{Mux.var"#absdir#53"}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#46#49"{Bool, Mux.var"#absdir#48"{Vector{String}}}, Mux.var"#47#50"{Mux.var"#absdir#48"{Vector{String}}}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{typeof(beautifulStacktrace), Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}}}}, req::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/basics.jl:49
[13] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[14] splitquery(app::Mux.var"#1#2"{typeof(Mux.toresponse), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#51#54"{Bool, Mux.var"#absdir#53"}, Mux.var"#52#55"{Mux.var"#absdir#53"}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#46#49"{Bool, Mux.var"#absdir#48"{Vector{String}}}, Mux.var"#47#50"{Mux.var"#absdir#48"{Vector{String}}}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}, Mux.var"#1#2"{typeof(beautifulStacktrace), Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}}}}}, req::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/basics.jl:31
[15] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#51#54"{Bool, Mux.var"#absdir#53"}, Mux.var"#52#55"{Mux.var"#absdir#53"}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}, Mux.var"#5#6"{Mux.var"#31#32"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#46#49"{Bool, Mux.var"#absdir#48"{Vector{String}}}, Mux.var"#47#50"{Mux.var"#absdir#48"{Vector{String}}}}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}, Mux.var"#1#2"{typeof(beautifulStacktrace), Mux.var"#1#2"{typeof(prettystderrcatch), Mux.var"#1#2"{typeof(test), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{Any}}, Mux.var"#23#24"{String}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#37#38"{Float64}, Mux.var"#23#24"{String}}, Mux.var"#23#24"{String}}}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#33#34"{Vector{SubString{String}}}, var"#5#7"}, Mux.var"#1#2"{Mux.var"#21#22"{Mux.var"#25#26"{Symbol, Int64}}, Mux.var"#23#24"{String}}}}}}}}})(x::HTTP.Messages.Request) @ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[21] (::Mux.var"#7#8"{Mux.App})(req::HTTP.Messages.Request)
@ Mux ~/.julia/packages/Mux/3h8RY/src/server.jl:42
[22] handle
@ ~/.julia/packages/HTTP/5e2VH/src/Handlers.jl:254 [inlined] [23] handle(::HTTP.Handlers.RequestHandlerFunction{Mux.var"#7#8"{Mux.App}}, ::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}) @ HTTP.Handlers ~/.julia/packages/HTTP/5e2VH/src/Handlers.jl:277 [24] #4 @ ~/.julia/packages/HTTP/5e2VH/src/Handlers.jl:346 [inlined] [25] macro expansion
@ ~/.julia/packages/HTTP/5e2VH/src/Servers.jl:413 [inlined]
[26] (::HTTP.Servers.var"#13#14"{HTTP.Handlers.var"#4#5"{HTTP.Handlers.RequestHandlerFunction{Mux.var"#7#8"{Mux.App}}}, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}, HTTP.Servers.Server{Nothing, Sockets.TCPServer}, HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}})()
@ HTTP.Servers ./task.jl:411
After
KeyError: key :test13 not found
Stacktrace:
[1] getindex
@ ./dict.jl:481 [inlined]
[2] test
@ ./REPL[2]:3 [inlined]
[3] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[4] prettystderrcatch(app::MuxClosure, ::Dict{Any, Any})
@ Main ./REPL[6]:4
[5] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[6] beautifulStacktrace(app::MuxClosure, ::Dict{Any, Any})
@ Main ./REPL[4]:4
[7] (::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[8] (::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:17
[9] (::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[10] (::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:17
[11] (::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[12] toresponse(app::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/basics.jl:49
[13] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[14] splitquery(app::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/basics.jl:31
[15] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[16] basiccatch(app::MuxClosure, ::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/3h8RY/src/basics.jl:80
[17] #1
@ ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10 [inlined]
[18] todict(app::MuxClosure, ::HTTP.Messages.Request)
@ Mux ~/.julia/packages/Mux/3h8RY/src/basics.jl:25
[19] (::MuxClosure, ::HTTP.Messages.Request) (repeats 5 times)
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:14
[20] (::MuxClosure, ::HTTP.Messages.Request)
@ Mux ~/.julia/packages/Mux/3h8RY/src/Mux.jl:10
[21] (::MuxClosure, ::HTTP.Messages.Request)
@ Mux ~/.julia/packages/Mux/3h8RY/src/server.jl:42
[22] handle
@ ~/.julia/packages/HTTP/5e2VH/src/Handlers.jl:254 [inlined]
[23] handle(::HTTP.Handlers.RequestHandlerFunction{MuxClosure, ::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}})
@ HTTP.Handlers ~/.julia/packages/HTTP/5e2VH/src/Handlers.jl:277
[24] #4
@ ~/.julia/packages/HTTP/5e2VH/src/Handlers.jl:346 [inlined]
[25] macro expansion
@ ~/.julia/packages/HTTP/5e2VH/src/Servers.jl:413 [inlined]
[26] (::HTTP.Servers.var"#13#14"{HTTP.Handlers.var"#4#5"{HTTP.Handlers.RequestHandlerFunction{Mux.var"#7#8"{Mux.App}}}, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}, HTTP.Servers.Server{Nothing, Sockets.TCPServer}, HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}})()
@ HTTP.Servers ./task.jl:411
It incorrectly transforms some closure that look like this (::MuxClosure)(app::Dict) to (::MuxClosure)(app::Dict) - but I think that's as far as a regex goes.
This is awesome! We'll definitely want a simple test for this, just to make sure it doesn't break.
Also, is it possible to do this without a regex, by inspecting the stackframes directly?
Also, is it possible to do this without a regex, by inspecting the stackframes directly?
I'm not sure I understand - can you say more?
This is awesome! We'll definitely want a simple test for this, just to make sure it doesn't break.
Sure, will update he code.
I'm not sure I understand - can you say more?
You call catch_backtrace(), which returns a data structure that can be inspected (before turning it into a String) for specific details about each error frame. You could grab the called closure+function from each frame, and just extract the contained function exactly, and then render that instead.
Of course, this might be more work than it's worth. I'm personally fine with the current approach; we can always improve its accuracy in another PR.
Closed in #157. Thanks for suggesting this approach!