From a96a8466cb47b10eb276650ad546620f56f31cc5 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Fri, 3 Mar 2017 21:39:37 +0000 Subject: [PATCH] Add initial golang code tracing and logging --- db/create.go | 5 ++- db/db.go | 81 ++++++++++++++++++++++++---------------- db/define.go | 18 +++++---- db/delete.go | 5 ++- db/info.go | 16 ++++---- db/let.go | 4 +- db/relate.go | 4 +- db/remove.go | 18 +++++---- db/return.go | 4 +- db/select.go | 4 +- db/update.go | 5 ++- glide.lock | 41 ++++++++++++-------- sql/parser.go | 4 ++ web/routes.go | 6 +-- web/trace.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ web/web.go | 4 ++ 16 files changed, 240 insertions(+), 80 deletions(-) create mode 100644 web/trace.go diff --git a/db/create.go b/db/create.go index 6871ea28..89e96ec4 100644 --- a/db/create.go +++ b/db/create.go @@ -16,13 +16,16 @@ package db import ( "fmt" + + "context" + "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/item" "github.com/abcum/surreal/util/keys" "github.com/abcum/surreal/util/uuid" ) -func (e *executor) executeCreateStatement(ast *sql.CreateStatement) (out []interface{}, err error) { +func (e *executor) executeCreateStatement(ctx context.Context, ast *sql.CreateStatement) (out []interface{}, err error) { for k, w := range ast.What { if what, ok := w.(*sql.Param); ok { diff --git a/db/db.go b/db/db.go index 318cd2d2..619889e3 100644 --- a/db/db.go +++ b/db/db.go @@ -15,6 +15,7 @@ package db import ( + "context" "fmt" "io" "time" @@ -30,6 +31,8 @@ import ( "github.com/abcum/surreal/mem" "github.com/abcum/surreal/sql" + "cloud.google.com/go/trace" + _ "github.com/abcum/surreal/kvs/rixxdb" // _ "github.com/abcum/surreal/kvs/dendro" ) @@ -91,6 +94,11 @@ func Begin(rw bool) (txn kvs.TX, err error) { // the underlying data layer. func Execute(ctx *fibre.Context, txt interface{}, vars map[string]interface{}) (out []*Response, err error) { + span := trace.FromContext(ctx.Context()).NewChild("db.Execute") + nctx := trace.NewContext(ctx.Context(), span) + ctx = ctx.WithContext(nctx) + defer span.Finish() + // If no preset variables have been defined // then ensure that the variables is // instantiated for future use. @@ -123,11 +131,16 @@ func Execute(ctx *fibre.Context, txt interface{}, vars map[string]interface{}) ( // data layer. func Process(ctx *fibre.Context, ast *sql.Query, vars map[string]interface{}) (out []*Response, err error) { + span := trace.FromContext(ctx.Context()).NewChild("db.Process") + nctx := trace.NewContext(ctx.Context(), span) + ctx = ctx.WithContext(nctx) + defer span.Finish() + // Create 2 channels, one for force quitting // the query processor, and the other for // receiving and buffering any query results. - quit := make(chan bool, 1) + quit := make(chan bool) recv := make(chan *Response) // Ensure that the force quit channel is auto @@ -164,7 +177,7 @@ func Process(ctx *fibre.Context, ast *sql.Query, vars map[string]interface{}) (o defer exec.done() - go exec.execute(quit, recv) + go exec.execute(ctx.Context(), quit, recv) // Wait for all of the processed queries to // return results, buffer the output, and @@ -178,7 +191,7 @@ func Process(ctx *fibre.Context, ast *sql.Query, vars map[string]interface{}) (o } -func (e *executor) execute(quit <-chan bool, send chan<- *Response) { +func (e *executor) execute(ctx context.Context, quit <-chan bool, send chan<- *Response) { var err error var now time.Time @@ -228,6 +241,9 @@ func (e *executor) execute(quit <-chan bool, send chan<- *Response) { default: + trc := trace.FromContext(ctx).NewChild(fmt.Sprint(stm)) + ctx := trace.NewContext(ctx, trc) + // If we are not inside a global transaction // then reset the error to nil so that the // next statement is not ignored. @@ -253,12 +269,15 @@ func (e *executor) execute(quit <-chan bool, send chan<- *Response) { switch stm.(type) { case *sql.BeginStatement: err = e.begin(true) + trc.Finish() continue case *sql.CancelStatement: err, buf = e.cancel(buf, err, send) + trc.Finish() continue case *sql.CommitStatement: err, buf = e.commit(buf, err, send) + trc.Finish() continue } @@ -267,7 +286,7 @@ func (e *executor) execute(quit <-chan bool, send chan<- *Response) { // subsequent statements in the transaction. if err == nil { - res, err = e.operate(stm) + res, err = e.operate(ctx, stm) } else { res, err = []interface{}{}, QueryNotExecuted } @@ -285,7 +304,6 @@ func (e *executor) execute(quit <-chan bool, send chan<- *Response) { if e.txn == nil { send <- rsp - continue } // If we are inside a global transaction we @@ -299,16 +317,17 @@ func (e *executor) execute(quit <-chan bool, send chan<- *Response) { default: buf = append(buf, rsp) } - continue } + trc.Finish() + } } } -func (e *executor) operate(ast sql.Statement) (res []interface{}, err error) { +func (e *executor) operate(ctx context.Context, ast sql.Statement) (res []interface{}, err error) { var loc bool var trw bool @@ -353,63 +372,63 @@ func (e *executor) operate(ast sql.Statement) (res []interface{}, err error) { switch stm := ast.(type) { case *sql.InfoStatement: - res, err = e.executeInfoStatement(stm) + res, err = e.executeInfoStatement(ctx, stm) case *sql.LetStatement: - res, err = e.executeLetStatement(stm) + res, err = e.executeLetStatement(ctx, stm) case *sql.ReturnStatement: - res, err = e.executeReturnStatement(stm) + res, err = e.executeReturnStatement(ctx, stm) case *sql.SelectStatement: - res, err = e.executeSelectStatement(stm) + res, err = e.executeSelectStatement(ctx, stm) case *sql.CreateStatement: - res, err = e.executeCreateStatement(stm) + res, err = e.executeCreateStatement(ctx, stm) case *sql.UpdateStatement: - res, err = e.executeUpdateStatement(stm) + res, err = e.executeUpdateStatement(ctx, stm) case *sql.DeleteStatement: - res, err = e.executeDeleteStatement(stm) + res, err = e.executeDeleteStatement(ctx, stm) case *sql.RelateStatement: - res, err = e.executeRelateStatement(stm) + res, err = e.executeRelateStatement(ctx, stm) case *sql.DefineNamespaceStatement: - res, err = e.executeDefineNamespaceStatement(stm) + res, err = e.executeDefineNamespaceStatement(ctx, stm) case *sql.RemoveNamespaceStatement: - res, err = e.executeRemoveNamespaceStatement(stm) + res, err = e.executeRemoveNamespaceStatement(ctx, stm) case *sql.DefineDatabaseStatement: - res, err = e.executeDefineDatabaseStatement(stm) + res, err = e.executeDefineDatabaseStatement(ctx, stm) case *sql.RemoveDatabaseStatement: - res, err = e.executeRemoveDatabaseStatement(stm) + res, err = e.executeRemoveDatabaseStatement(ctx, stm) case *sql.DefineLoginStatement: - res, err = e.executeDefineLoginStatement(stm) + res, err = e.executeDefineLoginStatement(ctx, stm) case *sql.RemoveLoginStatement: - res, err = e.executeRemoveLoginStatement(stm) + res, err = e.executeRemoveLoginStatement(ctx, stm) case *sql.DefineTokenStatement: - res, err = e.executeDefineTokenStatement(stm) + res, err = e.executeDefineTokenStatement(ctx, stm) case *sql.RemoveTokenStatement: - res, err = e.executeRemoveTokenStatement(stm) + res, err = e.executeRemoveTokenStatement(ctx, stm) case *sql.DefineScopeStatement: - res, err = e.executeDefineScopeStatement(stm) + res, err = e.executeDefineScopeStatement(ctx, stm) case *sql.RemoveScopeStatement: - res, err = e.executeRemoveScopeStatement(stm) + res, err = e.executeRemoveScopeStatement(ctx, stm) case *sql.DefineTableStatement: - res, err = e.executeDefineTableStatement(stm) + res, err = e.executeDefineTableStatement(ctx, stm) case *sql.RemoveTableStatement: - res, err = e.executeRemoveTableStatement(stm) + res, err = e.executeRemoveTableStatement(ctx, stm) case *sql.DefineFieldStatement: - res, err = e.executeDefineFieldStatement(stm) + res, err = e.executeDefineFieldStatement(ctx, stm) case *sql.RemoveFieldStatement: - res, err = e.executeRemoveFieldStatement(stm) + res, err = e.executeRemoveFieldStatement(ctx, stm) case *sql.DefineIndexStatement: - res, err = e.executeDefineIndexStatement(stm) + res, err = e.executeDefineIndexStatement(ctx, stm) case *sql.RemoveIndexStatement: - res, err = e.executeRemoveIndexStatement(stm) + res, err = e.executeRemoveIndexStatement(ctx, stm) } diff --git a/db/define.go b/db/define.go index b159dbb7..cb989e24 100644 --- a/db/define.go +++ b/db/define.go @@ -15,6 +15,8 @@ package db import ( + "context" + "golang.org/x/crypto/bcrypt" "github.com/abcum/surreal/sql" @@ -24,7 +26,7 @@ import ( "github.com/abcum/surreal/util/rand" ) -func (e *executor) executeDefineNamespaceStatement(ast *sql.DefineNamespaceStatement) (out []interface{}, err error) { +func (e *executor) executeDefineNamespaceStatement(ctx context.Context, ast *sql.DefineNamespaceStatement) (out []interface{}, err error) { // Set the namespace nkey := &keys.NS{KV: ast.KV, NS: ast.Name.ID} @@ -34,7 +36,7 @@ func (e *executor) executeDefineNamespaceStatement(ast *sql.DefineNamespaceState } -func (e *executor) executeDefineDatabaseStatement(ast *sql.DefineDatabaseStatement) (out []interface{}, err error) { +func (e *executor) executeDefineDatabaseStatement(ctx context.Context, ast *sql.DefineDatabaseStatement) (out []interface{}, err error) { // Set the namespace nkey := &keys.NS{KV: ast.KV, NS: ast.NS} @@ -49,7 +51,7 @@ func (e *executor) executeDefineDatabaseStatement(ast *sql.DefineDatabaseStateme } -func (e *executor) executeDefineLoginStatement(ast *sql.DefineLoginStatement) (out []interface{}, err error) { +func (e *executor) executeDefineLoginStatement(ctx context.Context, ast *sql.DefineLoginStatement) (out []interface{}, err error) { ast.Code = rand.New(128) @@ -90,7 +92,7 @@ func (e *executor) executeDefineLoginStatement(ast *sql.DefineLoginStatement) (o } -func (e *executor) executeDefineTokenStatement(ast *sql.DefineTokenStatement) (out []interface{}, err error) { +func (e *executor) executeDefineTokenStatement(ctx context.Context, ast *sql.DefineTokenStatement) (out []interface{}, err error) { if ast.Kind == sql.NAMESPACE { @@ -127,7 +129,7 @@ func (e *executor) executeDefineTokenStatement(ast *sql.DefineTokenStatement) (o } -func (e *executor) executeDefineScopeStatement(ast *sql.DefineScopeStatement) (out []interface{}, err error) { +func (e *executor) executeDefineScopeStatement(ctx context.Context, ast *sql.DefineScopeStatement) (out []interface{}, err error) { ast.Code = rand.New(128) @@ -149,7 +151,7 @@ func (e *executor) executeDefineScopeStatement(ast *sql.DefineScopeStatement) (o } -func (e *executor) executeDefineTableStatement(ast *sql.DefineTableStatement) (out []interface{}, err error) { +func (e *executor) executeDefineTableStatement(ctx context.Context, ast *sql.DefineTableStatement) (out []interface{}, err error) { // Set the namespace nkey := &keys.NS{KV: ast.KV, NS: ast.NS} @@ -175,7 +177,7 @@ func (e *executor) executeDefineTableStatement(ast *sql.DefineTableStatement) (o } -func (e *executor) executeDefineFieldStatement(ast *sql.DefineFieldStatement) (out []interface{}, err error) { +func (e *executor) executeDefineFieldStatement(ctx context.Context, ast *sql.DefineFieldStatement) (out []interface{}, err error) { // Set the namespace nkey := &keys.NS{KV: ast.KV, NS: ast.NS} @@ -206,7 +208,7 @@ func (e *executor) executeDefineFieldStatement(ast *sql.DefineFieldStatement) (o } -func (e *executor) executeDefineIndexStatement(ast *sql.DefineIndexStatement) (out []interface{}, err error) { +func (e *executor) executeDefineIndexStatement(ctx context.Context, ast *sql.DefineIndexStatement) (out []interface{}, err error) { // Set the namespace nkey := &keys.NS{KV: ast.KV, NS: ast.NS} diff --git a/db/delete.go b/db/delete.go index 27f90e64..20e530bd 100644 --- a/db/delete.go +++ b/db/delete.go @@ -16,12 +16,15 @@ package db import ( "fmt" + + "context" + "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/item" "github.com/abcum/surreal/util/keys" ) -func (e *executor) executeDeleteStatement(ast *sql.DeleteStatement) (out []interface{}, err error) { +func (e *executor) executeDeleteStatement(ctx context.Context, ast *sql.DeleteStatement) (out []interface{}, err error) { for k, w := range ast.What { if what, ok := w.(*sql.Param); ok { diff --git a/db/info.go b/db/info.go index a4a9a71f..bca3547a 100644 --- a/db/info.go +++ b/db/info.go @@ -15,26 +15,28 @@ package db import ( + "context" + "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/data" ) -func (e *executor) executeInfoStatement(ast *sql.InfoStatement) (out []interface{}, err error) { +func (e *executor) executeInfoStatement(ctx context.Context, ast *sql.InfoStatement) (out []interface{}, err error) { switch ast.Kind { case sql.NAMESPACE: - return e.executeInfoNSStatement(ast) + return e.executeInfoNSStatement(ctx, ast) case sql.DATABASE: - return e.executeInfoDBStatement(ast) + return e.executeInfoDBStatement(ctx, ast) case sql.TABLE: - return e.executeInfoTBStatement(ast) + return e.executeInfoTBStatement(ctx, ast) } return } -func (e *executor) executeInfoNSStatement(ast *sql.InfoStatement) (out []interface{}, err error) { +func (e *executor) executeInfoNSStatement(ctx context.Context, ast *sql.InfoStatement) (out []interface{}, err error) { db, err := e.mem.AllDB(ast.NS) if err != nil { @@ -74,7 +76,7 @@ func (e *executor) executeInfoNSStatement(ast *sql.InfoStatement) (out []interfa } -func (e *executor) executeInfoDBStatement(ast *sql.InfoStatement) (out []interface{}, err error) { +func (e *executor) executeInfoDBStatement(ctx context.Context, ast *sql.InfoStatement) (out []interface{}, err error) { tb, err := e.mem.AllTB(ast.NS, ast.DB) if err != nil { @@ -114,7 +116,7 @@ func (e *executor) executeInfoDBStatement(ast *sql.InfoStatement) (out []interfa } -func (e *executor) executeInfoTBStatement(ast *sql.InfoStatement) (out []interface{}, err error) { +func (e *executor) executeInfoTBStatement(ctx context.Context, ast *sql.InfoStatement) (out []interface{}, err error) { tb, err := e.mem.GetTB(ast.NS, ast.DB, ast.What.TB) if err != nil { diff --git a/db/let.go b/db/let.go index 5c41c3c9..ec48c0a9 100644 --- a/db/let.go +++ b/db/let.go @@ -15,10 +15,12 @@ package db import ( + "context" + "github.com/abcum/surreal/sql" ) -func (e *executor) executeLetStatement(ast *sql.LetStatement) (out []interface{}, err error) { +func (e *executor) executeLetStatement(ctx context.Context, ast *sql.LetStatement) (out []interface{}, err error) { switch what := ast.What.(type) { default: diff --git a/db/relate.go b/db/relate.go index a1cf0930..f2905937 100644 --- a/db/relate.go +++ b/db/relate.go @@ -15,10 +15,12 @@ package db import ( + "context" + "github.com/abcum/surreal/sql" ) -func (e *executor) executeRelateStatement(ast *sql.RelateStatement) (out []interface{}, err error) { +func (e *executor) executeRelateStatement(ctx context.Context, ast *sql.RelateStatement) (out []interface{}, err error) { return nil, nil diff --git a/db/remove.go b/db/remove.go index b6bc2776..86beec1a 100644 --- a/db/remove.go +++ b/db/remove.go @@ -15,11 +15,13 @@ package db import ( + "context" + "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/keys" ) -func (e *executor) executeRemoveNamespaceStatement(ast *sql.RemoveNamespaceStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveNamespaceStatement(ctx context.Context, ast *sql.RemoveNamespaceStatement) (out []interface{}, err error) { // Remove the namespace nkey := &keys.NS{KV: ast.KV, NS: ast.Name.ID} @@ -29,7 +31,7 @@ func (e *executor) executeRemoveNamespaceStatement(ast *sql.RemoveNamespaceState } -func (e *executor) executeRemoveDatabaseStatement(ast *sql.RemoveDatabaseStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveDatabaseStatement(ctx context.Context, ast *sql.RemoveDatabaseStatement) (out []interface{}, err error) { // Remove the database dkey := &keys.DB{KV: ast.KV, NS: ast.NS, DB: ast.Name.ID} @@ -39,7 +41,7 @@ func (e *executor) executeRemoveDatabaseStatement(ast *sql.RemoveDatabaseStateme } -func (e *executor) executeRemoveLoginStatement(ast *sql.RemoveLoginStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveLoginStatement(ctx context.Context, ast *sql.RemoveLoginStatement) (out []interface{}, err error) { if ast.Kind == sql.NAMESPACE { @@ -61,7 +63,7 @@ func (e *executor) executeRemoveLoginStatement(ast *sql.RemoveLoginStatement) (o } -func (e *executor) executeRemoveTokenStatement(ast *sql.RemoveTokenStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveTokenStatement(ctx context.Context, ast *sql.RemoveTokenStatement) (out []interface{}, err error) { if ast.Kind == sql.NAMESPACE { @@ -83,7 +85,7 @@ func (e *executor) executeRemoveTokenStatement(ast *sql.RemoveTokenStatement) (o } -func (e *executor) executeRemoveScopeStatement(ast *sql.RemoveScopeStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveScopeStatement(ctx context.Context, ast *sql.RemoveScopeStatement) (out []interface{}, err error) { // Remove the scope skey := &keys.SC{KV: ast.KV, NS: ast.NS, DB: ast.DB, SC: ast.Name.ID} @@ -93,7 +95,7 @@ func (e *executor) executeRemoveScopeStatement(ast *sql.RemoveScopeStatement) (o } -func (e *executor) executeRemoveTableStatement(ast *sql.RemoveTableStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveTableStatement(ctx context.Context, ast *sql.RemoveTableStatement) (out []interface{}, err error) { for _, TB := range ast.What { @@ -107,7 +109,7 @@ func (e *executor) executeRemoveTableStatement(ast *sql.RemoveTableStatement) (o } -func (e *executor) executeRemoveFieldStatement(ast *sql.RemoveFieldStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveFieldStatement(ctx context.Context, ast *sql.RemoveFieldStatement) (out []interface{}, err error) { for _, TB := range ast.What { @@ -121,7 +123,7 @@ func (e *executor) executeRemoveFieldStatement(ast *sql.RemoveFieldStatement) (o } -func (e *executor) executeRemoveIndexStatement(ast *sql.RemoveIndexStatement) (out []interface{}, err error) { +func (e *executor) executeRemoveIndexStatement(ctx context.Context, ast *sql.RemoveIndexStatement) (out []interface{}, err error) { for _, TB := range ast.What { diff --git a/db/return.go b/db/return.go index a51c87e0..52668863 100644 --- a/db/return.go +++ b/db/return.go @@ -15,10 +15,12 @@ package db import ( + "context" + "github.com/abcum/surreal/sql" ) -func (e *executor) executeReturnStatement(ast *sql.ReturnStatement) (out []interface{}, err error) { +func (e *executor) executeReturnStatement(ctx context.Context, ast *sql.ReturnStatement) (out []interface{}, err error) { switch what := ast.What.(type) { default: diff --git a/db/select.go b/db/select.go index 5631acd1..9e673b6d 100644 --- a/db/select.go +++ b/db/select.go @@ -15,12 +15,14 @@ package db import ( + "context" + "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/item" "github.com/abcum/surreal/util/keys" ) -func (e *executor) executeSelectStatement(ast *sql.SelectStatement) (out []interface{}, err error) { +func (e *executor) executeSelectStatement(ctx context.Context, ast *sql.SelectStatement) (out []interface{}, err error) { for k, w := range ast.What { if what, ok := w.(*sql.Param); ok { diff --git a/db/update.go b/db/update.go index 00b93f75..67abfefa 100644 --- a/db/update.go +++ b/db/update.go @@ -16,12 +16,15 @@ package db import ( "fmt" + + "context" + "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/item" "github.com/abcum/surreal/util/keys" ) -func (e *executor) executeUpdateStatement(ast *sql.UpdateStatement) (out []interface{}, err error) { +func (e *executor) executeUpdateStatement(ctx context.Context, ast *sql.UpdateStatement) (out []interface{}, err error) { for k, w := range ast.What { if what, ok := w.(*sql.Param); ok { diff --git a/glide.lock b/glide.lock index ce0fa0ce..d262708c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 323da77f9dc4a58b21e5b955a28edf6d4489cc74d3d6e61a4b2a60bdfe373b70 -updated: 2017-02-24T00:48:37.913219964Z +updated: 2017-03-03T21:38:13.520578616Z imports: - name: cloud.google.com/go version: 9b68cf4865e93f379a337b7e957f33de60397a48 @@ -12,12 +12,13 @@ imports: - logging - logging/apiv2 - logging/internal + - trace - name: github.com/abcum/cork version: 023d8293ed77a01ba325b0232e11e5f8bacea59c - name: github.com/abcum/emitr version: 67359a63b282c8056e52cf25488937aaddbc2a8b - name: github.com/abcum/fibre - version: cfe61e4d3b8a1085f93e82e2fa5f04cac5b0a6f2 + version: f00fdced46786a5a0a78ad417649e1b0977e21b6 subpackages: - mw - name: github.com/abcum/ptree @@ -99,7 +100,7 @@ imports: - name: github.com/mgutz/ansi version: 9520e82c474b0a04dd04f8a40959027271bab992 - name: github.com/miekg/dns - version: 0b729df06cb29cf7a3ff59b876e9a2ecb7fac2b1 + version: eda6b320244f0700772bb765282381d17495e7d3 - name: github.com/mitchellh/mapstructure version: db1efb556f84b25a0a13a04aad883943538ad2e0 - name: github.com/newrelic/go-agent @@ -121,9 +122,9 @@ imports: subpackages: - diffmatchpatch - name: github.com/Sirupsen/logrus - version: c078b1e43f58d563c74cebe63c85789e76ddb627 + version: 0208149b40d863d2c1a2f8fe5753096a9cf2cc8b - name: github.com/spf13/cobra - version: 92ea23a837e66f46ac9e7d04fa826602b7b0a42d + version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c - name: github.com/spf13/pflag version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 - name: github.com/ugorji/go @@ -131,18 +132,18 @@ imports: subpackages: - codec - name: github.com/yuin/gopher-lua - version: eed1c7917d2f4a7bbed5e9bf6a0ce64cbd2918c5 + version: 65fb8eeb2aa6d29a7b654d61afd1a07ce3897cc9 subpackages: - ast - parse - pm - name: golang.org/x/crypto - version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8 + version: 40541ccb1c6e64c947ed6f606b8a6cb4b67d7436 subpackages: - bcrypt - blowfish - name: golang.org/x/net - version: dd2d9a67c97da0afa00d5726e28086007a0acce5 + version: 906cda9512f77671ab44f8c8563b13a8e707b230 subpackages: - context - context/ctxhttp @@ -153,19 +154,27 @@ imports: - lex/httplex - trace - name: golang.org/x/oauth2 - version: b9780ec78894ab900c062d58ee3076cd9b2a4501 + version: efb10a30610e617dbb17fc243f4cc61a8cfa2903 subpackages: - google - internal - jws - jwt - name: golang.org/x/sys - version: e4594059fe4cde2daf423055a596c2cd1e6c9adf + version: e48874b42435b4347fc52bdee0424a52abc974d7 subpackages: - unix -- name: google.golang.org/api - version: 64485db7e8c8be51e572801d06cdbcfadd3546c1 +- name: golang.org/x/time + version: f51c12702a4d776e4c1fa9b0fabab841babae631 subpackages: + - rate +- name: google.golang.org/api + version: f786854525c2e5b0b49c2a301b0ff076d2ae20df + subpackages: + - cloudtrace/v1 + - gensupport + - googleapi + - googleapi/internal/uritemplates - googleapi/transport - internal - iterator @@ -173,7 +182,7 @@ imports: - support/bundler - transport - name: google.golang.org/appengine - version: 3a452f9e00122ead39586d68ffdb9c6e1326af3c + version: 5403c08c6e8fb3b2dc1209d2d833d8e8ac8240de subpackages: - internal - internal/app_identity @@ -187,7 +196,7 @@ imports: - socket - urlfetch - name: google.golang.org/genproto - version: dee11a626cb8e7ff045ac9413dcd8a92e72f5863 + version: 1e95789587db7d93ebbaa5eb65da17d3dbf8ab64 subpackages: - googleapis/api/annotations - googleapis/api/label @@ -197,7 +206,7 @@ imports: - googleapis/logging/v2 - googleapis/rpc/status - name: google.golang.org/grpc - version: 34384f34de585705f1a6783a158d2ec8af29f618 + version: 1dab93372523195731c738b0f0cb4e452228e959 subpackages: - codes - credentials @@ -214,7 +223,7 @@ imports: version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb testImports: - name: github.com/gopherjs/gopherjs - version: b9bcb1da229a59cc1e1d168401662cb6450aae08 + version: 7d94d732be268c4904141f8b8604eb2d6d6544a1 subpackages: - js - name: github.com/jtolds/gls diff --git a/sql/parser.go b/sql/parser.go index cd447157..aae93f33 100644 --- a/sql/parser.go +++ b/sql/parser.go @@ -20,6 +20,8 @@ import ( "strings" "github.com/abcum/fibre" + + "cloud.google.com/go/trace" ) // parser represents a parser. @@ -40,6 +42,8 @@ type parser struct { // Parse parses sql from a []byte, string, or io.Reader. func Parse(c *fibre.Context, i interface{}, v map[string]interface{}) (*Query, error) { + defer trace.FromContext(c.Context()).NewChild("sql.Parse").Finish() + if v == nil { v = make(map[string]interface{}) } diff --git a/web/routes.go b/web/routes.go index 1b76fc7a..c59b44e5 100644 --- a/web/routes.go +++ b/web/routes.go @@ -45,7 +45,7 @@ func start(c *fibre.Context, i int64) int64 { return i } -func trace(c *fibre.Context, i time.Time) time.Time { +func versn(c *fibre.Context, i time.Time) time.Time { if s := c.Query("version"); len(s) > 0 { if x, err := time.Parse(sql.RFCNano, s); err == nil { return x @@ -244,11 +244,11 @@ func routes(s *fibre.Fibre) { s.Get("/key/:class/:id", func(c *fibre.Context) error { - txt := "SELECT * FROM $thing VERSION $trace" + txt := "SELECT * FROM $thing VERSION $versn" res, err := db.Execute(c, txt, map[string]interface{}{ "thing": sql.NewThing(c.Param("class"), c.Param("id")), - "trace": trace(c, time.Now()), + "versn": versn(c, time.Now()), }) return show.Output(c, c.Param("class"), show.One, show.Select, res, err) diff --git a/web/trace.go b/web/trace.go new file mode 100644 index 00000000..0381cec2 --- /dev/null +++ b/web/trace.go @@ -0,0 +1,101 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package web + +import ( + "context" + + "github.com/abcum/fibre" + "github.com/abcum/surreal/cnf" + + "cloud.google.com/go/compute/metadata" + "cloud.google.com/go/trace" + "google.golang.org/api/option" +) + +var client *trace.Client + +// tracer returns a middleware function for stackdriver trace monitoring. +func tracer() fibre.MiddlewareFunc { + + var e error + var s trace.SamplingPolicy + var p string = cnf.Settings.Logging.Google.Project + var c string = cnf.Settings.Logging.Google.Credentials + + // If no project id has been set + // then attempt to pull this from + // machine metadata if on GCE. + + if p == "" { + if p, e = metadata.ProjectID(); e != nil { + return fibre.MiddlewareSkip + } + } + + // Connect to Stackdriver using a + // credentials file if one has been + // specified, or metadata if not. + + switch c { + case "": + client, e = trace.NewClient( + context.Background(), + p, + ) + default: + client, e = trace.NewClient( + context.Background(), + p, + option.WithServiceAccountFile(c), + ) + } + + if e != nil { + return fibre.MiddlewareSkip + } + + // Attempt to setup the Stackdriver + // client policy so that a fraction + // of requests are sent to google. + + if s, e = trace.NewLimitedSampler(1, 5); e != nil { + return fibre.MiddlewareSkip + } + + client.SetSamplingPolicy(s) + + return func(h fibre.HandlerFunc) fibre.HandlerFunc { + return func(c *fibre.Context) error { + + if c.Request().Header().Get("Upgrade") == "websocket" { + return h(c) + } + + span := client.SpanFromRequest(c.Request().Request) + + span.SetLabel("http/id", c.Get("id").(string)) + + ctx := trace.NewContext(c.Context(), span) + + c = c.WithContext(ctx) + + defer span.Finish() + + return h(c) + + } + } +} diff --git a/web/web.go b/web/web.go index e6f5c3f2..f0d2cdf2 100644 --- a/web/web.go +++ b/web/web.go @@ -47,6 +47,10 @@ func Setup(opts *cnf.Options) (err error) { s.Use(mw.Gzip()) // Gzip responses s.Use(mw.Cors()) // Add cors headers + // Add trace information + + s.Use(tracer()) + // Setup authentication s.Use(auth())