mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
remove rollbar
This commit is contained in:
parent
fa6460b8ab
commit
6279b416bc
15 changed files with 1 additions and 810 deletions
2
go.mod
2
go.mod
|
|
@ -22,7 +22,7 @@ require (
|
||||||
github.com/integrii/flaggy v1.4.0
|
github.com/integrii/flaggy v1.4.0
|
||||||
github.com/jesseduffield/asciigraph v0.0.0-20190605104717-6d88e39309ee
|
github.com/jesseduffield/asciigraph v0.0.0-20190605104717-6d88e39309ee
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20200201013258-57fdcf23edc5
|
github.com/jesseduffield/gocui v0.3.1-0.20200201013258-57fdcf23edc5
|
||||||
github.com/jesseduffield/rollrus v0.0.0-20190701125922-dd028cb0bfd7
|
github.com/jesseduffield/rollrus v0.0.0-20190701125922-dd028cb0bfd7 // indirect
|
||||||
github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9 // indirect
|
github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9 // indirect
|
||||||
github.com/jesseduffield/yaml v0.0.0-20190702115811-b900b7e08b56
|
github.com/jesseduffield/yaml v0.0.0-20190702115811-b900b7e08b56
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,13 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
"github.com/jesseduffield/rollrus"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewLogger returns a new logger
|
// NewLogger returns a new logger
|
||||||
func NewLogger(config *config.AppConfig, rollrusHook string) *logrus.Entry {
|
func NewLogger(config *config.AppConfig, rollrusHook string) *logrus.Entry {
|
||||||
var log *logrus.Logger
|
var log *logrus.Logger
|
||||||
environment := "production"
|
|
||||||
if config.Debug || os.Getenv("DEBUG") == "TRUE" {
|
if config.Debug || os.Getenv("DEBUG") == "TRUE" {
|
||||||
environment = "development"
|
|
||||||
log = newDevelopmentLogger(config)
|
log = newDevelopmentLogger(config)
|
||||||
} else {
|
} else {
|
||||||
log = newProductionLogger()
|
log = newProductionLogger()
|
||||||
|
|
@ -26,11 +23,6 @@ func NewLogger(config *config.AppConfig, rollrusHook string) *logrus.Entry {
|
||||||
// https://github.com/aybabtme/humanlog
|
// https://github.com/aybabtme/humanlog
|
||||||
log.Formatter = &logrus.JSONFormatter{}
|
log.Formatter = &logrus.JSONFormatter{}
|
||||||
|
|
||||||
if config.UserConfig.Reporting == "on" && rollrusHook != "" {
|
|
||||||
// this isn't really a secret token: it only has permission to push new rollbar items
|
|
||||||
hook := rollrus.NewHook(rollrusHook, environment)
|
|
||||||
log.Hooks.Add(hook)
|
|
||||||
}
|
|
||||||
return log.WithFields(logrus.Fields{
|
return log.WithFields(logrus.Fields{
|
||||||
"debug": config.Debug,
|
"debug": config.Debug,
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
|
|
|
||||||
1
vendor/github.com/jesseduffield/roll/.gitignore
generated
vendored
1
vendor/github.com/jesseduffield/roll/.gitignore
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
rollbar.test
|
|
||||||
24
vendor/github.com/jesseduffield/roll/CHANGELOG
generated
vendored
24
vendor/github.com/jesseduffield/roll/CHANGELOG
generated
vendored
|
|
@ -1,24 +0,0 @@
|
||||||
0.2.0 - May 22nd, 2016
|
|
||||||
====================
|
|
||||||
|
|
||||||
* Do not use title to determine fingerprint.
|
|
||||||
|
|
||||||
0.1.1 - August 24th, 2016
|
|
||||||
=========================
|
|
||||||
|
|
||||||
* Fix Go 1.6 support by removing call to runtime.CallersFrames, which was added
|
|
||||||
in Go 1.7.
|
|
||||||
|
|
||||||
0.1.0 - August 23rd, 2016
|
|
||||||
=========================
|
|
||||||
|
|
||||||
* Allow passing in arbitrary function pointer stacks. (thanks @apg!)
|
|
||||||
* Remove unneeded exported constants.
|
|
||||||
* Make HTTP(S) endpoint configurable.
|
|
||||||
* Remove unneeded debug print statement.
|
|
||||||
|
|
||||||
0.0.1 - January 19th, 2015
|
|
||||||
==========================
|
|
||||||
|
|
||||||
* Initial release based on https://github.com/stvp/rollbar
|
|
||||||
|
|
||||||
22
vendor/github.com/jesseduffield/roll/LICENSE
generated
vendored
22
vendor/github.com/jesseduffield/roll/LICENSE
generated
vendored
|
|
@ -1,22 +0,0 @@
|
||||||
Copyright (c) 2016 Stovepipe Studios
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
53
vendor/github.com/jesseduffield/roll/README.md
generated
vendored
53
vendor/github.com/jesseduffield/roll/README.md
generated
vendored
|
|
@ -1,53 +0,0 @@
|
||||||
roll
|
|
||||||
----
|
|
||||||
|
|
||||||
`roll` is a basic Rollbar client for Go that reports errors and logs
|
|
||||||
messages. It automatically builds stack traces and also supports
|
|
||||||
arbitrary traces. All errors and messages are sent to Rollbar
|
|
||||||
synchronously.
|
|
||||||
|
|
||||||
`roll` is intentionally simple. For more advanced functionality, check
|
|
||||||
out [heroku/rollbar](https://github.com/heroku/rollbar).
|
|
||||||
|
|
||||||
[API docs on godoc.org](http://godoc.org/github.com/stvp/roll)
|
|
||||||
|
|
||||||
Notes
|
|
||||||
=====
|
|
||||||
|
|
||||||
* Critical-, Error-, and Warning-level messages include a stack trace.
|
|
||||||
However, Go's `error` type doesn't include stack information from the
|
|
||||||
location the error was set or allocated. Instead, `roll` uses the
|
|
||||||
stack information from where the error was reported.
|
|
||||||
* Info- and Debug-level Rollbar messages do not include stack traces.
|
|
||||||
* When calling `roll` away from where the error actually occurred,
|
|
||||||
`roll`'s stack walking won't represent the actual stack trace at the
|
|
||||||
time the error occurred. The `*Stack` variants of Critical, Error, and
|
|
||||||
Warning take a `[]uintptr`, allowing the stack to be provided, rather
|
|
||||||
than walked.
|
|
||||||
|
|
||||||
Running Tests
|
|
||||||
=============
|
|
||||||
|
|
||||||
`go test` will run tests against a fake server by default.
|
|
||||||
|
|
||||||
If the environment variable `TOKEN` is a Rollbar access token, running
|
|
||||||
`go test` will produce errors using an environment named `test`.
|
|
||||||
|
|
||||||
TOKEN=f0df01587b8f76b2c217af34c479f9ea go test
|
|
||||||
|
|
||||||
Verify the reported errors manually in the Rollbar dashboard.
|
|
||||||
|
|
||||||
Contributors
|
|
||||||
============
|
|
||||||
|
|
||||||
* @challiwill
|
|
||||||
* @tysonmote
|
|
||||||
* @apg
|
|
||||||
|
|
||||||
This library was forked from [stvp/rollbar](https://github.com/stvp/rollbar),
|
|
||||||
which had contributions from:
|
|
||||||
|
|
||||||
* @kjk
|
|
||||||
* @Soulou
|
|
||||||
* @paulmach
|
|
||||||
|
|
||||||
242
vendor/github.com/jesseduffield/roll/client.go
generated
vendored
242
vendor/github.com/jesseduffield/roll/client.go
generated
vendored
|
|
@ -1,242 +0,0 @@
|
||||||
package roll
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"hash/adler32"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// By default, all Rollbar API requests are sent to this endpoint.
|
|
||||||
endpoint = "https://api.rollbar.com/api/1/item/"
|
|
||||||
|
|
||||||
// Identify this Rollbar client library to the Rollbar API.
|
|
||||||
clientName = "go-roll"
|
|
||||||
clientVersion = "0.2.0"
|
|
||||||
clientLanguage = "go"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Endpoint is the default HTTP(S) endpoint that all Rollbar API requests
|
|
||||||
// will be sent to. By default, this is Rollbar's "Items" API endpoint. If
|
|
||||||
// this is blank, no items will be sent to Rollbar.
|
|
||||||
Endpoint = endpoint
|
|
||||||
|
|
||||||
// Rollbar access token for the global client. If this is blank, no items
|
|
||||||
// will be sent to Rollbar.
|
|
||||||
Token = ""
|
|
||||||
|
|
||||||
// Environment for all items reported with the global client.
|
|
||||||
Environment = "development"
|
|
||||||
)
|
|
||||||
|
|
||||||
type rollbarSuccess struct {
|
|
||||||
Result map[string]string `json:"result"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client reports items to a single Rollbar project.
|
|
||||||
type Client interface {
|
|
||||||
Critical(err error, custom map[string]string) (uuid string, e error)
|
|
||||||
CriticalStack(err error, ptrs []uintptr, custom map[string]string) (uuid string, e error)
|
|
||||||
Error(err error, custom map[string]string) (uuid string, e error)
|
|
||||||
ErrorStack(err error, ptrs []uintptr, custom map[string]string) (uuid string, e error)
|
|
||||||
Warning(err error, custom map[string]string) (uuid string, e error)
|
|
||||||
WarningStack(err error, ptrs []uintptr, custom map[string]string) (uuid string, e error)
|
|
||||||
Info(msg string, custom map[string]string) (uuid string, e error)
|
|
||||||
Debug(msg string, custom map[string]string) (uuid string, e error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type rollbarClient struct {
|
|
||||||
token string
|
|
||||||
env string
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Rollbar client that reports items to the given project
|
|
||||||
// token and with the given environment (eg. "production", "development", etc).
|
|
||||||
func New(token, env string) Client {
|
|
||||||
return &rollbarClient{token, env}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Critical(err error, custom map[string]string) (uuid string, e error) {
|
|
||||||
return CriticalStack(err, getCallers(2), custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CriticalStack(err error, ptrs []uintptr, custom map[string]string) (uuid string, e error) {
|
|
||||||
return New(Token, Environment).CriticalStack(err, ptrs, custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Error(err error, custom map[string]string) (uuid string, e error) {
|
|
||||||
return ErrorStack(err, getCallers(2), custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ErrorStack(err error, ptrs []uintptr, custom map[string]string) (uuid string, e error) {
|
|
||||||
return New(Token, Environment).ErrorStack(err, ptrs, custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Warning(err error, custom map[string]string) (uuid string, e error) {
|
|
||||||
return WarningStack(err, getCallers(2), custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WarningStack(err error, ptrs []uintptr, custom map[string]string) (uuid string, e error) {
|
|
||||||
return New(Token, Environment).WarningStack(err, ptrs, custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Info(msg string, custom map[string]string) (uuid string, e error) {
|
|
||||||
return New(Token, Environment).Info(msg, custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Debug(msg string, custom map[string]string) (uuid string, e error) {
|
|
||||||
return New(Token, Environment).Debug(msg, custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) Critical(err error, custom map[string]string) (uuid string, e error) {
|
|
||||||
return c.CriticalStack(err, getCallers(2), custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) CriticalStack(err error, callers []uintptr, custom map[string]string) (uuid string, e error) {
|
|
||||||
item := c.buildTraceItem("critical", err, callers, custom)
|
|
||||||
return c.send(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) Error(err error, custom map[string]string) (uuid string, e error) {
|
|
||||||
return c.ErrorStack(err, getCallers(2), custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) ErrorStack(err error, callers []uintptr, custom map[string]string) (uuid string, e error) {
|
|
||||||
item := c.buildTraceItem("error", err, callers, custom)
|
|
||||||
return c.send(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) Warning(err error, custom map[string]string) (uuid string, e error) {
|
|
||||||
return c.WarningStack(err, getCallers(2), custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) WarningStack(err error, callers []uintptr, custom map[string]string) (uuid string, e error) {
|
|
||||||
item := c.buildTraceItem("warning", err, callers, custom)
|
|
||||||
return c.send(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) Info(msg string, custom map[string]string) (uuid string, e error) {
|
|
||||||
item := c.buildMessageItem("info", msg, custom)
|
|
||||||
return c.send(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) Debug(msg string, custom map[string]string) (uuid string, e error) {
|
|
||||||
item := c.buildMessageItem("debug", msg, custom)
|
|
||||||
return c.send(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) buildTraceItem(level string, err error, callers []uintptr, custom map[string]string) (item map[string]interface{}) {
|
|
||||||
stack := buildRollbarFrames(callers)
|
|
||||||
item = c.buildItem(level, err.Error(), custom)
|
|
||||||
itemData := item["data"].(map[string]interface{})
|
|
||||||
itemData["fingerprint"] = stack.fingerprint()
|
|
||||||
itemData["body"] = map[string]interface{}{
|
|
||||||
"trace": map[string]interface{}{
|
|
||||||
"frames": stack,
|
|
||||||
"exception": map[string]interface{}{
|
|
||||||
"class": errorClass(err),
|
|
||||||
"message": err.Error(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) buildMessageItem(level string, msg string, custom map[string]string) (item map[string]interface{}) {
|
|
||||||
item = c.buildItem(level, msg, custom)
|
|
||||||
itemData := item["data"].(map[string]interface{})
|
|
||||||
itemData["body"] = map[string]interface{}{
|
|
||||||
"message": map[string]interface{}{
|
|
||||||
"body": msg,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rollbarClient) buildItem(level, title string, custom map[string]string) map[string]interface{} {
|
|
||||||
hostname, _ := os.Hostname()
|
|
||||||
|
|
||||||
return map[string]interface{}{
|
|
||||||
"access_token": c.token,
|
|
||||||
"data": map[string]interface{}{
|
|
||||||
"environment": c.env,
|
|
||||||
"title": title,
|
|
||||||
"level": level,
|
|
||||||
"timestamp": time.Now().Unix(),
|
|
||||||
"platform": runtime.GOOS,
|
|
||||||
"language": clientLanguage,
|
|
||||||
"server": map[string]interface{}{
|
|
||||||
"host": hostname,
|
|
||||||
},
|
|
||||||
"notifier": map[string]interface{}{
|
|
||||||
"name": clientName,
|
|
||||||
"version": clientVersion,
|
|
||||||
},
|
|
||||||
"custom": custom,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send reports the given item to Rollbar and returns either a UUID for the
|
|
||||||
// reported item or an error.
|
|
||||||
func (c *rollbarClient) send(item map[string]interface{}) (uuid string, err error) {
|
|
||||||
if len(c.token) == 0 || len(Endpoint) == 0 {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonBody, err := json.Marshal(item)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := http.Post(Endpoint, "application/json", bytes.NewReader(jsonBody))
|
|
||||||
if err != nil {
|
|
||||||
// If something goes wrong it really does not matter
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
io.Copy(ioutil.Discard, resp.Body)
|
|
||||||
resp.Body.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
// If something goes wrong it really does not matter
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract UUID from JSON response
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
success := rollbarSuccess{}
|
|
||||||
json.Unmarshal(body, &success)
|
|
||||||
|
|
||||||
return success.Result["uuid"], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// errorClass returns a class name for an error (eg. "ErrUnexpectedEOF"). For
|
|
||||||
// string errors, it returns an Adler-32 checksum of the error string.
|
|
||||||
func errorClass(err error) string {
|
|
||||||
class := reflect.TypeOf(err).String()
|
|
||||||
if class == "" {
|
|
||||||
return "panic"
|
|
||||||
} else if class == "*errors.errorString" {
|
|
||||||
checksum := adler32.Checksum([]byte(err.Error()))
|
|
||||||
return fmt.Sprintf("{%x}", checksum)
|
|
||||||
} else {
|
|
||||||
return strings.TrimPrefix(class, "*")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
98
vendor/github.com/jesseduffield/roll/stack.go
generated
vendored
98
vendor/github.com/jesseduffield/roll/stack.go
generated
vendored
|
|
@ -1,98 +0,0 @@
|
||||||
package roll
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"hash/crc32"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
knownFilePathPatterns = []string{
|
|
||||||
"github.com/",
|
|
||||||
"code.google.com/",
|
|
||||||
"bitbucket.org/",
|
|
||||||
"launchpad.net/",
|
|
||||||
"gopkg.in/",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func getCallers(skip int) (pc []uintptr) {
|
|
||||||
pc = make([]uintptr, 1000)
|
|
||||||
i := runtime.Callers(skip+1, pc)
|
|
||||||
return pc[0:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- rollbarFrames
|
|
||||||
|
|
||||||
type rollbarFrame struct {
|
|
||||||
Filename string `json:"filename"`
|
|
||||||
Method string `json:"method"`
|
|
||||||
Line int `json:"lineno"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type rollbarFrames []rollbarFrame
|
|
||||||
|
|
||||||
// buildRollbarFrames takes a slice of function pointers and returns a Rollbar
|
|
||||||
// API payload containing the filename, method name, and line number of each
|
|
||||||
// function.
|
|
||||||
func buildRollbarFrames(callers []uintptr) (frames rollbarFrames) {
|
|
||||||
frames = rollbarFrames{}
|
|
||||||
|
|
||||||
// 2016-08-24 - runtime.CallersFrames was added in Go 1.7, which should
|
|
||||||
// replace the following code when roll is able to require Go 1.7+.
|
|
||||||
for _, caller := range callers {
|
|
||||||
frame := rollbarFrame{
|
|
||||||
Filename: "???",
|
|
||||||
Method: "???",
|
|
||||||
}
|
|
||||||
if fn := runtime.FuncForPC(caller); fn != nil {
|
|
||||||
name, line := fn.FileLine(caller)
|
|
||||||
frame.Filename = scrubFile(name)
|
|
||||||
frame.Line = line
|
|
||||||
frame.Method = scrubFunction(fn.Name())
|
|
||||||
}
|
|
||||||
frames = append(frames, frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
return frames
|
|
||||||
}
|
|
||||||
|
|
||||||
// fingerprint returns a checksum that uniquely identifies a stacktrace by the
|
|
||||||
// filename, method name, and line number of every frame in the stack.
|
|
||||||
func (f rollbarFrames) fingerprint() string {
|
|
||||||
hash := crc32.NewIEEE()
|
|
||||||
for _, frame := range f {
|
|
||||||
fmt.Fprintf(hash, "%s%s%d", frame.Filename, frame.Method, frame.Line)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%x", hash.Sum32())
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Helpers
|
|
||||||
|
|
||||||
// scrubFile removes unneeded information from the path of a source file. This
|
|
||||||
// makes them shorter in Rollbar UI as well as making them the same, regardless
|
|
||||||
// of the machine the code was compiled on.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// /home/foo/go/src/github.com/stvp/roll/rollbar.go -> github.com/stvp/roll/rollbar.go
|
|
||||||
func scrubFile(s string) string {
|
|
||||||
var i int
|
|
||||||
for _, pattern := range knownFilePathPatterns {
|
|
||||||
i = strings.Index(s, pattern)
|
|
||||||
if i != -1 {
|
|
||||||
return s[i:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// scrubFunction removes unneeded information from the full name of a function.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// github.com/stvp/roll.getCallers -> roll.getCallers
|
|
||||||
func scrubFunction(name string) string {
|
|
||||||
end := strings.LastIndex(name, string(os.PathSeparator))
|
|
||||||
return name[end+1 : len(name)]
|
|
||||||
}
|
|
||||||
7
vendor/github.com/jesseduffield/rollrus/.travis.yml
generated
vendored
7
vendor/github.com/jesseduffield/rollrus/.travis.yml
generated
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.10.8
|
|
||||||
- 1.11.6
|
|
||||||
- 1.12.1
|
|
||||||
script:
|
|
||||||
- go test -v -race ./...
|
|
||||||
22
vendor/github.com/jesseduffield/rollrus/LICENSE
generated
vendored
22
vendor/github.com/jesseduffield/rollrus/LICENSE
generated
vendored
|
|
@ -1,22 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright © Heroku 2014 - 2015
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
15
vendor/github.com/jesseduffield/rollrus/README.md
generated
vendored
15
vendor/github.com/jesseduffield/rollrus/README.md
generated
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
[](https://travis-ci.org/heroku/rollrus) [](https://godoc.org/github.com/heroku/rollrus)
|
|
||||||
|
|
||||||
# What
|
|
||||||
|
|
||||||
Rollrus is what happens when [Logrus](https://github.com/sirupsen/logrus) meets [Roll](https://github.com/stvp/roll).
|
|
||||||
|
|
||||||
When a .Error, .Fatal or .Panic logging function is called, report the details to rollbar via a Logrus hook.
|
|
||||||
|
|
||||||
Delivery is synchronous to help ensure that logs are delivered.
|
|
||||||
|
|
||||||
If the error includes a [`StackTrace`](https://godoc.org/github.com/pkg/errors#StackTrace), that `StackTrace` is reported to rollbar.
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
|
|
||||||
Examples available in the [tests](https://github.com/heroku/rollrus/blob/master/rollrus_test.go) or on [GoDoc](https://godoc.org/github.com/heroku/rollrus).
|
|
||||||
7
vendor/github.com/jesseduffield/rollrus/go.mod
generated
vendored
7
vendor/github.com/jesseduffield/rollrus/go.mod
generated
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
module github.com/jesseduffield/rollrus
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/jesseduffield/roll v0.0.0-20190629104057-695be2e62b00
|
|
||||||
github.com/pkg/errors v0.8.1
|
|
||||||
github.com/sirupsen/logrus v1.3.0
|
|
||||||
)
|
|
||||||
19
vendor/github.com/jesseduffield/rollrus/go.sum
generated
vendored
19
vendor/github.com/jesseduffield/rollrus/go.sum
generated
vendored
|
|
@ -1,19 +0,0 @@
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/jesseduffield/roll v0.0.0-20190629104057-695be2e62b00 h1:+JaOkfBNYQYlGD7dgru8mCwYNEc5tRRI8mThlVANhSM=
|
|
||||||
github.com/jesseduffield/roll v0.0.0-20190629104057-695be2e62b00/go.mod h1:cWNQljQAWYBp4wchyGfql4q2jRNZXxiE1KhVQgz+JaM=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
|
|
||||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
|
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
|
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
287
vendor/github.com/jesseduffield/rollrus/rollrus.go
generated
vendored
287
vendor/github.com/jesseduffield/rollrus/rollrus.go
generated
vendored
|
|
@ -1,287 +0,0 @@
|
||||||
// Package rollrus combines github.com/jesseduffield/roll with github.com/sirupsen/logrus
|
|
||||||
// via logrus.Hook mechanism, so that whenever logrus' logger.Error/f(),
|
|
||||||
// logger.Fatal/f() or logger.Panic/f() are used the messages are
|
|
||||||
// intercepted and sent to rollbar.
|
|
||||||
//
|
|
||||||
// Using SetupLogging should suffice for basic use cases that use the logrus
|
|
||||||
// singleton logger.
|
|
||||||
//
|
|
||||||
// More custom uses are supported by creating a new Hook with NewHook and
|
|
||||||
// registering that hook with the logrus Logger of choice.
|
|
||||||
//
|
|
||||||
// The levels can be customized with the WithLevels OptionFunc.
|
|
||||||
//
|
|
||||||
// Specific errors can be ignored with the WithIgnoredErrors OptionFunc. This is
|
|
||||||
// useful for ignoring errors such as context.Canceled.
|
|
||||||
//
|
|
||||||
// See the Examples in the tests for more usage.
|
|
||||||
package rollrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/roll"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var defaultTriggerLevels = []logrus.Level{
|
|
||||||
logrus.ErrorLevel,
|
|
||||||
logrus.FatalLevel,
|
|
||||||
logrus.PanicLevel,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook is a wrapper for the rollbar Client and is usable as a logrus.Hook.
|
|
||||||
type Hook struct {
|
|
||||||
roll.Client
|
|
||||||
triggers []logrus.Level
|
|
||||||
ignoredErrors []error
|
|
||||||
ignoreErrorFunc func(error) bool
|
|
||||||
ignoreFunc func(error, map[string]string) bool
|
|
||||||
|
|
||||||
// only used for tests to verify whether or not a report happened.
|
|
||||||
reported bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// OptionFunc that can be passed to NewHook.
|
|
||||||
type OptionFunc func(*Hook)
|
|
||||||
|
|
||||||
// wellKnownErrorFields are the names of the fields to be checked for values of
|
|
||||||
// type `error`, in priority order.
|
|
||||||
var wellKnownErrorFields = []string{
|
|
||||||
logrus.ErrorKey, "err",
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithLevels is an OptionFunc that customizes the log.Levels the hook will
|
|
||||||
// report on.
|
|
||||||
func WithLevels(levels ...logrus.Level) OptionFunc {
|
|
||||||
return func(h *Hook) {
|
|
||||||
h.triggers = levels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMinLevel is an OptionFunc that customizes the log.Levels the hook will
|
|
||||||
// report on by selecting all levels more severe than the one provided.
|
|
||||||
func WithMinLevel(level logrus.Level) OptionFunc {
|
|
||||||
var levels []logrus.Level
|
|
||||||
for _, l := range logrus.AllLevels {
|
|
||||||
if l <= level {
|
|
||||||
levels = append(levels, l)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(h *Hook) {
|
|
||||||
h.triggers = levels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithIgnoredErrors is an OptionFunc that whitelists certain errors to prevent
|
|
||||||
// them from firing. See https://golang.org/ref/spec#Comparison_operators
|
|
||||||
func WithIgnoredErrors(errors ...error) OptionFunc {
|
|
||||||
return func(h *Hook) {
|
|
||||||
h.ignoredErrors = append(h.ignoredErrors, errors...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithIgnoreErrorFunc is an OptionFunc that receives the error that is about
|
|
||||||
// to be logged and returns true/false if it wants to fire a rollbar alert for.
|
|
||||||
func WithIgnoreErrorFunc(fn func(error) bool) OptionFunc {
|
|
||||||
return func(h *Hook) {
|
|
||||||
h.ignoreErrorFunc = fn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithIgnoreFunc is an OptionFunc that receives the error and custom fields that are about
|
|
||||||
// to be logged and returns true/false if it wants to fire a rollbar alert for.
|
|
||||||
func WithIgnoreFunc(fn func(err error, fields map[string]string) bool) OptionFunc {
|
|
||||||
return func(h *Hook) {
|
|
||||||
h.ignoreFunc = fn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHook creates a hook that is intended for use with your own logrus.Logger
|
|
||||||
// instance. Uses the defualt report levels defined in wellKnownErrorFields.
|
|
||||||
func NewHook(token string, env string, opts ...OptionFunc) *Hook {
|
|
||||||
h := NewHookForLevels(token, env, defaultTriggerLevels)
|
|
||||||
|
|
||||||
for _, o := range opts {
|
|
||||||
o(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHookForLevels provided by the caller. Otherwise works like NewHook.
|
|
||||||
func NewHookForLevels(token string, env string, levels []logrus.Level) *Hook {
|
|
||||||
return &Hook{
|
|
||||||
Client: roll.New(token, env),
|
|
||||||
triggers: levels,
|
|
||||||
ignoredErrors: make([]error, 0),
|
|
||||||
ignoreErrorFunc: func(error) bool { return false },
|
|
||||||
ignoreFunc: func(error, map[string]string) bool { return false },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupLogging for use on Heroku. If token is not an empty string a rollbar
|
|
||||||
// hook is added with the environment set to env. The log formatter is set to a
|
|
||||||
// TextFormatter with timestamps disabled.
|
|
||||||
func SetupLogging(token, env string) {
|
|
||||||
setupLogging(token, env, defaultTriggerLevels)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupLoggingForLevels works like SetupLogging, but allows you to
|
|
||||||
// set the levels on which to trigger this hook.
|
|
||||||
func SetupLoggingForLevels(token, env string, levels []logrus.Level) {
|
|
||||||
setupLogging(token, env, levels)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupLogging(token, env string, levels []logrus.Level) {
|
|
||||||
logrus.SetFormatter(&logrus.TextFormatter{DisableTimestamp: true})
|
|
||||||
|
|
||||||
if token != "" {
|
|
||||||
logrus.AddHook(NewHookForLevels(token, env, levels))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReportPanic attempts to report the panic to rollbar using the provided
|
|
||||||
// client and then re-panic. If it can't report the panic it will print an
|
|
||||||
// error to stderr.
|
|
||||||
func (r *Hook) ReportPanic() {
|
|
||||||
if p := recover(); p != nil {
|
|
||||||
if _, err := r.Client.Critical(fmt.Errorf("panic: %q", p), nil); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "reporting_panic=false err=%q\n", err)
|
|
||||||
}
|
|
||||||
panic(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReportPanic attempts to report the panic to rollbar if the token is set
|
|
||||||
func ReportPanic(token, env string) {
|
|
||||||
if token != "" {
|
|
||||||
h := &Hook{Client: roll.New(token, env)}
|
|
||||||
h.ReportPanic()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Levels returns the logrus log.Levels that this hook handles
|
|
||||||
func (r *Hook) Levels() []logrus.Level {
|
|
||||||
if r.triggers == nil {
|
|
||||||
return defaultTriggerLevels
|
|
||||||
}
|
|
||||||
return r.triggers
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire the hook. This is called by Logrus for entries that match the levels
|
|
||||||
// returned by Levels().
|
|
||||||
func (r *Hook) Fire(entry *logrus.Entry) error {
|
|
||||||
trace, cause := extractError(entry)
|
|
||||||
for _, ie := range r.ignoredErrors {
|
|
||||||
if ie == cause {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.ignoreErrorFunc(cause) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m := convertFields(entry.Data)
|
|
||||||
if _, exists := m["time"]; !exists {
|
|
||||||
m["time"] = entry.Time.Format(time.RFC3339)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.ignoreFunc(cause, m) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.report(entry, cause, m, trace)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Hook) report(entry *logrus.Entry, cause error, m map[string]string, trace []uintptr) (err error) {
|
|
||||||
hasTrace := len(trace) > 0
|
|
||||||
level := entry.Level
|
|
||||||
|
|
||||||
r.reported = true
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case hasTrace && level == logrus.FatalLevel:
|
|
||||||
_, err = r.Client.CriticalStack(cause, trace, m)
|
|
||||||
case hasTrace && level == logrus.PanicLevel:
|
|
||||||
_, err = r.Client.CriticalStack(cause, trace, m)
|
|
||||||
case hasTrace && level == logrus.ErrorLevel:
|
|
||||||
_, err = r.Client.ErrorStack(cause, trace, m)
|
|
||||||
case hasTrace && level == logrus.WarnLevel:
|
|
||||||
_, err = r.Client.WarningStack(cause, trace, m)
|
|
||||||
case level == logrus.FatalLevel || level == logrus.PanicLevel:
|
|
||||||
_, err = r.Client.Critical(cause, m)
|
|
||||||
case level == logrus.ErrorLevel:
|
|
||||||
_, err = r.Client.Error(cause, m)
|
|
||||||
case level == logrus.WarnLevel:
|
|
||||||
_, err = r.Client.Warning(cause, m)
|
|
||||||
case level == logrus.InfoLevel:
|
|
||||||
_, err = r.Client.Info(entry.Message, m)
|
|
||||||
case level == logrus.DebugLevel:
|
|
||||||
_, err = r.Client.Debug(entry.Message, m)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertFields converts from log.Fields to map[string]string so that we can
|
|
||||||
// report extra fields to Rollbar
|
|
||||||
func convertFields(fields logrus.Fields) map[string]string {
|
|
||||||
m := make(map[string]string)
|
|
||||||
for k, v := range fields {
|
|
||||||
switch t := v.(type) {
|
|
||||||
case time.Time:
|
|
||||||
m[k] = t.Format(time.RFC3339)
|
|
||||||
default:
|
|
||||||
if s, ok := v.(fmt.Stringer); ok {
|
|
||||||
m[k] = s.String()
|
|
||||||
} else {
|
|
||||||
m[k] = fmt.Sprintf("%+v", t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractError attempts to extract an error from a well known field, err or error
|
|
||||||
func extractError(entry *logrus.Entry) ([]uintptr, error) {
|
|
||||||
var trace []uintptr
|
|
||||||
fields := entry.Data
|
|
||||||
|
|
||||||
type stackTracer interface {
|
|
||||||
StackTrace() errors.StackTrace
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, f := range wellKnownErrorFields {
|
|
||||||
e, ok := fields[f]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err, ok := e.(error)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cause := errors.Cause(err)
|
|
||||||
tracer, ok := err.(stackTracer)
|
|
||||||
if ok {
|
|
||||||
return copyStackTrace(tracer.StackTrace()), cause
|
|
||||||
}
|
|
||||||
return trace, cause
|
|
||||||
}
|
|
||||||
|
|
||||||
// when no error found, default to the logged message.
|
|
||||||
return trace, fmt.Errorf(entry.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyStackTrace(trace errors.StackTrace) (out []uintptr) {
|
|
||||||
for _, frame := range trace {
|
|
||||||
out = append(out, uintptr(frame))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
|
|
@ -53,10 +53,6 @@ github.com/integrii/flaggy
|
||||||
github.com/jesseduffield/asciigraph
|
github.com/jesseduffield/asciigraph
|
||||||
# github.com/jesseduffield/gocui v0.3.1-0.20200201013258-57fdcf23edc5
|
# github.com/jesseduffield/gocui v0.3.1-0.20200201013258-57fdcf23edc5
|
||||||
github.com/jesseduffield/gocui
|
github.com/jesseduffield/gocui
|
||||||
# github.com/jesseduffield/roll v0.0.0-20190629104057-695be2e62b00
|
|
||||||
github.com/jesseduffield/roll
|
|
||||||
# github.com/jesseduffield/rollrus v0.0.0-20190701125922-dd028cb0bfd7
|
|
||||||
github.com/jesseduffield/rollrus
|
|
||||||
# github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9
|
# github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9
|
||||||
github.com/jesseduffield/termbox-go
|
github.com/jesseduffield/termbox-go
|
||||||
# github.com/jesseduffield/yaml v0.0.0-20190702115811-b900b7e08b56
|
# github.com/jesseduffield/yaml v0.0.0-20190702115811-b900b7e08b56
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue