github.com/koron/hk@v0.0.0-20150303213137-b8aeaa3ab34c/rollbar/rollbar.go (about)

     1  package rollbar
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"runtime"
     9  	"time"
    10  )
    11  
    12  type Client struct {
    13  	AppName    string
    14  	AppVersion string
    15  	Endpoint   string
    16  	Token      string
    17  }
    18  
    19  func (c *Client) Report(message string) error {
    20  	body := c.buildBody()
    21  	data := body["data"].(map[string]interface{})
    22  	data["body"] = c.errorBody(message, 2)
    23  
    24  	jsonBody, err := json.Marshal(body)
    25  	if err != nil {
    26  		return err
    27  	}
    28  
    29  	resp, err := http.Post(c.Endpoint, "application/json", bytes.NewReader(jsonBody))
    30  	if err != nil {
    31  		return err
    32  	}
    33  	defer resp.Body.Close()
    34  
    35  	if resp.StatusCode/100 != 2 { // 200, 201, 202, etc
    36  		return fmt.Errorf("unexpected status code %d", resp.StatusCode)
    37  	}
    38  	return nil
    39  }
    40  
    41  func (c *Client) errorBody(message string, skip int) map[string]interface{} {
    42  	return map[string]interface{}{
    43  		"trace": map[string]interface{}{
    44  			"frames": c.stacktraceFrames(3 + skip),
    45  			"exception": map[string]interface{}{
    46  				"class":   "",
    47  				"message": message,
    48  			},
    49  		},
    50  	}
    51  }
    52  
    53  func (c *Client) stacktraceFrames(skip int) []map[string]interface{} {
    54  	frames := []map[string]interface{}{}
    55  
    56  	for i := skip; ; i++ {
    57  		pc, file, line, ok := runtime.Caller(i)
    58  		if !ok {
    59  			break
    60  		}
    61  		f := runtime.FuncForPC(pc)
    62  		fname := "unknown"
    63  		if f != nil {
    64  			fname = f.Name()
    65  		}
    66  		frames = append(frames, map[string]interface{}{
    67  			"filename": file,
    68  			"lineno":   line,
    69  			"method:":  fname,
    70  		})
    71  	}
    72  	return frames
    73  }
    74  
    75  func (c *Client) buildBody() map[string]interface{} {
    76  	timestamp := time.Now().UTC().Unix()
    77  
    78  	return map[string]interface{}{
    79  		"access_token": c.Token,
    80  		"data": map[string]interface{}{
    81  			"environment": "production",
    82  			"timestamp":   timestamp,
    83  			"platform":    "client",
    84  			"language":    "go",
    85  			"notifier": map[string]interface{}{
    86  				"name":    c.AppName,
    87  				"version": c.AppVersion,
    88  			},
    89  			"client": map[string]interface{}{
    90  				"arch":     runtime.GOARCH,
    91  				"platform": runtime.GOOS,
    92  			},
    93  		},
    94  	}
    95  }