getsentry / raven-go

Sentry client in Go
https://sentry.io
BSD 3-Clause "New" or "Revised" License
561 stars 148 forks source link

Logging breadcrumbs #118

Open ernestoalejo opened 7 years ago

ernestoalejo commented 7 years ago

A method to add breadcrumbs before capturing the error.

0x4445565A commented 7 years ago

I also think this is a needed feature. I tried to implement the interface and Sentry happily accepts it but wont show the breadcurmbs/doesn't include the posted data in the JSON (HOSTNAME/sentry/:project/issues/:id/events/:eid/json).

If I could get a valid json post for breadcrumbs I could probably implement this

For reference here is the interface that I'm passing to raven(in json form)

{  
   "breadcrumbs":[  
      {  
         "timestamp":1484704331,
         "type":"default",
         "message":"This is a test",
         "category":"root",
         "string":"debug",
         "data":{  
            "foo":"Hello this is foo",
            "blub":"blub blub fishy"
         }
      },
      {  
         "timestamp":1484704331,
         "type":"default",
         "message":"This another test",
         "category":"root",
         "string":"debug",
         "data":{  
            "foo":"still foo",
            "blub":"still fishy"
         }
      }
   ]
}

And in hopes that some progress happens from this here is the the snippet that I'm using to create and send some things need to be added like the error value and the tag map. I'm assuming this is just a small change away from actually working unless it is just a fundamental issue with how Sentry's Go package creates packets to send out.

type Breadcrumb struct {
    Breadcrumbs []Crumbs `json:"breadcrumbs"`
}

type Crumbs struct {
    Timestamp int64       `json:"timestamp"`
    Type      string      `json:"type"`
    Message   string      `json:"message"`
    Category  string      `json:"category"`
    Level     string      `json:"string"`
    Data      interface{} `json:"data"`
}

func (b *Breadcrumb) Class() string {
        // Was sentry.interfaces.Breadcrumbs but changed to match interfaces.go
    return "breadcrumbs"
}

bread := &Breadcrumb{
  Breadcrumbs: []Crumbs{
    Crumbs{
      Timestamp: int64(time.Now().Unix()),
      Type:      "default",
      Message:   "This is a test",
      Category:  "root",
      Level:     "debug",
      Data: struct {
        Foo  string `json:"foo"`
        Blub string `json:"blub"`
      }{
        Foo:  "Hello this is foo",
        Blub: "blub blub fishy",
      },
    },
    Crumbs{
      Timestamp: int64(time.Now().Unix()),
      Type:      "default",
      Message:   "This another test",
      Category:  "root",
      Level:     "debug",
      Data: struct {
        Foo  string `json:"foo"`
        Blub string `json:"blub"`
      }{
        Foo:  "still foo",
        Blub: "still fishy",
      },
    },
  },
}

raven.CaptureErrorAndWait(err, tags, []raven.Interface{
    bread,
}...)
0x4445565A commented 7 years ago

Managed to get this working at least with http messages

type Breadcrumb struct {
    Breadcrumbs []Crumbs `json:"values"`
}

type Crumbs struct {
    Timestamp int64       `json:"timestamp"`
    Type      string      `json:"type"`
    Message   string      `json:"message"`
    Category  string      `json:"category"`
    Level     string      `json:"string"`
    Data      interface{} `json:"data"`
}

func (b *Breadcrumb) Class() string {
    return "breadcrumbs"
}

    bread := &Breadcrumb{
        Breadcrumbs: []Crumbs{
            Crumbs{
                Timestamp: int64(time.Now().Unix()),
                Type:      "http",
                Data: struct {
                    URL        string `json:"url"`
                    Method     string `json:"method"`
                    StatusCode int    `json:"status_code"`
                    Reason     string `json:"reason"`
                }{
                    URL:        "http://example.com/api/1.0/users",
                    Method:     "GET",
                    StatusCode: 200,
                    Reason:     "OK",
                },
            },
        },
    }
    b, _ := json.Marshal(bread)
    fmt.Println(string(b))

    raven.CaptureErrorAndWait(errors.New("Testing error"), map[string]string{"test": "yes"}, []raven.Interface{
        bread,
    }...)

This leads me to think the documentation for sentry's breadcrumb interface is incorrect. https://docs.sentry.io/clientdev/interfaces/breadcrumbs/

The example json is an object with a property breadcrumbs that is array, when in reality it needs to be a property named values.

ernestoalejo commented 7 years ago

Apart from incomplete/plain wrong documentation (I had to copy structures from the Python client and the JSON result like you did) breadcrumbs gets generated during app execution, stored in a ring list and only sent to Sentry if an error occurs. It would be very helpful to have some kind of instance where you can add and add breadcrumbs to an internal ring structure and we'll send that structure when capturing the error. Something akin to the way the HTTP info is stored in the context but using multiple instances that can be passed as additional interfaces to CaptureError or added easily to the exception struct (we're generating our custom stack traces).

I have structs similar to the ones of the last comment but I also added the logging levels as constants:

type Level string

const (
    LevelCritical = Level("critical")
    LevelWarning  = Level("warning")
    LevelError    = Level("error")
    LevelInfo     = Level("info")
    LevelDebug    = Level("debug")
)
0x4445565A commented 7 years ago

It seems sentry does have these constants available in just a slightly different form, and they are exported

https://github.com/getsentry/raven-go/blob/master/client.go#L44

You should be able to access them like raven.DEBUG only difference is they use the phrase fatal instead of critical.

ernestoalejo commented 7 years ago

I should have looked better. Thank you!

kshitij10496 commented 5 years ago

Are breadcrumbs for this library on the development Roadmap? If not, has any decision been made on whether the support for this feature would be implemented in the near future?

kamilogorek commented 5 years ago

@kshitij10496 https://github.com/getsentry/sentry-go :) (we'll move out of beta this week with all the necessary docs)