I think part of the problem is that programmers rarely want to get into these supportive details; they just printf and get on with it.
I think part of the problem is that programmers rarely want to get into these supportive details; they just printf and get on with it.
I've been working on something like this that's language agnostic and works with not only tables but also trees, graphs, lists, hashmaps, etc., and animates the visuals as the data structures are modified in real time (and you can pause, playback, step, etc.): http://symbolflux.com/projects/avd
The api I was conceiving earlier was more complex, but if you read the copy there, you'll notice it's essentially the same now: `MObject.monitor(...)` or MTable.monitor() MStateMachine.monitor() etc.
Edit: really am happy to see some other projects like this in total, partly because I want to use 'em now if possible—but also because I've had a surprisingly hard time communicating to other developers why it might be desirable to do something like this in the first place, so I'll be very happy to have general awareness raised.
I read the first line of their docs as rather dry humor, "Displays tabular data as a table." —like yeah, of course you would want to see tabular data as a table, and hierarchical data as a tree, etc.!
To code the animations I use something in the engine which resembles CSS transitions and can be attached to arbitrary Java objects, which I call 'property modulators'. So most of the animation you see comes from setting up one of those on one property or another.
Since I've had such a difficult time communicating the potential benefit of the fully general piece of software, I've been exploring applications that I can build on top of it which do visualizations for more specific things (rather than leaving it to folks' imaginations to roam the wide possibilities of general data structure visualization :)).
As an example, my sister and I started building a 'code tutor' app in Electron, where you would be presented with problem sequences—but when you tested the code for your solution, you could watch what your algorithm actually did to the data (imagine a failed attempt to sort a list). This was the motivation for writing the javascript client. I integrated Lucidity's visuals by running it headless and streaming frames over TCP to the Electron app.
I think the next thing I'm gonna do though is just finish general object monitoring for the Java client, so that you could get something a little like the Chrome dev tools object printer in Java—but of course this one will allow you to watch algorithms performed on your objects :)
Btw, source for the (rather incomplete) javascript client is here if anyone's curious: https://github.com/westoncb/JS-Watcher
Actually part of how I see the role of systems like this is part of the necessary conditions for more safely working with mutable data. I think mutable data is more risky, but also super easy to work with, so if we had ways of making it more reliable we should explore them. I envision languages where this sort of visualization is a core feature designed in tandem with the runtime etc.
A small suggestion: Allow to not show so much.
A problem I have with most log-like solutions is that them bombard you with so much info and you need parse them after the fact, yet none of the log visualization have a way for that (just ctrlf, with luck).
A simple improvenment? Put a search box in top of the displayer, and a way to make contextual search, (like :tree.at Code.py), and a way to save search patterns, so I can put the whole search syntaxt and just fill boxes (like :mySearch foo)
Common Lisp and Smalltalk environments have something like console.table since its early days.
Xerox even went to the trouble of adding similar capabilities to the Mesa/Cedar enviroment, because they thought they should cater to their Interlisp-D and Smalltalk developers.
Java and .NET even allow to provide metadata so that debuggers know what is the best way to render the data in debug view.
Visual Studio allows similar capabilities for C++ via data visualizers.
Now if you insist in vim and Emacs, there is printf.
Also it has to do with IDE, because in an IDE there is two way communication between both tools, like the ability to do edit-and-continue.
It's not quite as fancy as an IDE, but it's a lot more than printf.
Here's a recording of using GDB's TUI mode: https://s.mort.coffee/d/vid/gdb-tui-demo.mp4
Note that I'm not a GDB pro, I just recently started trying to use it more instead of printf, so there are probably lots of stuff I didn't show off. (For example, I wish I'd shown the `bt` command to print stack traces).
Another thing that's worth noting is that with GDB, if your program crashed and generated a coredump, you can use GDB to look at how everything was when it crashed, just like if you were debugging a running program. This is extremely useful on for example embedded systems where you don't have GDB installed, or when the crash is hard to reproduce.
I don't know if you've tried it, but whenever you have a bit of time try Visual Studio's (or even Visual Studio Code's) debugger. They're among the best visual debuggers out there. Or IntelliJ's.
You see directly all the variables as you step through code, you can see array contents directly, they're super discoverable, etc.
It's such a shame that there's no glory (or money) to be had in designing CLI/TUIs. I also get the impression that it would be really hard to change things, OSS maintainers have a reputation for being very stubborn about workflow changes (sometimes for good reasons, sometimes not) :(
As for the data visualizers, as mentioned, with Java and .NET I can do it with a bit of annotations and the debugger takes it from there.
Or in C++'s case when using Visual Studio, a bit of XML describing the metadata.
BTW: In GDB, all commands have shortcuts i.e. 'b'=='break'. (Saves a lot of time).
Me, I'm lazy, so I lean on my tools to make my life easy. And there's some fantastic tooling out there; the biggest problem is usually discovering that a helpful feature exists and how to use it effectively.
They started to realize that there were many developers doing feature requests for stuff Visual Studio already supports.
I understand that what I did would be a bit close to a poor man's reversible debugger.
[0] https://gist.github.com/hadrianw/5b8d33a4b353c49e7dbd6eb55f8...
https://docs.microsoft.com/en-us/visualstudio/debugger/debug...
https://docs.microsoft.com/en-us/visualstudio/debugger/map-m...
Otherwise Intellitrace is the way to go.
https://docs.microsoft.com/en-us/visualstudio/debugger/intel...
#+BEGIN_SRC elisp
(list (list 'col1 'col2) (list 1 2))
#+END_SRC
(I don't use quote syntax to not confuse non-lispers)
Hitting C-c C-c on it produces the following block just below it: #+RESULTS:
| col1 | col2 |
| 1 | 2 |
With Org source blocks you can have a literate program even using multiple languages and still communicating easily between source code blocks and both generated and static tables. It can easily be intermixed with formatted text and exported to a suite of various formats, including plain text source code (so-called "tangled source").Edit: just for the sake of it, another example, this one in Python:
#+BEGIN_SRC python
return [[x for x in range(1,5)],
[chr(y) for y in range(ord('a'),ord('e'))]]
#+END_SRC
#+RESULTS:
| 1 | 2 | 3 | 4 |
| a | b | c | d |Freaking IBM had box drawing characters in freaking 1985, how hard is it to have them in 2018? https://www.ascii-codes.com/
See this:
┌─┬┐
│ ││
├─┼┤
└─┴┘
vs the crappy table.Beauty is in the eye of the beholder, true, but the majority of the beholders want a table to actually look like a table. If you give me pen and paper, I'm not going to draw weird half lines around the table, I'm going to draw the table first, line fully drawn everywhere and then add the content.
| Hello | Planet | Earth |
|-------+--------+-------|
| foo | 4 | 88 |
| bar | 265 | 123 |
|-------+--------+-------|
| sum | 269 | 211 |
This org table looks clean enough to me.The disadvantage of using box drawing characters is that they do not always align nicely - depending on the font, renderer, and couple other things. You can't go wrong with basic ASCII and a fixed-width display.
How do you type ┌─ ?
It's easier to use a font that renders "regular" keyboard characters as borders, akin to https://github.com/tonsky/FiraCode
Now if you insist in vim and Emacs, there is printf.
That's just plain wrong. GDB for example has had pretty printers for STL data structures for many years. Those operate on the underlying structure of the data types and you can write printers for your own data types pretty easily (gdb uses python for these).Apart from that, there is structured hierarchical logging, which seems to be on the way of becoming an industry standard and is considered best practice in some ecosystems (golang comes to mind)
No reason this couldn't be possible for Emacs, I guess nobody bothered. In particular, Common Lisp with SLIME already makes use of "presentations" in REPL, which nicely combine CL's print-object output with inspector/debugger capabilities.
Ultimately, no one limits you to printing out simple text. In various Lisp software I wrote, I ended up displaying profiling info inline in REPL, like this:
CHARTED-LET*
0 9.249
˫--------˧
SOME-VAR: 0.006 |
OTHER-VAR: 0.004 |
SOME-COMPUTATION: 2.036 |==.
A-SUMMARY: 0.062 |
DATA-FOR-A-CHART: 3.486 |====
SOME-BIG-COMPUTATION: 9.249 |==========
SOME-TREE-STUFF: 0.005 |
(EDIT: there were pretty Unicode characters in that output, but my browser / HN ate them. See https://github.com/tkych/cl-spark for how it should look like.)(all it took was a simple macro on top of a sparkline lib). I dumped custom execution stats out-of-band into a HTML file that, with little bit of static JS, rendered explorable charts. I've sent data straight into new Emacs buffers for processing, with a help of this simple macro:
https://gist.github.com/TeMPOraL/8715c9dd9837e0b601d1cdce059...
(can be trivially modified to make the new buffer automatically assume a given major-mode).
Point is, you don't have to limit yourself to simple, uninterpreted printfs. Write your own debugging tools! And while I'm not up to date with C#, most other languages and IDEs I've seen don't move beyond dumb printfs. Java definitely doesn't (hint: Grep Console is a very useful plugin to IntelliJ and Eclipse). And this Console.table() is just a visual gimmick. I'm actually disappointed that with all the capabilities for interactive HTML rendering, that's the best the Web standardized on so far.
─ info: GET /foo/endpoint
├─ info: user <user ID> valid auth
├─ info: request to service B
│ ├─ debug: opening new connection
│ ├─ debug: success, result = ...
│ └─ info: request took 1 seconds
├─ info: request to service B
│ ├─ debug: opening new connection
│ ├─ debug: success, result = ...
│ └─ info: request took 1 seconds
├─ info: preparing result took 1 seconds
└─ info: http request took 3 seconds
with the ability to hide sections, perhaps grep for only certain messages (particularly if you keep the formatting and the message separate, this should be doable, I think), attach metadata to messages…As it is, we have a fairly standard shove everything into syslog, and then pipe to a downstream logging system and a local file. But the downstream system is not very good at search (this is probably mostly our fault) and requires the message to be in JSON, so the stuff in the log file is _also_ JSON, b/c that's what syslog got. There are definitely better ways with our existing tools, but it sure makes one dream up what the perfect logging solution could look like.
A couple of places to look though:
- opentracing.io - Fonseca et al’s X-Trace work
I don’t have a link handy, and the visualizations haven’t aged well, but you can probably find a copy of my thesis or conference paper under Anthony Arkles in google scholar. I extended the X-Trace protocol a bit to make it easier to reassemble function calls that potentially had parallelism.
Assuming "everything" is "static log statements" which is the first issue I have with this, a developer must have thought before deployment that this could be useful, which usually results in a lot of useless garbage and a lack of actually useful information. And little by little you build up actually technically useful data collection, and rather than being spread throughout the codebase all of the probes are centralised and readable.
I've been thinking about using dynamic instrumentation tools (bcc/dtrace) for that purpose instead, you know you need something when you actually do need it, at that point you can add it to the probes/instrumentation (which is external to the program and deployable separately), and all information would be collected in a structured form in a database you can interact with (probably not something relational).
2. there are lots of systems having done this in production for many years, take a look at opencensus.io for googles open source version
Because you see the black console almost everywhere. We debug tabular or structured data in visual debugger, console or specialized snapshot-view that is not hard to create. All depends on programmer’s will to make their life easier. Console.table() is just one of the simplest things that you could write for yourself in dynamic language, but the fact that most web “devs” cared to read the docs only after it hit top of HN makes it look amazing.
>how poor most non-web debugging and logging
Praise the web.
Nonsense - web programming is inherently tied to the browser, which severely limits debugging and output options.
> The ability to mix and match data types and presentation format is extremely useful.
That's a common feature of dynamic type languages.
> Almost everywhere else we just have printf.
Most languages have logging libraries, and many have them built into the stdlib or runtime. Popular languages usually have many logging libraries to choose from.
> that’s printf going to stdout
Of course - printf(3) by definition "shall place output on the standard output stream stdout"[1]. If you want stderr or any other output stream, use fprintf(3).
#include <stdio.h>
int main() {
fprintf(stderr, "Error: %s\n", "LP0 on fire");
return 0;
}
Other languages usually handle that for you as part of the logging library.> there isn’t a universally deployed format
Sure there is: "text"[2].
> to even allow it to travel easily over the network
Copying files to a remote host is easy with scp. There are numerous ways to send data over a network. Web software is often more work as you have to move your debugging data/logs out of the browser first or use a specialized tool that does that for you. Sending program output realtime to a remote host only requires appending "| ssh ${host} \"${remote_cmd}\"" to your command.
> advanced viewers
That's great if you have specific needs and a viewer for your complex data structures, but the only universal solution is text. Fortunately, there are many tools available to handle structured data as text.
> I think part of the problem is that programmers rarely want to get into these supportive details; they just printf and get on with it.
I think you might want to explore the work programmers have done in other languages.
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/pr...
[2] http://www.catb.org/esr/writings/taoup/html/ch05s01.html
By printf I didn't _literally_ mean printf -- I meant any logging type equivalent whether that IS printf or a built-in logging system. The point is there's no inter-op between them with any rich detail, which prohibits universal log viewers.
When I say travel over the network, I don't mean scp. I mean allow my iOS/Raspberry Pi/local Erlang server device to stream in real-time it's logs to any viewer that I want, whether that's on the same device or somewhere else in the world. That's the kind of portability required when you can't guarantee that complex display can be part of the same system that generated it -- that's a unique quality of web browsers. IT'S ABOUT THE PROTOCOL, NOT THE MECHANISM.
Text is great, and most logs will be in text. But I also sometimes want to inspect data, or expand JSON, or view an image, etc etc. But let's even stick with text -- a good viewer would let me set up filters on a host of structured qualities -- filenames, lines, log levels, keywords, etc. It would output in a way that allows me to easily view such info in a UI that supports infinite scroll back, easy copy/paste, elegantly formats so different log instances are clearly separate from each other, adds color to enhance readability, allows me to hide/collapse sections or duplicate entries, provides columns for the structured logging fields like timestamps, allow interactive sorting on these columns like Excel, etc etc all without losing my data.
Apple's Console.app is an elementary example of what I'm suggesting I'd like to see. Except I don't want it tied to the syslogs of an Apple device. I want every language/platform to be able to output to it in real-time. And for it's capabilities to be as rich or richer than what we have in the browser. We already have universal text editors like VIM/Emacs -- why can't we have universal log viewers?
> I mean allow my iOS/Raspberry Pi/local Erlang server device to stream in real-time it's logs to any viewer that I want, whether that's on the same device or somewhere else in the world.
e.g. syslog (RFC5424)? -e- You can even add some extra fields of your choosing if you so desire: https://tools.ietf.org/html/rfc5424#section-6.3
> But let's even stick with text -- a good viewer would let me set up filters on a host of structured qualities -- filenames, lines, log levels, keywords, etc. It would output in a way that allows me to easily view such info in a UI that supports infinite scroll back, easy copy/paste, elegantly formats so different log instances are clearly separate from each other, adds color to enhance readability, allows me to hide/collapse sections or duplicate entries, provides columns for the structured logging fields like timestamps, allow interactive sorting on these columns like Excel, etc etc all without losing my data.
e.g. ELK, Graylog etc?
So, it sounds like you want a debugging library you can include in the language you are using to output structured debug lines and a client side that goes along with it to represent the usefully (or just use text+JSON and a JSON aware client), and to just stick it on top of syslog. I think that pretty much covers what you're asking for.
Except the most important thing: that ability to be included as standard, readily available, and well supported in languages.
Although in the end you probably aren't getting much out of it, as a dynamic language is fairly easy to just pump stuff through a JSON converter, and static/strongly typed ones probably require enough boilerplate that the added benefit is slight.
I get a console.table() equivalent in Python by using Jupyter Notebook, which is a web-based REPL shell, and pandas, which is a library for working with tabular data. Pandas displays HTML tables when used with Jupyter.
I reject your C-centric world for one of my own making. ;)
# perldoc -f printf | head -n3
printf FILEHANDLE FORMAT, LIST
printf FILEHANDLE
printf FORMAT, LIST
# perl -e 'printf STDERR "%0.2f\n", 2;' >/dev/null
2.00>Nonsense - web programming is inherently tied to the browser, which severely limits debugging and output options.
Web programming includes cli and server side tools (Node for one, JS testing tools, etc), has several first class logging SaaS and locally installed options, and even has stuff like the developer tools protocol, which allows one to debug Chrome running code in VS Code for example...
>That's a common feature of dynamic type languages.
That's merely an "ability", it's by no means a "common feature" in dynamic languages to have different output options in the example of e.g. console.table() (which itself is limited anyway).
>Copying files to a remote host is easy with scp.
That manual busywork is not what the parent asks for.
>That's great if you have specific needs and a viewer for your complex data structures, but the only universal solution is text.
You've just restated the problem -- only with a positive spin.
* Conditional Breakpoints
* Function breakpoints to add ad-hoc logging
* Show type information
* Ability to custom render state, a graph for instance.
* GUI to browse the state
* CLI to query the state
* Ability to alter state
* Multithread debugging support
* Record execution history and state so you can debug after the fact for hard non reproducible bugs.
* Remote debugging
* Support for network traffic debugging
Chrome developer tools will do all of these except
> * Record execution history and state so you can debug after the fact for hard non reproducible bugs.
^ Which would frankly be awesome. Various libraries provide their own userland support for this but it's all fragmented with hugely varying levels of quality and flexibility, but out of the box support would make me so happy (unless this already exists in which case, someone please enlighten me!).
DoodleDebug's output is HTML-based and interactive with semantic zoom. That means you can click parts of printed objects to inspect them.
However, I didn't work on it in years due to lack of time, and even the linked description page is a bit outdated (it's not an Eclipse plugin anymore).
[1]: http://scg.unibe.ch/wiki/projects/DoodleDebug [2]: https://github.com/CedricReichenbach/DoodleDebug
Edit: Maybe this PDF of my Bachelor's thesis gives a better overview of what DD is and does: http://scg.unibe.ch/archive/projects/Reic13a.pdf
Huge boon to productivity, especially when leveraged in tests.
Other folks have talked about this at length (e.g. https://mkremins.github.io/blog/unix-not-acceptable-unix/), but the fact that there is no standard way to pass anything other than strings of plain text between UNIX shell commands is incredibly limiting.
Heck even if we could pass a flag (say, -j) to something like ls and have it spit out JSON instead of plain text would be an upgrade.
It's slow and inefficient, you add the debug print, then you need to recompile the program, maybe you need another debug print, recompile the program, and so on, and then you must remember to delete all the debug prints that you added! And let's hope that your debug print didn't add some strange side effect (they might have!).
With a modern debugger you could print everything you want, at every memory location, you could set watchpoints, isn't it better than printf ? Also where you printf on an embedded system...
Edit: also, you don't need to remember to weed out debug prints, you can, in almost all languages, define a function or a macro to do that which can be undefined or an ignore function if not built in debug mode. With cpp or Lisp, that'd be a compile time decision, and I suppose many languages could optimise out a function that is defined to just ignore it's arguments and do nothing.
A modern debugger is a powerful tool (especially if the language you're using isn't itself very powerful). It's worth knowing your way around it. But that doesn't mean you shouldn't be using simple print statements whenever that's faster or more useful.
I use often in Lisp the INSPECT function with a GUI inspector. Each call to INSPECT puts the data into the inspector. For example (inspect (list :loop-i i :value n)) puts the list with the data into the inspector. The inspector has a history, which then allows me to see the various items. Thus this is similar to a print statement, but records the actual objects into a separate tool.
For the sake of completeness, I'll add that the output-connected-to-data works to some extent with Emacs & SLIME as well. These are so-called "presentations" - if you print an object, SLIME will connect the printed text to actual Lisp object, which allows you to inspect it later, or even copy and paste within the REPL - as long as you copy and paste the whole "presentation text", the underlying association will remain.
On the other hand, I'm disappointed. With all the power the web browser tools have - basically, arbitrary HTML rendering in console - this is the best we get? A simple, dumb table? There are so many to be explored here!
> I think part of the problem is that programmers rarely want to get into these supportive details; they just printf and get on with it.
A lot of programmers aren't aware that yes, they can and should modify their environment to suit their needs. Yes, they are allowed and should write their own debugging tools. Those tools don't have to be complicated. You can start with an ASCII-based console.table() equivalent. Or a script that parses the output and feeds it to some half-baked D3-based visualization. Or even gnuplot. Or graphviz. Plenty of possibilities there, and yet most devs I know never even think of them.
And I don't mean for computational/data science exploring, I've got numpy/matplotlib for that. But really as a debugging tool in the browser's dev console. It's not uncommon that I have an array of numbers (or something that looks like one), a few hundred or more. Finding the bug or unexpected behaviour in my program is often about finding the numbers in such a list that "stand out" in some way. Now I could specify and filter those elements that "stand out", but I could also plot a graph and grasp its behaviour in a single glance. Just dumping the numbers to the console and hunting for aberrant behaviour likely takes me out of my flow, where a graph would not.
Come to think of it, it shouldn't be hard to extend Emacs to eat specially prefixed output (e.g. #<scatterplot: (1 2) (3 4)...>), feed the data to external program and place a rendered chart inline. I might pick it up as a small project. Thanks!
printf("<tabe><tr><td>%s</td></tr></table>", htmlescape(blabla), ...);
Copy paste to the browser and you're done.
UP UP UP UP ENTER UP UP UP ENTER UP UP
before you can edit that line. But the web consoles allow you to type UP just once, and then move your cursor around the entire function definition. I wish all REPLs had this feature. "\e[A": history-search-backward
"\e[B": history-search-forward
enables searching by the current line's prefix in all programs that use readline (a lot of languages use readline for their REPL). That is, if you type "cp<UP>" you immediately get the previous command that started with "cp", regardless of how far back it is in your history.[1] https://codeinthehole.com/tips/the-most-important-command-li...
If the REPL uses readline (or mimics it), then
UP UP UP UP ^O ^O
will do the same thing as that sequence.It actually takes a little getting used to at first, that up literally just moves the cursor up into the output of the previous command. Nowdays, it is severely restricting to have the same commands move the cursor that change the current command. (That is, left/right move cursor, up/down do a ton more in most terminals. That is not the case in emacs shells.)
Really, though, the repl is a fun stepping stone to just sending function definitions from the file you are working on into an environment. https://github.com/skeeto/skewer-mode is a fun video showing the idea for javascript, amusingly.
That said, there was a fun video a while back of the guy that did Minecraft live coding a video game. Basically, the game would be running, and he could make a change and it would live update, just like the javascript video above. But it was in java.
This is harder in non-managed runtimes, I believe. But not impossible.
This displays better in the AWS console -- and also it enables better queries than raw text, e.g. `{$.response.code >= 400}`.
It's not just text. Grep is not enough for investigation.
You can see previous executions of the code you're interested in, with a highlight of the paths followed through the logic and snapshots of the variables as they were at the time.
Well, since that time when chrome was unable to find the javascript file of the page I was looking at, forcing me to go back to internet explorer, I disagree.
Also is it possible to edit the javascript code without reloading the page? I know how to do it with java+eclipse, but not in the browser.