Skip to content
This repository was archived by the owner on Aug 30, 2023. It is now read-only.

Commit

Permalink
feat: Add capture functions which takes fingerprint as parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
orange committed Mar 15, 2019
1 parent 04157b8 commit 6da7a07
Showing 1 changed file with 131 additions and 73 deletions.
204 changes: 131 additions & 73 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,10 +589,7 @@ func (client *Client) worker() {
}
}

// Capture asynchronously delivers a packet to the Sentry server. It is a no-op
// when client is nil. A channel is provided if it is important to check for a
// send's success.
func (client *Client) Capture(packet *Packet, captureTags map[string]string) (eventID string, ch chan error) {
func (client *Client) doCapture(packet *Packet, captureTags map[string]string, fingerprint []string) (eventID string, ch chan error) {
ch = make(chan error, 1)

if client == nil {
Expand Down Expand Up @@ -623,6 +620,8 @@ func (client *Client) Capture(packet *Packet, captureTags map[string]string) (ev
packet.AddTags(captureTags)
packet.AddTags(client.Tags)

packet.Fingerprint = fingerprint

// Initialize any required packet fields
client.mu.RLock()
packet.AddTags(client.context.tags)
Expand Down Expand Up @@ -674,26 +673,47 @@ func (client *Client) Capture(packet *Packet, captureTags map[string]string) (ev
return packet.EventID, ch
}

// Capture asynchronously delivers a packet to the Sentry server. It is a no-op
// when client is nil. A channel is provided if it is important to check for a
// send's success.
func (client *Client) Capture(packet *Packet, captureTags map[string]string) (eventID string, ch chan error) {
return client.doCapture(packet, captureTags, []string{})
}

// Capture asynchronously delivers a packet to the Sentry server with the default *Client.
// It is a no-op when client is nil. A channel is provided if it is important to check for a
// send's success.
func Capture(packet *Packet, captureTags map[string]string) (eventID string, ch chan error) {
return DefaultClient.Capture(packet, captureTags)
}

// CaptureMessage formats and delivers a string message to the Sentry server.
func (client *Client) CaptureMessage(message string, tags map[string]string, interfaces ...Interface) string {
// CaptureWithFingerprint is identical to Capture except it includes specified fingerprint in the packet.
func (client *Client) CaptureWithFingerprint(packet *Packet, captureTags map[string]string, fingerprint []string) (eventID string, ch chan error) {
return client.doCapture(packet, captureTags, fingerprint)
}

// CaptureWithFingerprint is identical to Capture except it includes specified fingerprint in the packet.
func CaptureWithFingerprint(packet *Packet, captureTags map[string]string, fingerprint []string) (eventID string, ch chan error) {
return DefaultClient.CaptureWithFingerprint(packet, captureTags, fingerprint)
}

func (client *Client) doCaptureMessage(message string, tags map[string]string, fingerprint []string, interfaces ...Interface) (eventID string, ch chan error) {
if client == nil {
return ""
return "", nil
}

if client.shouldExcludeErr(message) {
return ""
return "", nil
}

packet := NewPacket(message, append(append(interfaces, client.context.interfaces()...), &Message{message, nil})...)
eventID, _ := client.Capture(packet, tags)

return client.CaptureWithFingerprint(packet, tags, fingerprint)
}

// CaptureMessage formats and delivers a string message to the Sentry server.
func (client *Client) CaptureMessage(message string, tags map[string]string, interfaces ...Interface) string {
eventID, _ := client.doCaptureMessage(message, tags, []string{}, interfaces...)
return eventID
}

Expand All @@ -702,18 +722,19 @@ func CaptureMessage(message string, tags map[string]string, interfaces ...Interf
return DefaultClient.CaptureMessage(message, tags, interfaces...)
}

// CaptureMessageAndWait is identical to CaptureMessage except it blocks and waits for the message to be sent.
func (client *Client) CaptureMessageAndWait(message string, tags map[string]string, interfaces ...Interface) string {
if client == nil {
return ""
}
// CaptureMessageWithFingerprint is identical to CaptureMessage except it includes specified fingerprint in the packet.
func (client *Client) CaptureMessageWithFingerprint(message string, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
eventID, _ := client.doCaptureMessage(message, tags, fingerprint, interfaces...)
return eventID
}

if client.shouldExcludeErr(message) {
return ""
}
func CaptureMessageWithFingerprint(message string, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
return DefaultClient.CaptureMessageWithFingerprint(message, tags, fingerprint, interfaces...)
}

packet := NewPacket(message, append(append(interfaces, client.context.interfaces()...), &Message{message, nil})...)
eventID, ch := client.Capture(packet, tags)
// CaptureMessageAndWait is identical to CaptureMessage except it includes specified fingerprint in the packet.
func (client *Client) CaptureMessageAndWait(message string, tags map[string]string, interfaces ...Interface) string {
eventID, ch := client.doCaptureMessage(message, tags, []string{}, interfaces...)
if eventID != "" {
<-ch
}
Expand All @@ -726,27 +747,45 @@ func CaptureMessageAndWait(message string, tags map[string]string, interfaces ..
return DefaultClient.CaptureMessageAndWait(message, tags, interfaces...)
}

// CaptureError formats and delivers an error to the Sentry server.
// Adds a stacktrace to the packet, excluding the call to this method.
func (client *Client) CaptureError(err error, tags map[string]string, interfaces ...Interface) string {
// CaptureMessageWithFingerprintAndWait is identical to CaptureMessageAndWait except it includes specified fingerprint in the packet.
func (client *Client) CaptureMessageWithFingerprintAndWait(message string, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
eventID, ch := client.doCaptureMessage(message, tags, fingerprint, interfaces...)
if eventID != "" {
<-ch
}

return eventID
}

// CaptureMessageWithFingerprintAndWait is identical to CaptureMessageAndWait except it includes specified fingerprint in the packet.
func CaptureMessageWithFingerprintAndWait(message string, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
return DefaultClient.CaptureMessageWithFingerprintAndWait(message, tags, fingerprint, interfaces...)
}

func (client *Client) doCaptureError(err error, tags map[string]string, fingerprint []string, interfaces ...Interface) (string, chan error) {
if client == nil {
return ""
return "", nil
}

if err == nil {
return ""
return "", nil
}

if client.shouldExcludeErr(err.Error()) {
return ""
return "", nil
}

extra := extractExtra(err)
cause := Cause(err)

packet := NewPacketWithExtra(err.Error(), extra, append(append(interfaces, client.context.interfaces()...), NewException(cause, GetOrNewStacktrace(cause, 1, 3, client.includePaths)))...)
eventID, _ := client.Capture(packet, tags)
return client.CaptureWithFingerprint(packet, tags, fingerprint)
}

// CaptureError formats and delivers an error to the Sentry server.
// Adds a stacktrace to the packet, excluding the call to this method.
func (client *Client) CaptureError(err error, tags map[string]string, interfaces ...Interface) string {
eventID, _ := client.doCaptureError(err, tags, []string{}, interfaces...)
return eventID
}

Expand All @@ -756,36 +795,48 @@ func CaptureError(err error, tags map[string]string, interfaces ...Interface) st
return DefaultClient.CaptureError(err, tags, interfaces...)
}

// CaptureErrorWithFingerprint is identical to CaptureError except it includes specified fingerprint in the packet.
func (client *Client) CaptureErrorWithFingerprint(err error, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
eventID, _ := client.doCaptureError(err, tags, fingerprint, interfaces...)
return eventID
}

// CaptureErrorWithFingerprint is identical to CaptureError except it includes specified fingerprint in the packet.
func CaptureErrorWithFingerprint(err error, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
return DefaultClient.CaptureErrorWithFingerprint(err, tags, fingerprint, interfaces...)
}

// CaptureErrorAndWait is identical to CaptureError, except it blocks and assures that the event was sent
func (client *Client) CaptureErrorAndWait(err error, tags map[string]string, interfaces ...Interface) string {
if client == nil {
return ""
eventID, ch := client.doCaptureError(err, tags, []string{}, interfaces...)
if eventID != "" {
<-ch
}

if client.shouldExcludeErr(err.Error()) {
return ""
}
return eventID
}

extra := extractExtra(err)
cause := Cause(err)
// CaptureErrorAndWait is identical to CaptureError, except it blocks and assures that the event was sent
func CaptureErrorAndWait(err error, tags map[string]string, interfaces ...Interface) string {
return DefaultClient.CaptureErrorAndWait(err, tags, interfaces...)
}

packet := NewPacketWithExtra(err.Error(), extra, append(append(interfaces, client.context.interfaces()...), NewException(cause, GetOrNewStacktrace(cause, 1, 3, client.includePaths)))...)
eventID, ch := client.Capture(packet, tags)
// CaptureErrorWithFingerprint is identical to CaptureErrorAndWait except it includes specified fingerprint in the packet.
func (client *Client) CaptureErrorWithFingerprintAndWait(err error, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
eventID, ch := client.doCaptureError(err, tags, fingerprint, interfaces...)
if eventID != "" {
<-ch
}

return eventID
}

// CaptureErrorAndWait is identical to CaptureError, except it blocks and assures that the event was sent
func CaptureErrorAndWait(err error, tags map[string]string, interfaces ...Interface) string {
return DefaultClient.CaptureErrorAndWait(err, tags, interfaces...)
// CaptureErrorWithFingerprint is identical to CaptureErrorAndWait except it includes specified fingerprint in the packet.
func CaptureErrorWithFingerprintAndWait(err error, tags map[string]string, fingerprint []string, interfaces ...Interface) string {
return DefaultClient.CaptureErrorWithFingerprintAndWait(err, tags, fingerprint, interfaces...)
}

// CapturePanic calls f and then recovers and reports a panic to the Sentry server if it occurs.
// If an error is captured, both the error and the reported Sentry error ID are returned.
func (client *Client) CapturePanic(f func(), tags map[string]string, interfaces ...Interface) (err interface{}, errorID string) {
func (client *Client) doCapturePanic(f func(), tags map[string]string, fingerprint []string, interfaces ...Interface) (err interface{}, errorID string, ch chan error) {
// Note: This doesn't need to check for client, because we still want to go through the defer/recover path
// Down the line, Capture will be noop'd, so while this does a _tiny_ bit of overhead constructing the
// *Packet just to be thrown away, this should not be the normal case. Could be refactored to
Expand All @@ -809,60 +860,67 @@ func (client *Client) CapturePanic(f func(), tags map[string]string, interfaces
packet = NewPacket(rvalStr, append(append(interfaces, client.context.interfaces()...), NewException(errors.New(rvalStr), NewStacktrace(2, 3, client.includePaths)))...)
}

errorID, _ = client.Capture(packet, tags)
errorID, ch = client.CaptureWithFingerprint(packet, tags, fingerprint)
}()

f()
return
}

// CapturePanic calls f and then recovers and reports a panic to the Sentry server if it occurs.
// If an error is captured, both the error and the reported Sentry error ID are returned.
func (client *Client) CapturePanic(f func(), tags map[string]string, interfaces ...Interface) (err interface{}, errorID string) {
err, eventID, _ := client.doCapturePanic(f, tags, []string{}, interfaces...)
return err, eventID
}

// CapturePanic calls f and then recovers and reports a panic to the Sentry server if it occurs.
// If an error is captured, both the error and the reported Sentry error ID are returned.
func CapturePanic(f func(), tags map[string]string, interfaces ...Interface) (interface{}, string) {
return DefaultClient.CapturePanic(f, tags, interfaces...)
}

// CapturePanicWithFingerprint is identical to CapturePanic except it includes specified fingerprint in the packet.
func (client *Client) CapturePanicWithFingerprint(f func(), tags map[string]string, fingerprint []string, interfaces ...Interface) (err interface{}, errorID string) {
err, eventID, _ := client.doCapturePanic(f, tags, fingerprint, interfaces...)
return err, eventID
}

// CapturePanicWithFingerprint is identical to CapturePanic except it includes specified fingerprint in the packet.
func CapturePanicWithFingerprint(f func(), tags map[string]string, fingerprint []string, interfaces ...Interface) (interface{}, string) {
return DefaultClient.CapturePanicWithFingerprint(f, tags, fingerprint, interfaces...)
}

// CapturePanicAndWait is identical to CapturePanic, except it blocks and assures that the event was sent
func (client *Client) CapturePanicAndWait(f func(), tags map[string]string, interfaces ...Interface) (err interface{}, errorID string) {
// Note: This doesn't need to check for client, because we still want to go through the defer/recover path
// Down the line, Capture will be noop'd, so while this does a _tiny_ bit of overhead constructing the
// *Packet just to be thrown away, this should not be the normal case. Could be refactored to
// be completely noop though if we cared.
defer func() {
var packet *Packet
err = recover()
switch rval := err.(type) {
case nil:
return
case error:
if client.shouldExcludeErr(rval.Error()) {
return
}
packet = NewPacket(rval.Error(), append(append(interfaces, client.context.interfaces()...), NewException(rval, NewStacktrace(2, 3, client.includePaths)))...)
default:
rvalStr := fmt.Sprint(rval)
if client.shouldExcludeErr(rvalStr) {
return
}
packet = NewPacket(rvalStr, append(append(interfaces, client.context.interfaces()...), NewException(errors.New(rvalStr), NewStacktrace(2, 3, client.includePaths)))...)
}

var ch chan error
errorID, ch = client.Capture(packet, tags)
if errorID != "" {
<-ch
}
}()
err, eventID, ch := client.doCapturePanic(f, tags, []string{}, interfaces...)
if errorID != "" {
<-ch
}

f()
return
return err, eventID
}

// CapturePanicAndWait is identical to CapturePanic, except it blocks and assures that the event was sent
func CapturePanicAndWait(f func(), tags map[string]string, interfaces ...Interface) (interface{}, string) {
return DefaultClient.CapturePanicAndWait(f, tags, interfaces...)
}

// CapturePanicWithFingerprintAndWait is identical to CapturePanicAndWait except it includes specified fingerprint in the packet.
func (client *Client) CapturePanicWithFingerprintAndWait(f func(), tags map[string]string, fingerprint []string, interfaces ...Interface) (err interface{}, errorID string) {
err, eventID, ch := client.doCapturePanic(f, tags, fingerprint, interfaces...)
if errorID != "" {
<-ch
}

return err, eventID
}

// CapturePanicWithFingerprintAndWait is identical to CapturePanicAndWait except it includes specified fingerprint in the packet.
func CapturePanicWithFingerprintAndWait(f func(), tags map[string]string, fingerprint []string, interfaces ...Interface) (interface{}, string) {
return DefaultClient.CapturePanicWithFingerprintAndWait(f, tags, fingerprint, interfaces...)
}

// Close given clients event queue
func (client *Client) Close() {
close(client.queue)
Expand Down

0 comments on commit 6da7a07

Please # to comment.