Browse Source

vendor: update gopkg.in/clog.v1

Unknwon 6 years ago
parent
commit
d572381a37

+ 17 - 1
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).

+ 8 - 1
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.
@@ -37,6 +37,13 @@ type (
 	LEVEL int
 )
 
+const (
+	CONSOLE MODE = "console"
+	FILE    MODE = "file"
+	SLACK   MODE = "slack"
+	DISCORD MODE = "discord"
+)
+
 const (
 	TRACE LEVEL = iota
 	INFO

+ 0 - 2
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

+ 218 - 0
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)
+}

+ 2 - 3
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.

+ 2 - 5
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()
 

+ 3 - 3
vendor/vendor.json

@@ -567,10 +567,10 @@
 			"revisionTime": "2015-09-24T05:17:56Z"
 		},
 		{
-			"checksumSHA1": "AbDfvggt92trYSRhGRqXW5uQ4aU=",
+			"checksumSHA1": "aDNmMYhbmT5lPFTsBPUh4ZZ5pLA=",
 			"path": "gopkg.in/clog.v1",
-			"revision": "8492a6faa632c31ba82f562b53b4a6e5eacf2732",
-			"revisionTime": "2017-05-26T21:48:39Z"
+			"revision": "3bc2eaba5fa35df0338549cc1180dc45f6fc2a16",
+			"revisionTime": "2018-04-24T23:11:46Z"
 		},
 		{
 			"checksumSHA1": "LIu3jihd3edOyIsJJK3V6vx2UZg=",