Need better debugging support

Debugging my templates is impossible with the tools at my disposal.

I have an exceptionally complex template structure that is attempting to output API documentation. This requires model tables with fields which can also be models. In other words, templates are looping over fields and outputting data that can nest many levels.

Debugging with print(f) pollutes the page so terribly that I cannot use it practically. I have tied errorf, but this also outputs to the page, and it appears that it does not output data “in order” - by that, I mean the output seems to include errorf’s from calls to templates before the errorf that should come out before that template call. I believe there is some sort of buffering going on.

What would help tremendously would be a simple “debugf” call that would output to a file, and that output would be flushed at the end of every debugf statement to ensure orderly output.

What I do is to have a partial that is a JavaScript script populated with console.log statements containing Hugo tags.

Use of the partial in the build is controlled by a site parameter so I can easily turn it on/off.

Here is an example:

{{/* Output to JavaScript Console only - see baseof.html */}}
<script>
    console.log('-------- Hugo Debug: Theme = Twenty-Sixteen -------')
    console.log('HUGO_ENV: ', '{{ (getenv "HUGO_ENV") | default "NOT SET" }}')
    console.log('Long Env: ', '{{ (getenv "HUGO_ENV") | (getenv "ENVIRONMENT") | default .Site.Params.env | default "DEV" }}')
    console.log('Is Prod?: ', '{{ (eq (getenv "HUGO_ENV") "production" | or (eq .Site.Params.env "production")) }}')
    console.log('Page Kind: ', '{{.Page.Kind}}')
    console.log('Current Section: ', '{{.Page.CurrentSection | default "NOT SET" }}')
    console.log('Page Section: ', '{{.Page.Section | default "NOT SET" }}')
    console.log('Page Type: ', '{{.Page.Type}}')
    console.log('Page Dir: ', '{{.Page.Dir | default "/" }}{{ .File }}')
    console.log('Page Wd: ', '{{.Page.FuzzyWordCount}}')
    console.log('Page Home?: ', '{{.Page.IsHome}}')
    console.log('Page Node?: ', '{{.Page.IsNode}}')
    console.log('Page Page?: ', '{{.Page.IsPage}}')
    console.log('Page Date: ', '{{.Page.Date}}')
    console.log('Page Lastmod: ', '{{.Page.Lastmod}}')
    console.log('Page Date=Lastmod?: ', '{{ (eq .Page.Lastmod .Page.Date) }}')
    console.log('Page Date<>Lastmod?: ', '{{ (ne .Lastmod .Date) }}')
    console.log('Section Parent: ', '{{ with .Parent}}{{ .Dir | default "/" }}{{ .File }}{{end}}')
    console.log('Sharing Icons?: ', '{{ .Site.Params.Sharingicons | default "NOT DEFINED" }}')
    console.log('Comments?: ', '{{ .Params.comments | default "NOT DEFINED" }}')
    console.log('Disquss?: ', '{{ $.Site.DisqusShortname | default "NOT DEFINED" }}')
    console.log('Google Analytics?: ', '{{ .Site.GoogleAnalytics | default "NOT DEFINED" }}')
    console.log('Count of related pages: ', '{{if .Page.IsPage}}{{ len (.Site.RegularPages.Related .) }}{{end}}' )
    console.log(': ', '')
    console.log('---------------------------------------------------')
</script>

But yes, it is hard to debug Hugo. Not as hard as Jekyll though, in my - very limited - experience.

6 Likes

I handle debugging of such things by using a recursive partial.

I have a theme called hugo-bare-min-theme designed solely for debug and development of Hugo sites. You don’t have to use the whole theme; copying just the debugprint.html partial that I link in that project’s README (and debugprint.css partial) would suffice.


Related:

2 Likes

Would it make sense @kaushalmodi and @TotallyInformation to include your debugging templates (combined, with the best pieces of each) as an internal template for Hugo?

In that case, people can debug a page as easily as:

{{ template "_internal/debugging.html" . }}

We already have internal templates for situations that are much easier to accomplish, like adding a Google Analytics tracking script.

It makes sense to me to have the more complex situation of debugging also included ‘out of the box’.

Thank you for these ideas. They are interesting.

However, these do not solve the problem. Logging to a file is the solution that is needed, and adding a debugf function cannot be terribly difficult. I have lost so many hours of my time to something that could have been debugged in minutes with proper logging.

I agree with better need for debugging support.

But in the mean time you can use the errorf function to print information to the command line. If you use the logFile configuration variable you can also have that output appear in a file, from what I understand.

Perhaps we could all agree on an internal template. In fact, probably a couple - one that produces visible results and one that produces JavaScript console results.

Though honestly, it is probably easier simply to keep them on hand in this forum so that people can include and adapt as needed. It would be quite hard to create a template that covers everyone’s needs.

Simply cannot agree to that at all. Console output disappears, and output in my page messes with the visible results in a way that makes it difficult to see what I am debugging.

Honestly, I have never developed with any language that did not provide me with a proper logging mechanism, or a means to create one.

This seems like an exceptionally simple function to add to Hugo, and one that is essential for development of anything other than Mickey Mouse templates.

The debugprint.html partial detects a slice/map using a regex, so is not very robust by definition. But it works for all my use cases. So it wouldn’t be a good candidate for an internal template yet … until IsSlice, IsMap get implemented.

There was also a discussion on debug/dump function a while back. Folks interested should chime in their interest or support to make that happen in that issue.

I’m sure that contributions would be welcomed.

Perhaps add them to the documentation? The problem with keeping them here on the forum is that they’re so easily lost. It depends on people actively remember them. Much like the requesting help thread that Rick put together, but doesn’t get referenced here on the forum enough (in my view).

I totally understand where you’re coming from and I agree. But I also feel comments such as this don’t always help. Not everyone knows Go programming, has the time to learn Go, or has the time to learn the Hugo project and make contributions. We perhaps sometimes forget how hard that is. :slight_smile:

I don’t disagree about the issues with keeping things in a forum. However, there is a hints and tips section. The Hugo docs might be a better place perhaps but that would be up to the Hugo devs to comment on I think. I’d be happy to submit my suggestion somewhere if there is agreement on where. I fully expect that I will add more things like this to my knowledgebase. I started that because of similar questions and issues of location in another open source project.

But they do remind people that these forums are not a one-way street. I know that the Hugo devs are busy people - like the rest of us, they probably don’t have time to deal with all requests and desires. I am not a developer but I do try to add value to projects I use whether through input of hints, tips, help, documentation updates and even bits of code if possible. I’m not promoting myself here, just saying that we can all find ways to help. The OPs response came back very aggressively and while this may well be a language issue, it is still frustrating to see such responses when you know that there are people working really hard to make good things.

No aggression was intended, just a statement of fact. If you look specifically at the partial here:

which is working recursively with other partials, as well as the overall layout and data models of this project, which produces the documentation of a API, you can see that trying to debug this logic without any sort of logging ability would be difficult at best. The recursive nature of these partials, combined with Golang’s less than appealing scoping, makes this a difficult thing to code, let alone debug.

If I was not engaged 16 hours a day 7 days a week, I would be more than happy to contribute to the project. My contributions to open source over decades has been substantial. Sadly, at the moment I am burdened with delivering working systems for startup companies and have no time to contribute.