Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sentry Integration - Capture Manual panics with Sentry Exception and runtime panics with a wrapper on panic #4756

Merged
merged 15 commits into from
Mar 11, 2020
3 changes: 2 additions & 1 deletion chunker/chunk.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ func NewChunker(inputFormat InputFormat, batchSize int) Chunker {
nqs: NewNQuadBuffer(batchSize),
}
default:
panic("unknown input format")
x.PanicWithSentryException(errors.New("unknown input format"))
return nil
}
}

Expand Down
11 changes: 6 additions & 5 deletions codec/benchmark/benchmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ package main
import (
"compress/gzip"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -59,28 +60,28 @@ const (
func read(filename string) []int {
f, err := os.Open(filename)
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}
defer f.Close()

fgzip, err := gzip.NewReader(f)
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}
defer fgzip.Close()

buf := make([]byte, 4)
_, err = fgzip.Read(buf)
if err != nil && err != io.EOF {
panic(err)
x.PanicWithSentryException(err)
}
ndata := binary.LittleEndian.Uint32(buf)

data := make([]int, ndata)
for i := range data {
_, err = fgzip.Read(buf)
if err != nil && err != io.EOF {
panic(err)
x.PanicWithSentryException(err)
}

data[i] = int(binary.LittleEndian.Uint32(buf))
Expand Down Expand Up @@ -176,7 +177,7 @@ func fmtBenchmark(name string, speed int) {
func main() {
data := read("clustered1M.bin.gz")
if !sort.IsSorted(sort.IntSlice(data)) {
panic("test data must be sorted")
x.PanicWithSentryException(errors.New("test data must be sorted"))
}

chunks64 := chunkify64(data)
Expand Down
3 changes: 2 additions & 1 deletion contrib/integration/swap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/dgraph-io/dgo/v2/protos/api"
"github.com/dgraph-io/dgraph/testutil"
"github.com/dgraph-io/dgraph/x"
"github.com/pkg/errors"
)

var (
Expand Down Expand Up @@ -367,7 +368,7 @@ func checkInvariants(c *dgo.Dgraph, uids []string, sentences []string) error {
sort.Strings(gotUids)
sort.Strings(uids)
if !reflect.DeepEqual(gotUids, uids) {
panic(fmt.Sprintf(`query: %s\n
x.PanicWithSentryException(errors.Errorf(`query: %s\n
Uids in index for %q didn't match
calculated: %v. Len: %d
got: %v
Expand Down
10 changes: 9 additions & 1 deletion dgraph/cmd/alpha/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,8 +586,16 @@ func run() {
x.Config.QueryEdgeLimit = cast.ToUint64(Alpha.Conf.GetString("query_edge_limit"))
x.Config.NormalizeNodeLimit = cast.ToInt(Alpha.Conf.GetString("normalize_node_limit"))

x.PrintVersion()
x.InitSentry(enc.EeBuild)
defer x.FlushSentry()
x.ConfigureSentryScope("alpha")
x.WrapPanics()

// Simulate a Sentry exception or panic event as shown below.
// x.CaptureSentryException(errors.New("alpha exception"))
// x.PanicWithSentryException(errors.New("alpha manual panic will send 2 events"))

x.PrintVersion()
glog.Infof("x.Config: %+v", x.Config)
glog.Infof("x.WorkerConfig: %+v", x.WorkerConfig)
glog.Infof("worker.Config: %+v", worker.Config)
Expand Down
2 changes: 1 addition & 1 deletion dgraph/cmd/counter/increment.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func queryCounter(ctx context.Context, txn *dgo.Txn, pred string) (Counter, erro
case 1:
counter = m["q"][0]
default:
panic(fmt.Sprintf("Invalid response: %q", resp.Json))
x.PanicWithSentryException(errors.Errorf("Invalid response: %q", resp.Json))
}
span.Annotatef(nil, "Found counter: %+v", counter)
counter.startTs = resp.GetTxn().GetStartTs()
Expand Down
3 changes: 2 additions & 1 deletion dgraph/cmd/migrate/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"reflect"
"strings"

"github.com/dgraph-io/dgraph/x"
"github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -119,7 +120,7 @@ func getColumnValues(columns []string, dataTypes []dataType,
case datetimeType:
valuePtrs = append(valuePtrs, new(mysql.NullTime))
default:
panic(fmt.Sprintf("detected unsupported type %s on column %s",
x.PanicWithSentryException(errors.Errorf("detected unsupported type %s on column %s",
dataTypes[i], columns[i]))
}
}
Expand Down
20 changes: 14 additions & 6 deletions dgraph/cmd/zero/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package zero

import (
"context"
// "errors"
"fmt"
"log"
"net"
Expand All @@ -36,6 +37,7 @@ import (
"github.com/dgraph-io/badger/v2"
"github.com/dgraph-io/badger/v2/y"
"github.com/dgraph-io/dgraph/conn"
"github.com/dgraph-io/dgraph/ee/enc"
"github.com/dgraph-io/dgraph/protos/pb"
"github.com/dgraph-io/dgraph/raftwal"
"github.com/dgraph-io/dgraph/x"
Expand Down Expand Up @@ -192,14 +194,20 @@ func run() {
if len(opts.myAddr) == 0 {
opts.myAddr = fmt.Sprintf("localhost:%d", x.PortZeroGrpc+opts.portOffset)
}

x.InitSentry(enc.EeBuild)
defer x.FlushSentry()
x.ConfigureSentryScope("zero")
x.WrapPanics()

// Simulate a Sentry exception or panic event as shown below.
// x.CaptureSentryException(errors.New("zero exception"))
// x.PanicWithSentryException(errors.New("zero manual panic will send 2 events"))

grpcListener, err := setupListener(addr, x.PortZeroGrpc+opts.portOffset, "grpc")
if err != nil {
log.Fatal(err)
}
x.Check(err)
httpListener, err := setupListener(addr, x.PortZeroHTTP+opts.portOffset, "http")
if err != nil {
log.Fatal(err)
}
x.Check(err)

// Open raft write-ahead log and initialize raft node.
x.Checkf(os.MkdirAll(opts.w, 0700), "Error while creating WAL dir.")
Expand Down
4 changes: 2 additions & 2 deletions graphql/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ type adminServer struct {
func NewServers(withIntrospection bool, closer *y.Closer) (web.IServeGraphQL, web.IServeGraphQL) {
gqlSchema, err := schema.FromString("")
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}

resolvers := resolve.New(gqlSchema, resolverFactoryWithErrorMsg(errNoGraphQLSchema))
Expand All @@ -193,7 +193,7 @@ func newAdminResolver(

adminSchema, err := schema.FromString(graphqlAdminSchema)
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}

rf := newAdminResolverFactory()
Expand Down
20 changes: 10 additions & 10 deletions graphql/e2e/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"compress/gzip"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
Expand Down Expand Up @@ -152,36 +151,37 @@ type director struct {
func BootstrapServer(schema, data []byte) {
err := checkGraphQLStarted(graphqlAdminURL)
if err != nil {
panic(fmt.Sprintf("Waited for GraphQL test server to become available, but it never did.\n"+
"Got last error %+v", err.Error()))
x.PanicWithSentryException(errors.Errorf(
"Waited for GraphQL test server to become available, but it never did.\n"+
"Got last error %+v", err.Error()))
}

err = checkGraphQLStarted(graphqlAdminTestAdminURL)
if err != nil {
panic(fmt.Sprintf("Waited for GraphQL AdminTest server to become available, "+
"but it never did.\n Got last error: %+v", err.Error()))
x.PanicWithSentryException(errors.Errorf(
"Waited for GraphQL AdminTest server to become available, "+
"but it never did.\n Got last error: %+v", err.Error()))
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
d, err := grpc.DialContext(ctx, alphagRPC, grpc.WithInsecure())
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}
client := dgo.NewDgraphClient(api.NewDgraphClient(d))

err = addSchema(graphqlAdminURL, string(schema))
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}

err = populateGraphQLData(client, data)
if err != nil {
panic(err)
x.PanicWithSentryException(err)
}

if err = d.Close(); err != nil {
panic(err)
x.PanicWithSentryException(err)
}
}

Expand Down
11 changes: 7 additions & 4 deletions graphql/e2e/common/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package common
import (
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http/httptest"
Expand All @@ -40,8 +41,8 @@ import (
)

const (
panicMsg = "\n****\nThis test should trap this panic.\n" +
"It's working as expected if this message is logged with a stack trace.\n****\n"
panicMsg = "\n****\nthis test should trap this panic.\n" +
"It's working as expected if this message is logged with a stack trace\n****"
)

type ErrorCase struct {
Expand Down Expand Up @@ -263,12 +264,14 @@ func panicCatcher(t *testing.T) {
type panicClient struct{}

func (dg *panicClient) Query(ctx context.Context, query *gql.GraphQuery) ([]byte, error) {
panic(panicMsg)
x.PanicWithSentryException(errors.New(panicMsg))
return nil, nil
}

func (dg *panicClient) Mutate(
ctx context.Context,
query *gql.GraphQuery,
mutations []*dgoapi.Mutation) (map[string]string, map[string]interface{}, error) {
panic(panicMsg)
x.PanicWithSentryException(errors.New(panicMsg))
return nil, nil, nil
}
4 changes: 2 additions & 2 deletions graphql/schema/gqlschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func copyAstFieldDef(src *ast.FieldDefinition) *ast.FieldDefinition {
func expandSchema(doc *ast.SchemaDocument) {
docExtras, gqlErr := parser.ParseSchema(&ast.Source{Input: schemaExtras})
if gqlErr != nil {
panic(gqlErr)
x.PanicWithSentryException(gqlErr)
}

// Cache the interface definitions in a map. They could also be defined after types which
Expand Down Expand Up @@ -1301,7 +1301,7 @@ func Stringify(schema *ast.Schema, originalTypes []string) string {
// the generated definitions.
docExtras, gqlErr := parser.ParseSchema(&ast.Source{Input: schemaExtras})
if gqlErr != nil {
panic(gqlErr)
x.PanicWithSentryException(gqlErr)
}
for _, defn := range docExtras.Definitions {
printed[defn.Name] = true
Expand Down
2 changes: 1 addition & 1 deletion graphql/web/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer span.End()

if !gh.isValid() {
panic("graphqlHandler not initialised")
x.PanicWithSentryException(errors.New("graphqlHandler not initialised"))
}

ctx = x.AttachAccessJwt(ctx, r)
Expand Down
10 changes: 8 additions & 2 deletions types/facets/facet_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@

package facets

import "github.com/dgraph-io/dgo/v2/protos/api"
import (
"errors"

"github.com/dgraph-io/dgo/v2/protos/api"
"github.com/dgraph-io/dgraph/x"
)

const (
// IntID represents the integer type.
Expand Down Expand Up @@ -48,5 +53,6 @@ func ValTypeForTypeID(typId TypeID) api.Facet_ValType {
case StringID:
return api.Facet_STRING
}
panic("Unhandled case in ValTypeForTypeID.")
x.PanicWithSentryException(errors.New("unhandled case in ValTypeForTypeID"))
return api.Facet_ValType(0)
}
9 changes: 8 additions & 1 deletion worker/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@

package worker

import (
"errors"

"github.com/dgraph-io/dgraph/x"
)

func evalCompare(cmp string, lv, rv int64) bool {
switch cmp {
case "le":
Expand All @@ -29,5 +35,6 @@ func evalCompare(cmp string, lv, rv int64) bool {
case "eq":
return lv == rv
}
panic("EvalCompare: unreachable")
x.PanicWithSentryException(errors.New("EvalCompare: unreachable"))
return false
}
2 changes: 1 addition & 1 deletion worker/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func escapedString(str string) string {
// All valid stings should be able to be escaped to a JSON string so
// it's safe to panic here. Marshal has to return an error because it
// accepts an interface.
panic("Could not marshal string to JSON string")
x.PanicWithSentryException(errors.New("Could not marshal string to JSON string"))
}
return string(byt)
}
Expand Down
4 changes: 3 additions & 1 deletion x/histogram.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package x

import (
"errors"
"sync"
"time"

Expand All @@ -41,7 +42,8 @@ type slidingHistogram struct {
// details.
func newSlidingHistogram(duration time.Duration, maxVal int64, sigFigs int) *slidingHistogram {
if duration <= 0 {
panic("cannot create a sliding histogram with nonpositive duration")
PanicWithSentryException(errors.New(
"cannot create a sliding histogram with nonpositive duration"))
}
return &slidingHistogram{
nextT: time.Now(),
Expand Down
2 changes: 1 addition & 1 deletion x/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ func GetSplitKey(baseKey []byte, startUid uint64) ([]byte, error) {

index := 1 + 2 + len(p.Attr) + 1
if index >= len(keyCopy) {
panic("Cannot write to key. Key is too small")
PanicWithSentryException(errors.New("Cannot write to key. Key is too small"))
}
keyCopy[index] = ByteSplit
binary.BigEndian.PutUint64(keyCopy[len(baseKey):], startUid)
Expand Down
Loading