diff options
author | Unknwon <u@gogs.io> | 2018-04-25 22:13:16 -0400 |
---|---|---|
committer | Unknwon <u@gogs.io> | 2018-04-25 22:13:16 -0400 |
commit | d572381a37020f8a3d9c1e01bc37f8cfc48aaccb (patch) | |
tree | 8a0acba1f0b67ff4ba7a920c037970d15018919f /vendor/gopkg.in/clog.v1 | |
parent | 9127001f119843b787e604a0ab732e5ad7f4cb43 (diff) |
vendor: update gopkg.in/clog.v1
Diffstat (limited to 'vendor/gopkg.in/clog.v1')
-rw-r--r-- | vendor/gopkg.in/clog.v1/README.md | 18 | ||||
-rw-r--r-- | vendor/gopkg.in/clog.v1/clog.go | 9 | ||||
-rw-r--r-- | vendor/gopkg.in/clog.v1/console.go | 2 | ||||
-rw-r--r-- | vendor/gopkg.in/clog.v1/discord.go | 218 | ||||
-rw-r--r-- | vendor/gopkg.in/clog.v1/file.go | 5 | ||||
-rw-r--r-- | vendor/gopkg.in/clog.v1/slack.go | 7 |
6 files changed, 247 insertions, 12 deletions
diff --git a/vendor/gopkg.in/clog.v1/README.md b/vendor/gopkg.in/clog.v1/README.md index e66c0abc..c87d21ba 100644 --- a/vendor/gopkg.in/clog.v1/README.md +++ b/vendor/gopkg.in/clog.v1/README.md @@ -28,7 +28,7 @@ Please apply `-u` flag to update in the future. ## Getting Started -Clog currently has three builtin logger adapters: `console`, `file` and `slack`. +Clog currently has three builtin logger adapters: `console`, `file`, `slack` and `discord`. It is extremely easy to create one with all default settings. Generally, you would want to create new logger inside `init` or `main` function. @@ -140,6 +140,22 @@ Slack logger is also supported in a simple way: This logger also works for [Discord Slack](https://discordapp.com/developers/docs/resources/webhook#execute-slackcompatible-webhook) endpoint. +## Discord + +Discord logger is supported in rich format via [Embed Object](https://discordapp.com/developers/docs/resources/channel#embed-object): + +```go +... + err := log.New(log.DISCORD, log.DiscordConfig{ + Level: log.INFO, + BufferSize: 100, + URL: "https://url-to-discord-webhook", + }) +... +``` + +This logger also retries automatically if hits rate limit after `retry_after`. + ## Credits - Avatar is a modified version based on [egonelbre/gophers' scientist](https://github.com/egonelbre/gophers/blob/master/vector/science/scientist.svg). diff --git a/vendor/gopkg.in/clog.v1/clog.go b/vendor/gopkg.in/clog.v1/clog.go index 5236cae6..eb9325c1 100644 --- a/vendor/gopkg.in/clog.v1/clog.go +++ b/vendor/gopkg.in/clog.v1/clog.go @@ -24,7 +24,7 @@ import ( ) const ( - _VERSION = "1.1.1" + _VERSION = "1.2.0" ) // Version returns current version of the package. @@ -38,6 +38,13 @@ type ( ) const ( + CONSOLE MODE = "console" + FILE MODE = "file" + SLACK MODE = "slack" + DISCORD MODE = "discord" +) + +const ( TRACE LEVEL = iota INFO WARN diff --git a/vendor/gopkg.in/clog.v1/console.go b/vendor/gopkg.in/clog.v1/console.go index 0f9b7333..df81b775 100644 --- a/vendor/gopkg.in/clog.v1/console.go +++ b/vendor/gopkg.in/clog.v1/console.go @@ -20,8 +20,6 @@ import ( "github.com/fatih/color" ) -const CONSOLE MODE = "console" - // Console color set for different levels. var consoleColors = []func(a ...interface{}) string{ color.New(color.FgBlue).SprintFunc(), // Trace diff --git a/vendor/gopkg.in/clog.v1/discord.go b/vendor/gopkg.in/clog.v1/discord.go new file mode 100644 index 00000000..abc7521f --- /dev/null +++ b/vendor/gopkg.in/clog.v1/discord.go @@ -0,0 +1,218 @@ +// Copyright 2018 Unknwon +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package clog + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "time" +) + +type ( + discordEmbed struct { + Title string `json:"title"` + Description string `json:"description"` + Timestamp string `json:"timestamp"` + Color int `json:"color"` + } + + discordPayload struct { + Username string `json:"username,omitempty"` + Embeds []*discordEmbed `json:"embeds"` + } +) + +var ( + discordTitles = []string{ + "Tracing", + "Information", + "Warning", + "Error", + "Fatal", + } + + discordColors = []int{ + 0, // Trace + 3843043, // Info + 16761600, // Warn + 13041721, // Error + 9440319, // Fatal + } +) + +type DiscordConfig struct { + // Minimum level of messages to be processed. + Level LEVEL + // Buffer size defines how many messages can be queued before hangs. + BufferSize int64 + // Discord webhook URL. + URL string + // Username to be shown for the message. + // Leave empty to use default as set in the Discord. + Username string +} + +type discord struct { + Adapter + + url string + username string +} + +func newDiscord() Logger { + return &discord{ + Adapter: Adapter{ + quitChan: make(chan struct{}), + }, + } +} + +func (d *discord) Level() LEVEL { return d.level } + +func (d *discord) Init(v interface{}) error { + cfg, ok := v.(DiscordConfig) + if !ok { + return ErrConfigObject{"DiscordConfig", v} + } + + if !isValidLevel(cfg.Level) { + return ErrInvalidLevel{} + } + d.level = cfg.Level + + if len(cfg.URL) == 0 { + return errors.New("URL cannot be empty") + } + d.url = cfg.URL + d.username = cfg.Username + + d.msgChan = make(chan *Message, cfg.BufferSize) + return nil +} + +func (d *discord) ExchangeChans(errorChan chan<- error) chan *Message { + d.errorChan = errorChan + return d.msgChan +} + +func buildDiscordPayload(username string, msg *Message) (string, error) { + payload := discordPayload{ + Username: username, + Embeds: []*discordEmbed{ + { + Title: discordTitles[msg.Level], + Description: msg.Body[8:], + Timestamp: time.Now().Format(time.RFC3339), + Color: discordColors[msg.Level], + }, + }, + } + p, err := json.Marshal(&payload) + if err != nil { + return "", err + } + return string(p), nil +} + +type rateLimitMsg struct { + RetryAfter int64 `json:"retry_after"` +} + +func (d *discord) postMessage(r io.Reader) (int64, error) { + resp, err := http.Post(d.url, "application/json", r) + if err != nil { + return -1, fmt.Errorf("HTTP Post: %v", err) + } + defer resp.Body.Close() + + if resp.StatusCode == 429 { + rlMsg := &rateLimitMsg{} + if err = json.NewDecoder(resp.Body).Decode(&rlMsg); err != nil { + return -1, fmt.Errorf("decode rate limit message: %v", err) + } + + return rlMsg.RetryAfter, nil + } else if resp.StatusCode/100 != 2 { + data, _ := ioutil.ReadAll(resp.Body) + return -1, fmt.Errorf("%s", data) + } + + return -1, nil +} + +func (d *discord) write(msg *Message) { + payload, err := buildDiscordPayload(d.username, msg) + if err != nil { + d.errorChan <- fmt.Errorf("discord: builddiscordPayload: %v", err) + return + } + + const RETRY_TIMES = 3 + // Due to discord limit, try at most x times with respect to "retry_after" parameter. + for i := 1; i <= 3; i++ { + retryAfter, err := d.postMessage(bytes.NewReader([]byte(payload))) + if err != nil { + d.errorChan <- fmt.Errorf("discord: postMessage: %v", err) + return + } + + if retryAfter > 0 { + time.Sleep(time.Duration(retryAfter) * time.Millisecond) + continue + } + + return + } + + d.errorChan <- fmt.Errorf("discord: failed to send message after %d retries", RETRY_TIMES) +} + +func (d *discord) Start() { +LOOP: + for { + select { + case msg := <-d.msgChan: + d.write(msg) + case <-d.quitChan: + break LOOP + } + } + + for { + if len(d.msgChan) == 0 { + break + } + + d.write(<-d.msgChan) + } + d.quitChan <- struct{}{} // Notify the cleanup is done. +} + +func (d *discord) Destroy() { + d.quitChan <- struct{}{} + <-d.quitChan + + close(d.msgChan) + close(d.quitChan) +} + +func init() { + Register(DISCORD, newDiscord) +} diff --git a/vendor/gopkg.in/clog.v1/file.go b/vendor/gopkg.in/clog.v1/file.go index a0157d40..6b490f9c 100644 --- a/vendor/gopkg.in/clog.v1/file.go +++ b/vendor/gopkg.in/clog.v1/file.go @@ -27,9 +27,8 @@ import ( ) const ( - FILE MODE = "file" - SIMPLE_DATE_FORMAT = "2006-01-02" - LOG_PREFIX_LENGTH = len("2017/02/06 21:20:08 ") + SIMPLE_DATE_FORMAT = "2006-01-02" + LOG_PREFIX_LENGTH = len("2017/02/06 21:20:08 ") ) // FileRotationConfig represents rotation related configurations for file mode logger. diff --git a/vendor/gopkg.in/clog.v1/slack.go b/vendor/gopkg.in/clog.v1/slack.go index 5ce65577..d6c5de18 100644 --- a/vendor/gopkg.in/clog.v1/slack.go +++ b/vendor/gopkg.in/clog.v1/slack.go @@ -32,10 +32,6 @@ type slackPayload struct { Attachments []slackAttachment `json:"attachments"` } -const ( - SLACK = "slack" -) - var slackColors = []string{ "", // Trace "#3aa3e3", // Info @@ -113,13 +109,14 @@ func buildSlackPayload(msg *Message) (string, error) { func (s *slack) write(msg *Message) { payload, err := buildSlackPayload(msg) if err != nil { - s.errorChan <- fmt.Errorf("slack.buildSlackPayload: %v", err) + s.errorChan <- fmt.Errorf("slack: buildSlackPayload: %v", err) return } resp, err := http.Post(s.url, "application/json", bytes.NewReader([]byte(payload))) if err != nil { s.errorChan <- fmt.Errorf("slack: %v", err) + return } defer resp.Body.Close() |