Litter is a pretty printer library for Go data structures to aid in debugging and testing.

!Build Status

Litter

Litter is a pretty printer library for Go data structures to aid in debugging and testing.


Litter is provided by


Sanity: The Headless CMS Construction Kit

Litter named for the fact that it outputs literals, which you litter your output with. As a side benefit, all Litter output is syntactically correct Go. You can use Litter to emit data during debug, and it's also really nice for "snapshot data" in unit tests, since it produces consistent, sorted output. Litter was inspired by Spew, but focuses on terseness and readability.

Basic example

This:

type Person struct {
	Name   string
	Age    int
	Parent *Person
}

litter.Dump(Person{
	Name:   "Bob",
	Age:    20,
	Parent: &Person{
		Name: "Jane",
		Age:  50,
	},
})

will output:

Person{
	Name: "Bob",
	Age: 20,
	Parent: &Person{
		Name: "Jane",
		Age: 50,
	},
}

Use in tests

Litter is a great alternative to JSON or YAML for providing "snapshots" or example data. For example:

func TestSearch(t *testing.T) {
	result := DoSearch()

	actual := litterOpts.Sdump(result)
	expected, err := ioutil.ReadFile("testdata.txt")
	if err != nil {
		// First run, write test data since it doesn't exist
		if !os.IsNotExist(err) {
			t.Error(err)
		}
		ioutil.Write("testdata.txt", actual, 0644)
		actual = expected
	}
	if expected != actual {
		t.Errorf("Expected %s, got %s", expected, actual)
	}
}

The first run will use Litter to write the data to testdata.txt. On subsequent runs, the test will compare the data. Since Litter always provides a consistent view of a value, you can compare the strings directly.

Circular references

Litter detects circular references or aliasing, and will replace additional references to the same object with aliases. For example:

type Circular struct {
	Self *Circular
}

selfref := Circular{}
selfref.Self = &selfref

litter.Dump(selfref)

will output:

Circular { // p0
	Self: p0,
}

Installation

$ go get -u github.com/sanity-io/litter

Quick start

Add this import line to the file you're working in:

import "github.com/sanity-io/litter"

To dump a variable with full newlines, indentation, type, and aliasing information, use Dump or Sdump:

litter.Dump(myVar1)
str := litter.Sdump(myVar1)

litter.Dump(value, ...)

Dumps the data structure to STDOUT.

litter.Sdump(value, ...)

Returns the dump as a string

Configuration

You can configure litter globally by modifying the default litter.Config

// Strip all package names from types
litter.Config.StripPackageNames = true

// Hide private struct fields from dumped structs
litter.Config.HidePrivateFields = true

// Hide fields matched with given regexp if it is not nil. It is set up to hide fields generate with protoc-gen-go
litter.Config.FieldExclusions = regexp.MustCompile(`^(XXX_.*)$`)

// Sets a "home" package. The package name will be stripped from all its types
litter.Config.HomePackage = "mypackage"

// Sets separator used when multiple arguments are passed to Dump() or Sdump().
litter.Config.Separator = "\n"

// Use compact output: strip newlines and other unnecessary whitespace
litter.Config.Compact = true

// Prevents duplicate pointers from being replaced by placeholder variable names (except in necessary, in the case
// of circular references)
litter.Config.DisablePointerReplacement = true

litter.Options

Allows you to configure a local configuration of litter to allow for proper compartmentalization of state at the expense of some comfort:

	sq := litter.Options {
		HidePrivateFields: true,
		HomePackage: "thispack",
		Separator: " ",
	}

	sq.Dump("dumped", "with", "local", "settings")

Custom dumpers

Implement the interface Dumper on your types to take control of how your type is dumped.

type Dumper interface {
	LitterDump(w io.Writer)
}

Just write your custom dump to the provided stream, using multiple lines divided by "\n" if you need. Litter might indent your output according to context, and optionally decorate your first line with a pointer comment where appropriate.

A couple of examples from the test suite:

type CustomMultiLineDumper struct {}

func (cmld *CustomMultiLineDumper) LitterDump(w io.Writer) {
	w.Write([]byte("{\n  multi\n  line\n}"))
}

type CustomSingleLineDumper int

func (csld CustomSingleLineDumper) LitterDump(w io.Writer) {
	w.Write([]byte("<custom>"))
}
Owner
Sanity
Sanity.io a platform for structured content that comes with an open source editor that you can customize with React.js.
Sanity
Comments
  • "Latest" release is not the latest

    image

    https://github.com/sanity-io/litter/releases https://github.com/sanity-io/litter/tags

    It might be easier to just delete those two releases and keep only tags.

  • add colour syntax highlighting  (quick hack)

    add colour syntax highlighting (quick hack)

    I don't think you want to just merge this (it adds a bunch of dependencies, and you could do separately), but im adding just in case youre interested. (cc: #27 )

  • Fix pointers resued in maps key

    Fix pointers resued in maps key

    When I use liiter to dump golang.org/x/tools/go/packages.Package, I found litter repeats in an endless loop. Then I found that reused pointers in maps key is the reason.

    I fixed it and added the test TestSdump_RecursiveMaps.

  • Pointers to simple types are not rendered as valid Go

    Pointers to simple types are not rendered as valid Go

    Consider the example:

    package main
    
    import (
    	"github.com/sanity-io/litter"
    )
    
    type T struct {
    	I *int
    }
    
    func main() {
    	i := 0
    	t := T{
    		I: &i,
    	}
    	litter.Dump(t)
    }
    

    This prints:

    main.T{
      I: &0,
    }
    

    which is not valid Go.

    When the type of a field is a simple type, like int, string, float64, etc. I would suggest that litter prints:

    main.T{
      I: litter.Int(0),
    }
    

    where litter.Int is defined as:

    package litter
    
    func Int(i int) *int { return &i }
    

    Similarly for other types.

  • Option to hide autogenerated protobuf fields

    Option to hide autogenerated protobuf fields

    Hi!

    We are using gRPC (with protobuf) and the latest version of protoc-gen-go generates 3 service fields named

    XXX_NoUnkeyedLiteral
    XXX_unrecognized
    XXX_sizecache
    

    and it is getting annoying to see them in the output. So, I added special option to hide these fields which is set to true by default.

    I decided to filter out exactly these three fields instead of filtering out everything started from XXX_ as explicit is better than implicit.

  • Add DumpFunc option

    Add DumpFunc option

    Adds new config option DumpFunc which allows overriding any value's formatting. I don't think this is ready as-is, but I'm posting an early iteration to get feedback.

    My usecase is printing a yaml ast for debugging (specifically the Node https://pkg.go.dev/gopkg.in/yaml.v3#Node). The Kind field doesn't implement fmt.Stringer so it just shows up as a number. In that case, I'd add a dump func like this

    package main
    
    import (
    	"fmt"
    	"io"
    	"reflect"
    
    	"gopkg.in/yaml.v3"
    )
    
    func KindString(k yaml.Kind) string {
    	switch k {
    	case yaml.DocumentNode:
    		return "DocumentNode"
    	case yaml.SequenceNode:
    		return "SequenceNode"
    	case yaml.ScalarNode:
    		return "MappingNode"
    	case yaml.ScalarNode:
    		return "ScalarNode"
    	case yaml.AliasNode:
    		return "AliasNode"
    	default:
    		return fmt.Sprintf("Unknown(%d)", k)
    	}
    }
    
    func main() {
    	cfg.DumpFunc = func(v reflect.Value, w io.Writer) bool {
    		if !v.CanInterface() {
    			return false
    		}
    		if k, ok := v.Interface().(yaml.Kind); ok {
    			io.WriteString(w, KindString(k))
    			return true
    		}
    		return false
    	}
    }
    
  • Issues/34: More compact array/map representation

    Issues/34: More compact array/map representation

    What:

    • Where the elements in a slice/array are primitive types; dump in a compact manner.
    • Where the elements(not keys) in a map are primitive types; dump in a compact manner

    Why:

    • Fixes: https://github.com/sanity-io/litter/issues/34
  • Prevent panic when dumping unexported map

    Prevent panic when dumping unexported map

    Fixes #18

    Tried some of the standard tricks for accessing unexported values but none worked. This fix isn't ideal because the resulting key order is non-deterministic but at least it doesn't panic.

  • Test failure

    Test failure

    Running go test on master yields:

    --- FAIL: TestSdump_customDumper (0.00s)
        --- FAIL: TestSdump_customDumper/customDumper (0.00s)
            Error Trace:    dump_test.go:213
        	            	dump_test.go:171
        	Error:      	Strings are different (left is expected, right is actual):
        	            	map[string]interface {}{					map[string]interface {}{
        	            	  "v1": *litter_test.CustomMultiLineDumper{ // p1	      |	  "v1": *litter_test.CustomMultiLineDumper{ // p0
        	            	    multi							    multi
        	            	    line							    line
        	            	  },								  },
        	            	  "v2": p1,						      |	  "v2": p0,
        	            	  "v2x": *litter_test.CustomMultiLineDumper{			  "v2x": *litter_test.CustomMultiLineDumper{
        	            	    multi							    multi
        	            	    line							    line
        	            	  },								  },
        	            	  "v3": litter_test.CustomSingleLineDumper<custom>,		  "v3": litter_test.CustomSingleLineDumper<custom>,
        	            	  "v4": *litter_test.CustomSingleLineDumper<custom>, // p0    |	  "v4": *litter_test.CustomSingleLineDumper<custom>, // p1
        	            	  "v5": p0,						      |	  "v5": p1,
        	            	  "v6": *litter_test.CustomSingleLineDumper<custom>,		  "v6": *litter_test.CustomSingleLineDumper<custom>,
        	            	}								}
    FAIL
    exit status 1
    FAIL	github.com/sanity-io/litter	0.021s
    
  • Output does not have correct float64 type for numbers.

    Output does not have correct float64 type for numbers.

    I am using litter to output structures that include map[string]interface{} objects that were produced by the standard JSON encode/decode package. The standard JSON decoder returns all numbers in a property map as float64 values. When I run litter on the resulting struct it outputs structures where the numbers have no specified type, just literal values. As a result, numbers that had integral values get converter to int by the compiler. Is there a way to get litter to retain the float64 type specification?

  • AddingPowerSupport_For_golang-github-sanity-io-litter

    AddingPowerSupport_For_golang-github-sanity-io-litter

    Adding Power Support.

    Adding power support ppc64le This is part of the Ubuntu distribution for ppc64le. This helps us simplify testing later when distributions are re-building and re-releasing. For more info tag @gerrith3.

    The Build is successful for both arch: amd64/ppc64le. Please find the Travis Link: https://travis-ci.com/github/santosh653/litter

  • Configure Renovate

    Configure Renovate

    Mend Renovate

    Welcome to Renovate! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.

    🚦 To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.


    Detected Package Files

    • .github/workflows/test.yml (github-actions)
    • go.mod (gomod)

    Configuration Summary

    Based on the default config's presets, Renovate will:

    • Start dependency updates only once this onboarding PR is merged
    • Enable Renovate Dependency Dashboard creation.
    • If Renovate detects semantic commits, it will use semantic commit type fix for dependencies and chore for all others.
    • Ignore node_modules, bower_components, vendor and various test/tests directories.
    • Autodetect whether to pin dependencies or maintain ranges.
    • Rate limit PR creation to a maximum of two per hour.
    • Limit to maximum 10 open PRs at any time.
    • Group known monorepo packages together.
    • Use curated list of recommended non-monorepo package groupings.
    • A collection of workarounds for known problems with packages.

    🔡 Would you like to change the way Renovate is upgrading your dependencies? Simply edit the renovate.json in this branch with your custom config and the list of Pull Requests in the "What to Expect" section below will be updated the next time Renovate runs.


    What to Expect

    With your current configuration, Renovate will create 4 Pull Requests:

    chore(deps): update module go to 1.19
    • Schedule: ["at any time"]
    • Branch name: renovate/go-1.x
    • Merge into: main
    • Upgrade go to 1.19
    chore(deps): update actions/checkout action to v3
    • Schedule: ["at any time"]
    • Branch name: renovate/actions-checkout-3.x
    • Merge into: main
    • Upgrade actions/checkout to v3
    chore(deps): update actions/setup-go action to v3
    • Schedule: ["at any time"]
    • Branch name: renovate/actions-setup-go-3.x
    • Merge into: main
    • Upgrade actions/setup-go to v3
    fix(deps): update module github.com/stretchr/testify to v1
    • Schedule: ["at any time"]
    • Branch name: renovate/github.com-stretchr-testify-1.x
    • Merge into: main
    • Upgrade github.com/stretchr/testify to b747d7c5f853d017ddbc5e623d026d7fc2770a58

    🚸 Branch creation will be limited to maximum 2 per hour, so it doesn't swamp any CI resources or spam the project. See docs for prhourlylimit for details.


    ❓ Got questions? Check out Renovate's Docs, particularly the Getting Started section. If you need any further assistance then you can also request help here.


    This PR has been generated by Mend Renovate. View repository job log here.

  • Not support String() implement function?

    Not support String() implement function?

    Seems like litter not accept costumed String() implement func

    Example comparing go-spew

    package main
    
    import (
    	"github.com/davecgh/go-spew/spew"
    	"github.com/sanity-io/litter"
    )
    
    func main() {
    	TT()
    }
    
    type A struct {
    	Tag string
    	Num int
    	InA InA
    }
    
    type InA struct {
    	Id   int
    	Type string
    }
    
    func (t InA) String() string {
    	return t.Type
    }
    
    func TT() {
    	a := A{
    		Tag: "tag-A",
    		Num: 1,
    		InA: InA{
    			Id:   100,
    			Type: "test",
    		},
    	}
    	spew.Dump(a)
    	litter.Dump(a)
    }
    

    Output compare

    (main.A) {
     Tag: (string) (len=5) "tag-A",
     Num: (int) 1,
     InA: (main.InA) test
    }
    main.A{
      Tag: "tag-A",
      Num: 1,
      InA: main.InA{
        Id: 100,
        Type: "test",
      },
    }
    
  • Dump with Error()/String() if possible

    Dump with Error()/String() if possible

    Dump with Error()/String() if possible, like fmt, spew.

    A DisableMethods config added, controlling the Error(), String()(should include LittleDump?) method invoking or not.

    May be a solution of https://github.com/sanity-io/litter/issues/12.

  • More compact array representation

    More compact array representation

    This gets old fast:

           Source: &json.RawMessage{
              123,
              34,
              97,
              103,
              101,
              110,
              116,
              95,
              117,
              105,
              100,
              34,
    ...
    

    We should emit arrays in a compact way for primitive types such as bytes.

  • Panic when dumping a gorilla named route

    Panic when dumping a gorilla named route

    Seems similar to #18 but still happens with current version:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    	"github.com/sanity-io/litter"
    )
    
    func main() {
    	r := mux.NewRouter()
    
    	r.HandleFunc(`/foo`, AnyHandler).Name("named")
    	r.HandleFunc("/", AnyHandler).Name("front")
    
    	srv := &http.Server{
    		Handler: r,
    		Addr:    "127.0.0.1:8000",
    	}
    
    	log.Fatal(srv.ListenAndServe())
    }
    
    func AnyHandler(w http.ResponseWriter, r *http.Request) {
    	route := mux.CurrentRoute(r)
    	litter.Config.HidePrivateFields = false
    	fmt.Fprintln(w, route.GetName())
    	defer func() {
    		p := recover()
    		if p != nil {
    			fmt.Printf("Recovered: %#v\n", p)
    		}
    	}()
    	litter.Sdump(route)
    }
    
    • Navigate to either / or /foo
    • Panics with: "reflect.Value.Interface: cannot return value obtained from unexported field or method"
    • Does not panic if only one of the routes is handled
    • Does not panic if either of the routes is not named
  • Dumping context.Context() doesn't show useful info

    Dumping context.Context() doesn't show useful info

    Code: litter.Dump(r.Context()) where r is a http.Request.

    Output

    &context.valueCtx{
      Context: &context.valueCtx{
        Context: &context.valueCtx{
          Context: &context.valueCtx{
            Context: &context.valueCtx{
              Context: &context.valueCtx{ // p2
                Context: &context.valueCtx{
                  Context: &context.cancelCtx{
                    Context: &context.cancelCtx{
                      Context: &context.valueCtx{
                        Context: &context.valueCtx{
                          Context: &0,
                        },
                      },
                    },
                  },
                },
              },
            },
          },
        },
      },
    }
    
    

    While github.com/davecgh/go-spew does show Values and other properties set in Context.

Implements a deep pretty printer for Go data structures to aid in debugging

spew Spew implements a deep pretty printer for Go data structures to aid in debugging. A comprehensive suite of tests with 100% test coverage is provi

Dec 25, 2022
Colored pretty printer for Go language
Colored pretty printer for Go language

pp Colored pretty printer for Go language Usage Just call pp.Print(). import "github.com/k0kubun/pp" m := map[string]string{"foo": "bar", "hello": "w

Dec 29, 2022
Quick and dirty debugging output for tired Go programmers
Quick and dirty debugging output for tired Go programmers

q q is a better way to do print statement debugging. Type q.Q instead of fmt.Printf and your variables will be printed like this: Why is this better t

Jan 7, 2023
A simple to use log system, minimalist but with features for debugging and differentiation of messages
A simple to use log system, minimalist but with features for debugging and differentiation of messages

A simple to use log system, minimalist but with features for debugging and differentiation of messages

Sep 26, 2022
🪵 A dead simple, pretty, and feature-rich logger for golang
🪵 A dead simple, pretty, and feature-rich logger for golang

?? lumber ?? A dead simple, pretty, and feature-rich logger for golang ?? Install ?? Logging Functions lumber.Success() lumber.Info() lumber.Debug() l

Jul 20, 2022
Package httpretty prints the HTTP requests you make with Go pretty on your terminal.

httpretty Package httpretty prints the HTTP requests of your Go programs pretty on your terminal screen. It is mostly inspired in curl's --verbose mod

Jan 8, 2023
A flexible process data collection, metrics, monitoring, instrumentation, and tracing client library for Go
A flexible process data collection, metrics, monitoring, instrumentation, and tracing client library for Go

Package monkit is a flexible code instrumenting and data collection library. See documentation at https://godoc.org/gopkg.in/spacemonkeygo/monkit.v3 S

Dec 14, 2022
Parametrized JSON logging library in Golang which lets you obfuscate sensitive data and marshal any kind of content.
Parametrized JSON logging library in Golang which lets you obfuscate sensitive data and marshal any kind of content.

Noodlog Summary Noodlog is a Golang JSON parametrized and highly configurable logging library. It allows you to: print go structs as JSON messages; pr

Oct 27, 2022
The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.

The open-source platform for monitoring and observability. Grafana allows you to query, visualize, alert on and understand your metrics no matter wher

Jan 3, 2023
Log-generator - A simple CLI tool that generates near real logs for testing

Log-generator - A simple CLI tool that generates near real logs for testing

Jan 22, 2022
Tracetest - Trace-based testing. End-to-end tests powered by your OpenTelemetry Traces.
Tracetest - Trace-based testing. End-to-end tests powered by your OpenTelemetry Traces.

End-to-end tests powered by OpenTelemetry. For QA, Dev, & Ops. Live Demo | Documentation | Twitter | Discord | Blog Click on the image or this link to

Jan 3, 2023
Open source framework for processing, monitoring, and alerting on time series data

Kapacitor Open source framework for processing, monitoring, and alerting on time series data Installation Kapacitor has two binaries: kapacitor – a CL

Dec 26, 2022
pprof is a tool for visualization and analysis of profiling data

Introduction pprof is a tool for visualization and analysis of profiling data. pprof reads a collection of profiling samples in profile.proto format a

Jan 8, 2023
a lightweight, high-performance, out-of-the-box logging library that relies solely on the Go standard library

English | 中文 olog olog is a lightweight, high-performance, out-of-the-box logging library that relies solely on the Go standard library. Support outpu

Apr 12, 2023
Golang beautify data display for Humans

Golang beautify data display for Humans English 简体中文 Usage Examples package main import ( ffmt "gopkg.in/ffmt.v1" ) func main() { example() } typ

Dec 22, 2022
Very simple charts with some debug data for Go programs
Very simple charts with some debug data for Go programs

debugcharts Go memory debug charts. This package uses Plotly chart library. It is open source and free for use. Installation go get -v -u github.com/m

Dec 14, 2022
Visualise Go program GC trace data in real time

This project is no longer maintained I'm sorry but I do not have the bandwidth to maintain this tool. Please do not send issues or PRs. Thank you. gcv

Dec 14, 2022
Interfaces for LZ77-based data compression

Pack Interfaces for LZ77-based data compression. Introduction Many compression libraries have two main parts: Something that looks for repeated sequen

Oct 19, 2021
mtail - extract internal monitoring data from application logs for collection into a timeseries database
 mtail - extract internal monitoring data from application logs for collection into a timeseries database

mtail - extract internal monitoring data from application logs for collection into a timeseries database mtail is a tool for extracting metrics from a

Dec 29, 2022