summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/stvp/roll/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/stvp/roll/client.go')
-rw-r--r--vendor/github.com/stvp/roll/client.go240
1 files changed, 240 insertions, 0 deletions
diff --git a/vendor/github.com/stvp/roll/client.go b/vendor/github.com/stvp/roll/client.go
new file mode 100644
index 000000000..687343f2a
--- /dev/null
+++ b/vendor/github.com/stvp/roll/client.go
@@ -0,0 +1,240 @@
+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 {
+ return "", err
+ }
+ defer func() {
+ io.Copy(ioutil.Discard, resp.Body)
+ resp.Body.Close()
+ }()
+
+ if resp.StatusCode != http.StatusOK {
+ return "", fmt.Errorf("Rollbar returned %s", resp.Status)
+ }
+
+ // 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, "*")
+ }
+}