Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime/debug: allow JSON encoding of BuildInfo #51026

Closed
hyangah opened this issue Feb 5, 2022 · 9 comments
Closed

runtime/debug: allow JSON encoding of BuildInfo #51026

hyangah opened this issue Feb 5, 2022 · 9 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@hyangah
Copy link
Contributor

hyangah commented Feb 5, 2022

go1.18 added MarshalText and UnmarshalText methods for BuildInfo.
https://pkg.go.dev/runtime/debug@go1.18beta2#BuildInfo

This addition changed the behavior of this program.

package main

import (
	"encoding/json"
	"fmt"
	"runtime/debug"
)

func main() {
	info, _ := debug.ReadBuildInfo()
	b, _ := json.MarshalIndent(info, " ", " ")
	fmt.Printf("%s\n", b)
}

With go1.17

{
  "Path": "example",
  "Main": {
   "Path": "example",
   "Version": "(devel)",
   "Sum": "",
   "Replace": null
  },
  "Deps": null
 }

With go1.18

"go\tgo1.18beta2\npath\texample\nmod\texample\t(devel)\t\nbuild\t-compiler=gc\nbuild\t-gcflags=all=-N -l\nbuild\tCGO_ENABLED=1\nbuild\tCGO_CFLAGS=-O0 -g\nbuild\tCGO_CPPFLAGS=\nbuild\tCGO_CXXFLAGS=\nbuild\tCGO_LDFLAGS=\nbuild\tGOARCH=amd64\nbuild\tGOOS=darwin\nbuild\tGOAMD64=v1\n"

My proposal is either drop MarshalText/UnmarshalText (instead String/Parse, Encode/Decode?), or provide MarshalJSON/UnmarshalJSON so JSON encoding can encode in a form that tools written in other languages can access the info easily.

@gopherbot
Copy link

Change https://golang.org/cl/382274 mentions this issue: internal/lsp/debug: add go version to gopls version output

@ericlagergren
Copy link
Contributor

ericlagergren commented Feb 6, 2022

At work we print this information as part of a diagnostics file.

type Diagnostics struct {
    BuildInfo *debug.BuildInfo
    [...]
}

func Write(w io.Writer) error {
    d := Diagnostics{ ... }
    buf, err := json.Marshal(d)
    [...]
}

We use JSON because it's easy for both humans and machines to parse. The new format makes the JSON output inscrutable for humans and breaks machine parsing. While there wasn't any guarantee that BuildInfo would always be representable as JSON, it doesn't seem an unreasonable request.

It would be nice if the fix could make it into 1.18.

cc: @jayconrod

@rsc rsc added this to the Go1.18 milestone Feb 7, 2022
@rsc rsc added release-blocker NeedsFix The path to resolution is known, but the work has not been done. labels Feb 7, 2022
@rsc
Copy link
Contributor

rsc commented Feb 7, 2022

Agree - we can't let the MarshalText break MarshalJSON. Probably we should just rename that method something else and let people call it as they need it. Will discuss with @bcmills and @matloob.

gopherbot pushed a commit to golang/tools that referenced this issue Feb 7, 2022
Add -json flag to output in JSON format.

Include the Go version info
  - go1.18: runtime/debug.BuildInfo.GoVersion
  - pre go1.18: runtime.Version

Restructure ServiceVersion so we embed info from
runtime/debug.BuildInfo. Instead of directly using
runtime/debug.BuildInfo, we use our own BuildInfo type.
That allows:
  for go1.17 or older versions, we can add GoVersion.
  for go1.18, we can drop MarshalText that prevents
  JSON encoding other languages and human can understand
  (golang/go#51026)

For golang/go#49783

Change-Id: Ia5ab50ce1f5e6c3a912654834785ecea7f5034e2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/382274
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
@bcmills
Copy link
Contributor

bcmills commented Feb 7, 2022

It's unfortunate that MarshalText and UnmarshalText break JSON embedding, because semantically they're a perfect fit: these methods really are marshaling and unmarshaling the object into “a textual form”, and the signatures are more appropriate than String / Parse because the marshaling operation can fail (because field values that could collide with separators do not have escaping).

But maybe it would be better to add some form of escaping and switch to func (*BuildInfo) String() and debug.ParseBuildInfo.

@seankhliao
Copy link
Member

BuildInfo could also implement MarshalJSON and UnmarshalJSON to get the json back, something like:

func (b BuildInfo) MarshalJSON() ([]byte, error) {
    type buildInfo BuildInfo // Mask out the methods
    return json.Marshal(buildInfo(b))
}

@bcmills
Copy link
Contributor

bcmills commented Feb 7, 2022

It could, if it were in an ordinary package. Unfortunately, it is in runtime/debug, which cannot import encoding/json. 😞

So if we provided a MarshalJSON method it would probably have to be a bespoke implementation — and UnmarshalJSON in particular seems more complex than it's worth.

@Cyberax
Copy link

Cyberax commented Feb 8, 2022

Perhaps a targeted hack in JSON marshaler will help?

@bcmills bcmills self-assigned this Feb 8, 2022
@gopherbot
Copy link

Change https://go.dev/cl/384154 mentions this issue: runtime/debug: replace (*BuildInfo).Marshal methods with Parse and String

@gopherbot
Copy link

Change https://go.dev/cl/384161 mentions this issue: runtime/debug: expand fuzz corpus for FuzzParseBuildInfoRoundTrip

@rsc rsc unassigned bcmills Jun 22, 2022
gopherbot pushed a commit that referenced this issue Jan 26, 2023
Updates #51026

Change-Id: Id7af2ffa8c99970274b2a2b12622d986ea105b1b
Reviewed-on: https://go-review.googlesource.com/c/go/+/384161
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
@golang golang locked and limited conversation to collaborators Jun 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

7 participants