From 3b5a53570ddbbb65bac89311eea247f97813680b Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Mon, 19 Sep 2022 16:56:28 +0530 Subject: [PATCH 01/27] Added support for Query Row and Query Context --- go/go-sql.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ go/go.mod | 5 ++++ go/go.sum | 2 ++ 3 files changed, 83 insertions(+) create mode 100644 go/go-sql.go create mode 100644 go/go.mod create mode 100644 go/go.sum diff --git a/go/go-sql.go b/go/go-sql.go new file mode 100644 index 00000000..28329d20 --- /dev/null +++ b/go/go-sql.go @@ -0,0 +1,76 @@ +package sqlcommenterGo + +import ( + "context" + "database/sql" + "encoding/json" + "fmt" + "net/url" + "strings" + + _ "github.com/go-sql-driver/mysql" +) + +type DB struct { + *sql.DB + commenterOptions map[string]bool +} + +var goSQLCommenterTags = map[string]string{"dbDriver": "go/sql"} + +func Open(driverName, dataSourceName string, commenterOptions map[string]bool) (*DB, error) { + db, err := sql.Open(driverName, dataSourceName) + return &DB{DB: db, commenterOptions: commenterOptions}, err +} + +func (db *DB) QueryRow(query string, args ...interface{}) any { + return db.DB.QueryRow(db.withComment(context.Background(), query), args...) +} + +func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error) { + return db.DB.QueryContext(ctx, db.withComment(ctx, query), args...) +} + +func (db *DB) withComment(ctx context.Context, query string) string { + + var finalCommentsMap = map[string]string{} + var finalCommentsStr string = "" + query = strings.TrimSpace(query) + + for key, element := range db.commenterOptions { + if element { // Checks if option is set as true + if _, ok := goSQLCommenterTags[key]; ok { // Check if static value is assigned and if true append + finalCommentsMap[key] = goSQLCommenterTags[key] + } else if ctx.Value(key) != nil { // Append if key is avaliable in context + finalCommentsMap[key] = ctx.Value(key).(string) + } + } + + } + if len(finalCommentsMap) > 0 { // Converts comments map to string and appends it to query + jsonStr, err := json.Marshal(finalCommentsMap) + if err != nil { + fmt.Printf("Error: %s", err.Error()) + } else { + finalCommentsStr = strings.Replace(string(jsonStr), "{", "/*", 1) + finalCommentsStr = strings.Replace(string(finalCommentsStr), "}", "*/", 1) + } + } + + if strings.Contains(query, ";") { + query = strings.Replace(string(query), ";", "", 1) + return fmt.Sprintf("%s%s;", query, finalCommentsStr) + } + return fmt.Sprintf("%s%s", query, finalCommentsStr) + +} + +// TODO: +func encodeValue(v string) string { + urlEscape := strings.ReplaceAll(url.PathEscape(string(v)), "+", "%20") + return fmt.Sprintf("'%s'", urlEscape) +} + +func encodeKey(k string) string { + return url.QueryEscape(string(k)) +} diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 00000000..54833be9 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,5 @@ +module google.com/sqlcommenterGo + +go 1.19 + +require github.com/go-sql-driver/mysql v1.6.0 diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 00000000..20c16d6f --- /dev/null +++ b/go/go.sum @@ -0,0 +1,2 @@ +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= From f9b7cad340a9747885a365afb8064d0c3cb7c1cd Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Thu, 22 Sep 2022 12:03:34 +0530 Subject: [PATCH 02/27] Added support for http-router --- go/go-http-router.go | 12 ++++++++++++ go/go-sql.go | 30 +++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 go/go-http-router.go diff --git a/go/go-http-router.go b/go/go-http-router.go new file mode 100644 index 00000000..47e087c4 --- /dev/null +++ b/go/go-http-router.go @@ -0,0 +1,12 @@ +package sqlcommenter + +// import ( +// "context" +// "net/http" +// ) + +// func AddHttpRouterTags(r *http.Request) context.Context { +// ctx := context.Background() +// ctx = context.WithValue(ctx, "route", r.URL.Path) +// return ctx +// } diff --git a/go/go-sql.go b/go/go-sql.go index 28329d20..f2abb7ef 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -1,26 +1,34 @@ -package sqlcommenterGo +package sqlcommenter import ( "context" "database/sql" "encoding/json" "fmt" + "net/http" "net/url" "strings" + "github.com/fatih/structs" + _ "github.com/go-sql-driver/mysql" ) type DB struct { *sql.DB - commenterOptions map[string]bool + CommenterOptions CommenterOptions +} + +type CommenterOptions struct { + DBDriver bool + Route bool } -var goSQLCommenterTags = map[string]string{"dbDriver": "go/sql"} +var goSQLCommenterTags = map[string]string{"DBDriver": "go/sql"} -func Open(driverName, dataSourceName string, commenterOptions map[string]bool) (*DB, error) { +func Open(driverName string, dataSourceName string, commenterOptions CommenterOptions) (*DB, error) { db, err := sql.Open(driverName, dataSourceName) - return &DB{DB: db, commenterOptions: commenterOptions}, err + return &DB{DB: db, CommenterOptions: commenterOptions}, err } func (db *DB) QueryRow(query string, args ...interface{}) any { @@ -37,8 +45,10 @@ func (db *DB) withComment(ctx context.Context, query string) string { var finalCommentsStr string = "" query = strings.TrimSpace(query) - for key, element := range db.commenterOptions { - if element { // Checks if option is set as true + commenterOptions := structs.Map(db.CommenterOptions) + + for key, element := range commenterOptions { + if element.(bool) { // Checks if option is set as true if _, ok := goSQLCommenterTags[key]; ok { // Check if static value is assigned and if true append finalCommentsMap[key] = goSQLCommenterTags[key] } else if ctx.Value(key) != nil { // Append if key is avaliable in context @@ -74,3 +84,9 @@ func encodeValue(v string) string { func encodeKey(k string) string { return url.QueryEscape(string(k)) } + +func AddHttpRouterTags(r *http.Request) context.Context { + ctx := context.Background() + ctx = context.WithValue(ctx, "Route", r.URL.Path) + return ctx +} From 0cc3b085b59309bd08e3499f38dd45fa3abecc6e Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 23 Sep 2022 13:26:20 +0530 Subject: [PATCH 03/27] Go-SQL Implementation done --- go/go-http-router.go | 12 ----- go/go-sql.go | 125 +++++++++++++++++++++++++++++-------------- go/go.mod | 4 +- go/go.sum | 2 - 4 files changed, 87 insertions(+), 56 deletions(-) delete mode 100644 go/go-http-router.go diff --git a/go/go-http-router.go b/go/go-http-router.go deleted file mode 100644 index 47e087c4..00000000 --- a/go/go-http-router.go +++ /dev/null @@ -1,12 +0,0 @@ -package sqlcommenter - -// import ( -// "context" -// "net/http" -// ) - -// func AddHttpRouterTags(r *http.Request) context.Context { -// ctx := context.Background() -// ctx = context.WithValue(ctx, "route", r.URL.Path) -// return ctx -// } diff --git a/go/go-sql.go b/go/go-sql.go index f2abb7ef..46387739 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -3,15 +3,12 @@ package sqlcommenter import ( "context" "database/sql" - "encoding/json" "fmt" "net/http" "net/url" + "reflect" + "runtime" "strings" - - "github.com/fatih/structs" - - _ "github.com/go-sql-driver/mysql" ) type DB struct { @@ -20,18 +17,25 @@ type DB struct { } type CommenterOptions struct { - DBDriver bool - Route bool + DBDriver bool + Route bool + Framework bool + Controller bool + Action bool } -var goSQLCommenterTags = map[string]string{"DBDriver": "go/sql"} - func Open(driverName string, dataSourceName string, commenterOptions CommenterOptions) (*DB, error) { db, err := sql.Open(driverName, dataSourceName) return &DB{DB: db, CommenterOptions: commenterOptions}, err } -func (db *DB) QueryRow(query string, args ...interface{}) any { +// ***** Query Functions ***** + +func (db *DB) Query(query string, args ...any) (*sql.Rows, error) { + return db.DB.Query(db.withComment(context.Background(), query), args...) +} + +func (db *DB) QueryRow(query string, args ...interface{}) *sql.Row { return db.DB.QueryRow(db.withComment(context.Background(), query), args...) } @@ -39,54 +43,97 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*sql return db.DB.QueryContext(ctx, db.withComment(ctx, query), args...) } +func (db *DB) Exec(query string, args ...any) (sql.Result, error) { + return db.DB.Exec(db.withComment(context.Background(), query), args...) +} + +func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error) { + return db.DB.ExecContext(ctx, db.withComment(ctx, query), args...) +} + +func (db *DB) Prepare(query string) (*sql.Stmt, error) { + return db.DB.Prepare(db.withComment(context.Background(), query)) +} + +func (db *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) { + return db.DB.PrepareContext(ctx, db.withComment(ctx, query)) +} + +// ***** Query Functions ***** + +// ***** Framework Functions ***** + +func AddHttpRouterTags(r *http.Request, n any, p any) context.Context { // any type is set because we need to refrain from importing http-router package + ctx := context.Background() + ctx = context.WithValue(ctx, "route", r.URL.Path) + ctx = context.WithValue(ctx, "action", getFunctionName(n)) + ctx = context.WithValue(ctx, "framework", "github.com/julienschmidt/httprouter") + return ctx +} + +// ***** Framework Functions ***** + +// ***** Commenter Functions ***** + func (db *DB) withComment(ctx context.Context, query string) string { var finalCommentsMap = map[string]string{} var finalCommentsStr string = "" query = strings.TrimSpace(query) - commenterOptions := structs.Map(db.CommenterOptions) + // Sorted alphabetically + if db.CommenterOptions.Action && (ctx.Value("action") != nil) { + finalCommentsMap["action"] = ctx.Value("action").(string) + } - for key, element := range commenterOptions { - if element.(bool) { // Checks if option is set as true - if _, ok := goSQLCommenterTags[key]; ok { // Check if static value is assigned and if true append - finalCommentsMap[key] = goSQLCommenterTags[key] - } else if ctx.Value(key) != nil { // Append if key is avaliable in context - finalCommentsMap[key] = ctx.Value(key).(string) - } - } + if db.CommenterOptions.DBDriver { + finalCommentsMap["driver"] = "go/sql" + } + if db.CommenterOptions.Framework && (ctx.Value("framework") != nil) { + finalCommentsMap["framework"] = ctx.Value("framework").(string) } + + if db.CommenterOptions.Route && (ctx.Value("route") != nil) { + finalCommentsMap["route"] = ctx.Value("route").(string) + } + if len(finalCommentsMap) > 0 { // Converts comments map to string and appends it to query - jsonStr, err := json.Marshal(finalCommentsMap) - if err != nil { - fmt.Printf("Error: %s", err.Error()) - } else { - finalCommentsStr = strings.Replace(string(jsonStr), "{", "/*", 1) - finalCommentsStr = strings.Replace(string(finalCommentsStr), "}", "*/", 1) - } + finalCommentsStr = fmt.Sprintf("/*%s*/", convertMapToComment(finalCommentsMap)) + fmt.Println(finalCommentsStr) } - if strings.Contains(query, ";") { - query = strings.Replace(string(query), ";", "", 1) - return fmt.Sprintf("%s%s;", query, finalCommentsStr) + if query[len(query)-1:] == ";" { + return fmt.Sprintf("%s%s;", strings.TrimSuffix(query, ";"), finalCommentsStr) } return fmt.Sprintf("%s%s", query, finalCommentsStr) } -// TODO: -func encodeValue(v string) string { - urlEscape := strings.ReplaceAll(url.PathEscape(string(v)), "+", "%20") - return fmt.Sprintf("'%s'", urlEscape) -} +// ***** Commenter Functions ***** + +// ***** Util Functions ***** -func encodeKey(k string) string { +func encodeURL(k string) string { return url.QueryEscape(string(k)) } -func AddHttpRouterTags(r *http.Request) context.Context { - ctx := context.Background() - ctx = context.WithValue(ctx, "Route", r.URL.Path) - return ctx +func getFunctionName(i interface{}) string { + return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() +} + +func convertMapToComment(tags map[string]string) string { + var sb strings.Builder + i, sz := 0, len(tags) + for key, val := range tags { + if i == sz-1 { + sb.WriteString(fmt.Sprintf("%s=%v", encodeURL(key), encodeURL(val))) + } else { + sb.WriteString(fmt.Sprintf("%s=%v,", encodeURL(key), encodeURL(val))) + } + i++ + } + return sb.String() } + +// ***** Util Functions ***** diff --git a/go/go.mod b/go/go.mod index 54833be9..63d83829 100644 --- a/go/go.mod +++ b/go/go.mod @@ -1,5 +1,3 @@ -module google.com/sqlcommenterGo +module google.com/sqlcommenter go 1.19 - -require github.com/go-sql-driver/mysql v1.6.0 diff --git a/go/go.sum b/go/go.sum index 20c16d6f..e69de29b 100644 --- a/go/go.sum +++ b/go/go.sum @@ -1,2 +0,0 @@ -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= From 373142dc20bb57de18768f9964cb11f8e20d1a11 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 23 Sep 2022 15:55:53 +0530 Subject: [PATCH 04/27] Added README.md & copyright header --- go/README.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ go/go-sql.go | 16 +++++++++++ 2 files changed, 92 insertions(+) create mode 100644 go/README.md diff --git a/go/README.md b/go/README.md new file mode 100644 index 00000000..afa82289 --- /dev/null +++ b/go/README.md @@ -0,0 +1,76 @@ +# Sqlcommenter [In development] + +Sqlcommenter is a plugin/middleware/wrapper to augment SQL statements from go libraries with comments that can be used later to correlate user code with SQL statements. + +## Installation + +### Install from source + +* Clone the source +* In terminal go inside the client folder location where we need to import google-sqlcommenter package and enter the below commands + +```shell +go mod edit -replace google.com/sqlcommenterGo=path/to/google/sqlcommenter/go + +go mod tiny +``` +### Install from github [To be added] + +## Usages + +### go-sql-driver +Use the sqlcommenter's db driver to perform query + +```go +db, err := sqlcommenterGo.Open("", "", sqlcommenter.CommenterOptions{:}) + +``` + +#### Configuration + +Tags to be appended can be configured by creating a variable of type sqlcommenter.CommenterOptions + +```go +type CommenterOptions struct { + DBDriver bool + Traceparent bool + Route bool //applicable for web frameworks + Framework bool //applicable for web frameworks + Controller bool //applicable for web frameworks + Action bool //applicable for web frameworks +} +``` +### go-http-router +Populate the request context with sqlcommenter.AddHttpRouterTags(r) function in a custom middleware. + +#### Note +* It needs to be used with drivers such as go-sql-orm +* ORM related tags are added to the driver only when the tags are enabled in the commenter's driver's config and also the request context should passed to the querying functions + +#### Example +```go +// middleware is used to intercept incoming HTTP calls and populate request context with commenter tags. +func middleware(n httprouter.Handle) httprouter.Handle { + return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + ctx := sqlcommenter.AddHttpRouterTags(r) + log.Printf("HTTP request sent to %s from %s", r.URL.Path, r.RemoteAddr) + + // call registered handler + n(w, r.WithContext(ctx), ps) + } +} +``` + + + +## Options + +With Go SqlCommenter, we have configuration to choose which tags to be appended to the comment. + +| Options | Included by default? | go-sql-orm | http-router | Notes | +| --------------- | :------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---: | +| `DBDriver` | | [ go-sql-driver](https://pkg.go.dev/database/sql/driver) | | +| `Action` | | | [http-router handle](https://pkg.go.dev/github.com/julienschmidt/httprouter#Handle) | | +| `Route` | | | [http-router routing path](https://pkg.go.dev/github.com/julienschmidt/httprouter#Router) | | +| `Framework` | | | [github.com/julienschmidt/httprouter](https://pkg.go.dev/github.com/julienschmidt/httprouter) | | +| `Opentelemetry` | | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | | diff --git a/go/go-sql.go b/go/go-sql.go index 46387739..ad2f2451 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -1,3 +1,19 @@ +/* +Copyright 2022 Google LLC + +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 sqlcommenter import ( From d61b98545e24993010374e81731ff648449d7b71 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 23 Sep 2022 17:44:51 +0530 Subject: [PATCH 05/27] Updated net/http --- go/README.md | 25 ++++++++++--------------- go/go-sql.go | 6 +++--- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/go/README.md b/go/README.md index afa82289..93f3aca2 100644 --- a/go/README.md +++ b/go/README.md @@ -40,7 +40,7 @@ type CommenterOptions struct { Action bool //applicable for web frameworks } ``` -### go-http-router +### net/http Populate the request context with sqlcommenter.AddHttpRouterTags(r) function in a custom middleware. #### Note @@ -50,27 +50,22 @@ Populate the request context with sqlcommenter.AddHttpRouterTags(r) function in #### Example ```go // middleware is used to intercept incoming HTTP calls and populate request context with commenter tags. -func middleware(n httprouter.Handle) httprouter.Handle { - return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - ctx := sqlcommenter.AddHttpRouterTags(r) - log.Printf("HTTP request sent to %s from %s", r.URL.Path, r.RemoteAddr) - - // call registered handler - n(w, r.WithContext(ctx), ps) - } +func middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := sqlcommenter.AddHttpRouterTags(r, next) + next.ServeHTTP(w, r.WithContext(ctx)) + }) } ``` - - ## Options With Go SqlCommenter, we have configuration to choose which tags to be appended to the comment. -| Options | Included by default? | go-sql-orm | http-router | Notes | +| Options | Included by default? | go-sql-orm | net/http | Notes | | --------------- | :------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---: | | `DBDriver` | | [ go-sql-driver](https://pkg.go.dev/database/sql/driver) | | -| `Action` | | | [http-router handle](https://pkg.go.dev/github.com/julienschmidt/httprouter#Handle) | | -| `Route` | | | [http-router routing path](https://pkg.go.dev/github.com/julienschmidt/httprouter#Router) | | -| `Framework` | | | [github.com/julienschmidt/httprouter](https://pkg.go.dev/github.com/julienschmidt/httprouter) | | +| `Action` | | | [net/http handle](https://pkg.go.dev/net/http#Handle) | | +| `Route` | | | [net/http routing path](https://pkg.go.dev/github.com/gorilla/mux#Route.URLPath) | | +| `Framework` | | | [net/http](https://pkg.go.dev/net/http) | | | `Opentelemetry` | | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | | diff --git a/go/go-sql.go b/go/go-sql.go index ad2f2451..52fb955d 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -79,11 +79,11 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, erro // ***** Framework Functions ***** -func AddHttpRouterTags(r *http.Request, n any, p any) context.Context { // any type is set because we need to refrain from importing http-router package +func AddHttpRouterTags(r *http.Request, next any) context.Context { // any type is set because we need to refrain from importing http-router package ctx := context.Background() ctx = context.WithValue(ctx, "route", r.URL.Path) - ctx = context.WithValue(ctx, "action", getFunctionName(n)) - ctx = context.WithValue(ctx, "framework", "github.com/julienschmidt/httprouter") + ctx = context.WithValue(ctx, "action", getFunctionName(next)) + ctx = context.WithValue(ctx, "framework", "net/http") return ctx } From f89b7b3a6fa40d7be63b435907698463179782a8 Mon Sep 17 00:00:00 2001 From: Subhrajyoti Date: Fri, 23 Sep 2022 18:31:22 +0530 Subject: [PATCH 06/27] Update README.md --- go/README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/go/README.md b/go/README.md index 93f3aca2..10edb40e 100644 --- a/go/README.md +++ b/go/README.md @@ -1,6 +1,6 @@ # Sqlcommenter [In development] -Sqlcommenter is a plugin/middleware/wrapper to augment SQL statements from go libraries with comments that can be used later to correlate user code with SQL statements. +SQLcommenter is a plugin/middleware/wrapper to augment application related information/tags with SQL Statements that can be used later to correlate user code with SQL statements. ## Installation @@ -10,7 +10,7 @@ Sqlcommenter is a plugin/middleware/wrapper to augment SQL statements from go li * In terminal go inside the client folder location where we need to import google-sqlcommenter package and enter the below commands ```shell -go mod edit -replace google.com/sqlcommenterGo=path/to/google/sqlcommenter/go +go mod edit -replace google.com/sqlcommenter=path/to/google/sqlcommenter/go go mod tiny ``` @@ -19,32 +19,33 @@ go mod tiny ## Usages ### go-sql-driver -Use the sqlcommenter's db driver to perform query +Please use the sqlcommenter's default database driver to execute statements. \ +Due to inherent nature of Go, the safer way to pass information from framework to database driver is via `context`. So, it is recommended to use the context based methods of `DB` interface like `QueryContext`, `ExecContext` and `PrepareContext`. ```go -db, err := sqlcommenterGo.Open("", "", sqlcommenter.CommenterOptions{:}) - +db, err := sqlcommenter.Open("", "", sqlcommenter.CommenterOptions{:}) ``` #### Configuration -Tags to be appended can be configured by creating a variable of type sqlcommenter.CommenterOptions +Users are given control over what tags they want to append by using `sqlcommenter.CommenterOptions` struct. ```go type CommenterOptions struct { - DBDriver bool - Traceparent bool - Route bool //applicable for web frameworks - Framework bool //applicable for web frameworks - Controller bool //applicable for web frameworks - Action bool //applicable for web frameworks + DBDriver bool + Traceparent bool // OpenTelemetry trace information + Route bool // applicable for web frameworks + Framework bool // applicable for web frameworks + Controller bool // applicable for web frameworks + Action bool // applicable for web frameworks } ``` + ### net/http Populate the request context with sqlcommenter.AddHttpRouterTags(r) function in a custom middleware. #### Note -* It needs to be used with drivers such as go-sql-orm +* We only support the `database/sql` driver and have provided an implementation for that. * ORM related tags are added to the driver only when the tags are enabled in the commenter's driver's config and also the request context should passed to the querying functions #### Example From dc6c518e57101b3116da5e294fdede257f7aaf1d Mon Sep 17 00:00:00 2001 From: Subhrajyoti Date: Fri, 23 Sep 2022 19:01:24 +0530 Subject: [PATCH 07/27] Update go-sql.go --- go/go-sql.go | 98 +++++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/go/go-sql.go b/go/go-sql.go index 52fb955d..105c0f02 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -1,18 +1,16 @@ -/* -Copyright 2022 Google LLC - -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. -*/ +// Copyright 2022 Google LLC +// +// 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 sqlcommenter @@ -27,22 +25,33 @@ import ( "strings" ) +const ( + + + + string = "route" + controller string = "controller" + action string = "action" + framework string = "framework" + driver string = "driver" +) + type DB struct { *sql.DB - CommenterOptions CommenterOptions + options CommenterOptions } type CommenterOptions struct { - DBDriver bool - Route bool - Framework bool - Controller bool - Action bool + EnableDBDriver bool + EnableRoute bool + EnableFramework bool + EnableController bool + EnableAction bool } -func Open(driverName string, dataSourceName string, commenterOptions CommenterOptions) (*DB, error) { +func Open(driverName string, dataSourceName string, options CommenterOptions) (*DB, error) { db, err := sql.Open(driverName, dataSourceName) - return &DB{DB: db, CommenterOptions: commenterOptions}, err + return &DB{DB: db, options: options}, err } // ***** Query Functions ***** @@ -81,9 +90,9 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, erro func AddHttpRouterTags(r *http.Request, next any) context.Context { // any type is set because we need to refrain from importing http-router package ctx := context.Background() - ctx = context.WithValue(ctx, "route", r.URL.Path) - ctx = context.WithValue(ctx, "action", getFunctionName(next)) - ctx = context.WithValue(ctx, "framework", "net/http") + ctx = context.WithValue(ctx, route, r.URL.Path) + ctx = context.WithValue(ctx, action, getFunctionName(next)) + ctx = context.WithValue(ctx, framework, "net/http") return ctx } @@ -92,38 +101,39 @@ func AddHttpRouterTags(r *http.Request, next any) context.Context { // any type // ***** Commenter Functions ***** func (db *DB) withComment(ctx context.Context, query string) string { - - var finalCommentsMap = map[string]string{} - var finalCommentsStr string = "" + var commentsMap = map[string]string{} query = strings.TrimSpace(query) // Sorted alphabetically - if db.CommenterOptions.Action && (ctx.Value("action") != nil) { - finalCommentsMap["action"] = ctx.Value("action").(string) + if db.options.EnableAction && (ctx.Value(action) != nil) { + commentsMap[action] = ctx.Value(action).(string) } - - if db.CommenterOptions.DBDriver { - finalCommentsMap["driver"] = "go/sql" + + // `driver` information should not be coming from framework. + // So, explicitly adding that here. + if db.options.EnableDBDriver { + commentsMap[driver] = "database/sql" } - if db.CommenterOptions.Framework && (ctx.Value("framework") != nil) { - finalCommentsMap["framework"] = ctx.Value("framework").(string) + if db.options.EnableFramework && (ctx.Value(framework) != nil) { + commentsMap[framework] = ctx.Value(framework).(string) } - if db.CommenterOptions.Route && (ctx.Value("route") != nil) { - finalCommentsMap["route"] = ctx.Value("route").(string) + if db.options.EnableRoute && (ctx.Value(route) != nil) { + commentsMap[route] = ctx.Value(route).(string) } - if len(finalCommentsMap) > 0 { // Converts comments map to string and appends it to query - finalCommentsStr = fmt.Sprintf("/*%s*/", convertMapToComment(finalCommentsMap)) - fmt.Println(finalCommentsStr) + var commentsString string = "" + if len(commentsMap) > 0 { // Converts comments map to string and appends it to query + commentsString = fmt.Sprintf("/*%s*/", convertMapToComment(commentsMap)) } + // A semicolon at the end of the SQL statement means the query ends there. + // We need to insert the comment before that to be considered as part of the SQL statemtent. if query[len(query)-1:] == ";" { - return fmt.Sprintf("%s%s;", strings.TrimSuffix(query, ";"), finalCommentsStr) + return fmt.Sprintf("%s%s;", strings.TrimSuffix(query, ";"), commentsString) } - return fmt.Sprintf("%s%s", query, finalCommentsStr) - + return fmt.Sprintf("%s%s", query, commentsString) } // ***** Commenter Functions ***** From f7eb636e2f859159eb2aea119a0c87d5036c747e Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Mon, 26 Sep 2022 13:13:50 +0530 Subject: [PATCH 08/27] Added support for otel traceparet --- go/go-sql.go | 57 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/go/go-sql.go b/go/go-sql.go index 105c0f02..8c5ce7d6 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -3,9 +3,9 @@ // 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. @@ -23,30 +23,32 @@ import ( "reflect" "runtime" "strings" + + "go.opentelemetry.io/otel/propagation" ) const ( - - - - string = "route" - controller string = "controller" - action string = "action" - framework string = "framework" - driver string = "driver" + route string = "route" + controller string = "controller" + action string = "action" + framework string = "framework" + driver string = "driver" + traceparent string = "traceparent" ) type DB struct { *sql.DB - options CommenterOptions + options CommenterOptions + otelTraceparent string } type CommenterOptions struct { - EnableDBDriver bool - EnableRoute bool - EnableFramework bool - EnableController bool - EnableAction bool + EnableDBDriver bool + EnableRoute bool + EnableFramework bool + EnableController bool + EnableAction bool + EnableTraceparent bool } func Open(driverName string, dataSourceName string, options CommenterOptions) (*DB, error) { @@ -54,6 +56,19 @@ func Open(driverName string, dataSourceName string, options CommenterOptions) (* return &DB{DB: db, options: options}, err } +func (db *DB) AddorUpdateCurrentSpan(ctx context.Context) { + + // Serialize the context into carrier + propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + carrier := propagation.MapCarrier{} + propgator.Inject(ctx, carrier) + + // Update traceparent + if val, ok := carrier["traceparent"]; ok { + db.otelTraceparent = val + } +} + // ***** Query Functions ***** func (db *DB) Query(query string, args ...any) (*sql.Rows, error) { @@ -108,7 +123,7 @@ func (db *DB) withComment(ctx context.Context, query string) string { if db.options.EnableAction && (ctx.Value(action) != nil) { commentsMap[action] = ctx.Value(action).(string) } - + // `driver` information should not be coming from framework. // So, explicitly adding that here. if db.options.EnableDBDriver { @@ -123,13 +138,17 @@ func (db *DB) withComment(ctx context.Context, query string) string { commentsMap[route] = ctx.Value(route).(string) } + if db.options.EnableTraceparent && (ctx.Value(traceparent) != "") { + commentsMap[traceparent] = db.otelTraceparent + } + var commentsString string = "" if len(commentsMap) > 0 { // Converts comments map to string and appends it to query commentsString = fmt.Sprintf("/*%s*/", convertMapToComment(commentsMap)) } - // A semicolon at the end of the SQL statement means the query ends there. - // We need to insert the comment before that to be considered as part of the SQL statemtent. + // A semicolon at the end of the SQL statement means the query ends there. + // We need to insert the comment before that to be considered as part of the SQL statemtent. if query[len(query)-1:] == ";" { return fmt.Sprintf("%s%s;", strings.TrimSuffix(query, ";"), commentsString) } From 935870f3bc2a38718ee4af01040f141f0544671c Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Tue, 27 Sep 2022 14:16:54 +0530 Subject: [PATCH 09/27] PR changes for otel integration --- go/README.md | 12 ++++++------ go/go-sql.go | 33 ++++++++++++++++----------------- go/go.mod | 4 ++++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/go/README.md b/go/README.md index 10edb40e..2d49a9e5 100644 --- a/go/README.md +++ b/go/README.md @@ -32,12 +32,12 @@ Users are given control over what tags they want to append by using `sqlcommente ```go type CommenterOptions struct { - DBDriver bool - Traceparent bool // OpenTelemetry trace information - Route bool // applicable for web frameworks - Framework bool // applicable for web frameworks - Controller bool // applicable for web frameworks - Action bool // applicable for web frameworks + EnableDBDriver bool + EnableTraceparent bool // OpenTelemetry trace information + EnableRoute bool // applicable for web frameworks + EnableFramework bool // applicable for web frameworks + EnableController bool // applicable for web frameworks + EnableAction bool // applicable for web frameworks } ``` diff --git a/go/go-sql.go b/go/go-sql.go index 8c5ce7d6..71f13539 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -38,8 +38,7 @@ const ( type DB struct { *sql.DB - options CommenterOptions - otelTraceparent string + options CommenterOptions } type CommenterOptions struct { @@ -56,19 +55,6 @@ func Open(driverName string, dataSourceName string, options CommenterOptions) (* return &DB{DB: db, options: options}, err } -func (db *DB) AddorUpdateCurrentSpan(ctx context.Context) { - - // Serialize the context into carrier - propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) - carrier := propagation.MapCarrier{} - propgator.Inject(ctx, carrier) - - // Update traceparent - if val, ok := carrier["traceparent"]; ok { - db.otelTraceparent = val - } -} - // ***** Query Functions ***** func (db *DB) Query(query string, args ...any) (*sql.Rows, error) { @@ -108,6 +94,7 @@ func AddHttpRouterTags(r *http.Request, next any) context.Context { // any type ctx = context.WithValue(ctx, route, r.URL.Path) ctx = context.WithValue(ctx, action, getFunctionName(next)) ctx = context.WithValue(ctx, framework, "net/http") + fmt.Println(ctx.Value("route")) return ctx } @@ -138,8 +125,11 @@ func (db *DB) withComment(ctx context.Context, query string) string { commentsMap[route] = ctx.Value(route).(string) } - if db.options.EnableTraceparent && (ctx.Value(traceparent) != "") { - commentsMap[traceparent] = db.otelTraceparent + if db.options.EnableTraceparent { + carrier := extractTraceparent(ctx) + if val, ok := carrier["traceparent"]; ok { + commentsMap[traceparent] = val + } } var commentsString string = "" @@ -181,4 +171,13 @@ func convertMapToComment(tags map[string]string) string { return sb.String() } +func extractTraceparent(ctx context.Context) propagation.MapCarrier { + + // Serialize the context into carrier + propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + carrier := propagation.MapCarrier{} + propgator.Inject(ctx, carrier) + return carrier +} + // ***** Util Functions ***** diff --git a/go/go.mod b/go/go.mod index 63d83829..1cef2574 100644 --- a/go/go.mod +++ b/go/go.mod @@ -1,3 +1,7 @@ module google.com/sqlcommenter go 1.19 + +require go.opentelemetry.io/otel v1.10.0 + +require go.opentelemetry.io/otel/trace v1.10.0 // indirect From 5ac9c4240359185d3e34ecf2aa4739516f396377 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Tue, 27 Sep 2022 17:46:02 +0530 Subject: [PATCH 10/27] Added Unittests --- go/go-sql_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++ go/go.mod | 16 +++++++++-- go/go.sum | 20 +++++++++++++ 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 go/go-sql_test.go diff --git a/go/go-sql_test.go b/go/go-sql_test.go new file mode 100644 index 00000000..68ec639b --- /dev/null +++ b/go/go-sql_test.go @@ -0,0 +1,73 @@ +package sqlcommenter + +import ( + "context" + "net/http" + "regexp" + "testing" + + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +func TestDisabled(t *testing.T) { + + db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{}) + + got := db.withComment(context.Background(), "Select 1") + want := "Select 1" + + if got != want { + t.Errorf("got %q, wanted %q", got, want) + } +} + +func TestHTTP_Net(t *testing.T) { + + db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{EnableDBDriver: true, EnableRoute: true, EnableFramework: true}) + + r, _ := http.NewRequest("GET", "hello/1", nil) + ctx := AddHttpRouterTags(r, context.Background()) + + got := db.withComment(ctx, "Select 1") + wantOrder1 := "Select 1/*driver=database%2Fsql,framework=net%2Fhttp,route=hello%2F1*/" + wantOrder2 := "Select 1/*framework=net%2Fhttp,route=hello%2F1,driver=database%2Fsql*/" + //wantOrder3 := "Select 1/*driver=database%2Fsql,framework=net%2Fhttp,route=hello%2F1*/" + + if (got != wantOrder1) && (got != wantOrder2) { + t.Errorf("got %q, wanted1 %q or wanted2 %q", got, wantOrder1, wantOrder2) + } +} + +func TestQueryWithSemicolon(t *testing.T) { + + db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{EnableDBDriver: true}) + + got := db.withComment(context.Background(), "Select 1;") + want := "Select 1/*driver=database%2Fsql*/;" + + if got != want { + t.Errorf("got %q, wanted %q", got, want) + } +} + +func TestOtelIntegration(t *testing.T) { + + db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{EnableTraceparent: true}) + + exp, _ := stdouttrace.New(stdouttrace.WithPrettyPrint()) + bsp := sdktrace.NewSimpleSpanProcessor(exp) // You should use batch span processor in prod + tp := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithSpanProcessor(bsp), + ) + + ctx, _ := tp.Tracer("").Start(context.Background(), "parent-span-name") + + got := db.withComment(ctx, "Select 1;") + r, _ := regexp.Compile("Select 1/\\*traceparent=\\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\\d{1,2}\\*/;") + + if !r.MatchString(got) { + t.Errorf("got %q", got) + } +} diff --git a/go/go.mod b/go/go.mod index 1cef2574..ca2b01dc 100644 --- a/go/go.mod +++ b/go/go.mod @@ -2,6 +2,18 @@ module google.com/sqlcommenter go 1.19 -require go.opentelemetry.io/otel v1.10.0 +require ( + go.opentelemetry.io/otel v1.10.0 + go.opentelemetry.io/otel/sdk v1.10.0 +) -require go.opentelemetry.io/otel/trace v1.10.0 // indirect +require ( + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 // indirect +) + +require ( + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 + go.opentelemetry.io/otel/trace v1.10.0 // indirect +) diff --git a/go/go.sum b/go/go.sum index e69de29b..786ed491 100644 --- a/go/go.sum +++ b/go/go.sum @@ -0,0 +1,20 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 h1:c9UtMu/qnbLlVwTwt+ABrURrioEruapIslTDYZHJe2w= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0/go.mod h1:h3Lrh9t3Dnqp3NPwAZx7i37UFX7xrfnO1D+fuClREOA= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= From 5ff4995a081a7c90ee78928b1ca8d786dc7c6c14 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Tue, 27 Sep 2022 17:52:29 +0530 Subject: [PATCH 11/27] PR changes --- go/go-sql.go | 1 - 1 file changed, 1 deletion(-) diff --git a/go/go-sql.go b/go/go-sql.go index 71f13539..00078a86 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -94,7 +94,6 @@ func AddHttpRouterTags(r *http.Request, next any) context.Context { // any type ctx = context.WithValue(ctx, route, r.URL.Path) ctx = context.WithValue(ctx, action, getFunctionName(next)) ctx = context.WithValue(ctx, framework, "net/http") - fmt.Println(ctx.Value("route")) return ctx } From 1ef9f62ae715a3c5f05b208f68db665a74488d1d Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 15:59:58 +0530 Subject: [PATCH 12/27] PR changes --- go/README.md | 4 ++-- go/go-sql.go | 16 ++++++++++++---- go/go-sql_test.go | 44 +++++++++++++++++++++++++++++--------------- go/go.sum | 2 ++ 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/go/README.md b/go/README.md index 2d49a9e5..d19afe0c 100644 --- a/go/README.md +++ b/go/README.md @@ -33,12 +33,12 @@ Users are given control over what tags they want to append by using `sqlcommente ```go type CommenterOptions struct { EnableDBDriver bool - EnableTraceparent bool // OpenTelemetry trace information + EnableTraceparent bool // OpenTelemetry trace information EnableRoute bool // applicable for web frameworks EnableFramework bool // applicable for web frameworks EnableController bool // applicable for web frameworks EnableAction bool // applicable for web frameworks -} + } ``` ### net/http diff --git a/go/go-sql.go b/go/go-sql.go index 00078a86..4f8bdfca 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -22,6 +22,7 @@ import ( "net/url" "reflect" "runtime" + "sort" "strings" "go.opentelemetry.io/otel/propagation" @@ -159,11 +160,19 @@ func getFunctionName(i interface{}) string { func convertMapToComment(tags map[string]string) string { var sb strings.Builder i, sz := 0, len(tags) - for key, val := range tags { + + //sort by keys + sortedKeys := make([]string, 0, len(tags)) + for k := range tags { + sortedKeys = append(sortedKeys, k) + } + sort.Strings(sortedKeys) + + for _, key := range sortedKeys { if i == sz-1 { - sb.WriteString(fmt.Sprintf("%s=%v", encodeURL(key), encodeURL(val))) + sb.WriteString(fmt.Sprintf("%s=%v", encodeURL(key), encodeURL(tags[key]))) } else { - sb.WriteString(fmt.Sprintf("%s=%v,", encodeURL(key), encodeURL(val))) + sb.WriteString(fmt.Sprintf("%s=%v,", encodeURL(key), encodeURL(tags[key]))) } i++ } @@ -171,7 +180,6 @@ func convertMapToComment(tags map[string]string) string { } func extractTraceparent(ctx context.Context) propagation.MapCarrier { - // Serialize the context into carrier propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) carrier := propagation.MapCarrier{} diff --git a/go/go-sql_test.go b/go/go-sql_test.go index 68ec639b..9ef4914b 100644 --- a/go/go-sql_test.go +++ b/go/go-sql_test.go @@ -6,43 +6,53 @@ import ( "regexp" "testing" + "github.com/DATA-DOG/go-sqlmock" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) -func TestDisabled(t *testing.T) { +var engine, connectionParams = "mysql", "root:root@/gotest" - db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{}) +func TestDisabled(t *testing.T) { + mockDB, _, err := sqlmock.New() - got := db.withComment(context.Background(), "Select 1") - want := "Select 1" + db := DB{DB: mockDB, options: CommenterOptions{}} + if err != nil { + t.Fatalf("MockSQL failed with unexpected error: %s", err) + } - if got != want { - t.Errorf("got %q, wanted %q", got, want) + query := "SELECT 2" + if got, want := db.withComment(context.Background(), query), query; got != want { + t.Errorf("db.withComment(context.Background(), %q) = %q, want = %q", query, got, want) } } func TestHTTP_Net(t *testing.T) { + mockDB, _, err := sqlmock.New() - db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{EnableDBDriver: true, EnableRoute: true, EnableFramework: true}) + db := DB{DB: mockDB, options: CommenterOptions{EnableDBDriver: true, EnableRoute: true, EnableFramework: true}} + if err != nil { + t.Fatalf("MockSQL failed with unexpected error: %s", err) + } r, _ := http.NewRequest("GET", "hello/1", nil) ctx := AddHttpRouterTags(r, context.Background()) got := db.withComment(ctx, "Select 1") - wantOrder1 := "Select 1/*driver=database%2Fsql,framework=net%2Fhttp,route=hello%2F1*/" - wantOrder2 := "Select 1/*framework=net%2Fhttp,route=hello%2F1,driver=database%2Fsql*/" - //wantOrder3 := "Select 1/*driver=database%2Fsql,framework=net%2Fhttp,route=hello%2F1*/" + want := "Select 1/*driver=database%2Fsql,framework=net%2Fhttp,route=hello%2F1*/" - if (got != wantOrder1) && (got != wantOrder2) { - t.Errorf("got %q, wanted1 %q or wanted2 %q", got, wantOrder1, wantOrder2) + if got != want { + t.Errorf("got %q, wanted %q", got, want) } } func TestQueryWithSemicolon(t *testing.T) { + mockDB, _, err := sqlmock.New() - db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{EnableDBDriver: true}) - + db := DB{DB: mockDB, options: CommenterOptions{EnableDBDriver: true}} + if err != nil { + t.Fatalf("MockSQL failed with unexpected error: %s", err) + } got := db.withComment(context.Background(), "Select 1;") want := "Select 1/*driver=database%2Fsql*/;" @@ -52,8 +62,12 @@ func TestQueryWithSemicolon(t *testing.T) { } func TestOtelIntegration(t *testing.T) { + mockDB, _, err := sqlmock.New() - db, _ := Open("mysql", "root:root@/gotest", CommenterOptions{EnableTraceparent: true}) + db := DB{DB: mockDB, options: CommenterOptions{EnableTraceparent: true}} + if err != nil { + t.Fatalf("MockSQL failed with unexpected error: %s", err) + } exp, _ := stdouttrace.New(stdouttrace.WithPrettyPrint()) bsp := sdktrace.NewSimpleSpanProcessor(exp) // You should use batch span processor in prod diff --git a/go/go.sum b/go/go.sum index 786ed491..3127bc42 100644 --- a/go/go.sum +++ b/go/go.sum @@ -1,3 +1,5 @@ +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= From f79cf9444ad94f54f56b2ce411640072b9bddc1e Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 16:22:35 +0530 Subject: [PATCH 13/27] Added CI unittest pipeline --- .github/workflows/go-tests.yaml | 28 ++++++++++++++++++++++++++++ .github/workflows/unit-tests.yaml | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 .github/workflows/go-tests.yaml diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml new file mode 100644 index 00000000..47b959eb --- /dev/null +++ b/.github/workflows/go-tests.yaml @@ -0,0 +1,28 @@ +name: Python Packages Test + +on: + push: +# branches: +# - master +# paths: +# - go/** + pull_request: + paths: + - go/** + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -v ./... \ No newline at end of file diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml index 684ee05d..bc56b27b 100644 --- a/.github/workflows/unit-tests.yaml +++ b/.github/workflows/unit-tests.yaml @@ -9,12 +9,14 @@ on: - php/sqlcommenter-php/samples/sqlcommenter-laravel/** - python/sqlcommenter-python/** - nodejs/** + - go/** pull_request: paths-ignore: - php/sqlcommenter-php/packages/sqlcommenter-laravel/** - php/sqlcommenter-php/samples/sqlcommenter-laravel/** - python/sqlcommenter-python/** - nodejs/** + - go/** jobs: unittests: From 3327a3bfe4aa3b620f5544e64c8cd8c9ca6dfd0b Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 16:24:42 +0530 Subject: [PATCH 14/27] Added CI unittest pipeline --- .github/workflows/go-tests.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml index 47b959eb..84d3f8e1 100644 --- a/.github/workflows/go-tests.yaml +++ b/.github/workflows/go-tests.yaml @@ -1,4 +1,4 @@ -name: Python Packages Test +name: Go Packages Test on: push: @@ -23,6 +23,8 @@ jobs: - name: Build run: go build -v ./... + working-directory: ./go - name: Test - run: go test -v ./... \ No newline at end of file + run: go test -v ./... + working-directory: ./go From 9749f6b5e58f39ab5f2f3693fa4d68e6d2cb53f1 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 16:26:17 +0530 Subject: [PATCH 15/27] Added sqlmock module --- go/go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go/go.mod b/go/go.mod index ca2b01dc..409b243c 100644 --- a/go/go.mod +++ b/go/go.mod @@ -14,6 +14,7 @@ require ( ) require ( + github.com/DATA-DOG/go-sqlmock v1.5.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 go.opentelemetry.io/otel/trace v1.10.0 // indirect ) From 4b5cebc19f5d64afb4d5c1244a8b4ccc63f542e5 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 16:35:56 +0530 Subject: [PATCH 16/27] Added CI unittest pipeline --- .github/workflows/go-tests.yaml | 6 ++++++ go/go-sql.go | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml index 84d3f8e1..dccd0338 100644 --- a/.github/workflows/go-tests.yaml +++ b/.github/workflows/go-tests.yaml @@ -25,6 +25,12 @@ jobs: run: go build -v ./... working-directory: ./go + # Verify go fmt standards are used + - name: Format + run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi + - name: Test run: go test -v ./... working-directory: ./go + + diff --git a/go/go-sql.go b/go/go-sql.go index 4f8bdfca..3bec1c0b 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -25,8 +25,7 @@ import ( "sort" "strings" - "go.opentelemetry.io/otel/propagation" -) + "go.opentelemetry.io/otel/propagation") const ( route string = "route" From c347efbb6de26f51e4e81f4c3cf84a9308c8ae10 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 16:39:30 +0530 Subject: [PATCH 17/27] Added gofmt tests --- .github/workflows/go-tests.yaml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml index dccd0338..250eb6cf 100644 --- a/.github/workflows/go-tests.yaml +++ b/.github/workflows/go-tests.yaml @@ -25,12 +25,21 @@ jobs: run: go build -v ./... working-directory: ./go - # Verify go fmt standards are used - - name: Format - run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi - - name: Test run: go test -v ./... working-directory: ./go + gofmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + + # Verify go fmt standards are used + - name: Format + run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi From f27540a8fecf7b76a82e4232be17e7c26810aab3 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 16:41:21 +0530 Subject: [PATCH 18/27] Added gofmt tests --- .github/workflows/go-tests.yaml | 2 +- go/go-sql.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml index 250eb6cf..b0ab72df 100644 --- a/.github/workflows/go-tests.yaml +++ b/.github/workflows/go-tests.yaml @@ -11,7 +11,7 @@ on: - go/** jobs: - build: + unittests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/go/go-sql.go b/go/go-sql.go index 3bec1c0b..4f8bdfca 100644 --- a/go/go-sql.go +++ b/go/go-sql.go @@ -25,7 +25,8 @@ import ( "sort" "strings" - "go.opentelemetry.io/otel/propagation") + "go.opentelemetry.io/otel/propagation" +) const ( route string = "route" From 50e7ffd57d797b7c589e45375c6764b2a0c4efdc Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 17:55:56 +0530 Subject: [PATCH 19/27] Rename Package --- go/{ => go-sql}/README.md | 0 go/{ => go-sql}/go-sql.go | 2 +- go/{ => go-sql}/go-sql_test.go | 2 +- go/{ => go-sql}/go.mod | 4 ++-- go/{ => go-sql}/go.sum | 2 ++ 5 files changed, 6 insertions(+), 4 deletions(-) rename go/{ => go-sql}/README.md (100%) rename go/{ => go-sql}/go-sql.go (99%) rename go/{ => go-sql}/go-sql_test.go (99%) rename go/{ => go-sql}/go.mod (78%) rename go/{ => go-sql}/go.sum (90%) diff --git a/go/README.md b/go/go-sql/README.md similarity index 100% rename from go/README.md rename to go/go-sql/README.md diff --git a/go/go-sql.go b/go/go-sql/go-sql.go similarity index 99% rename from go/go-sql.go rename to go/go-sql/go-sql.go index 4f8bdfca..05ddf6ca 100644 --- a/go/go-sql.go +++ b/go/go-sql/go-sql.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package sqlcommenter +package gosql import ( "context" diff --git a/go/go-sql_test.go b/go/go-sql/go-sql_test.go similarity index 99% rename from go/go-sql_test.go rename to go/go-sql/go-sql_test.go index 9ef4914b..be03518a 100644 --- a/go/go-sql_test.go +++ b/go/go-sql/go-sql_test.go @@ -1,4 +1,4 @@ -package sqlcommenter +package gosql import ( "context" diff --git a/go/go.mod b/go/go-sql/go.mod similarity index 78% rename from go/go.mod rename to go/go-sql/go.mod index 409b243c..201245cb 100644 --- a/go/go.mod +++ b/go/go-sql/go.mod @@ -1,4 +1,4 @@ -module google.com/sqlcommenter +module google.com/sqlcommenter/gosql go 1.19 @@ -10,7 +10,7 @@ require ( require ( github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 // indirect + golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 // indirect ) require ( diff --git a/go/go.sum b/go/go-sql/go.sum similarity index 90% rename from go/go.sum rename to go/go-sql/go.sum index 3127bc42..14fae557 100644 --- a/go/go.sum +++ b/go/go-sql/go.sum @@ -19,4 +19,6 @@ go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zA go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 h1:cy1ko5847T/lJ45eyg/7uLprIE/amW5IXxGtEnQdYMI= +golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= From 6ce058ab742050d46abb46f4d9e588963de7c212 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 17:58:00 +0530 Subject: [PATCH 20/27] updated github workflow --- .github/workflows/go-tests.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml index b0ab72df..c857981a 100644 --- a/.github/workflows/go-tests.yaml +++ b/.github/workflows/go-tests.yaml @@ -1,4 +1,4 @@ -name: Go Packages Test +name: go-sql Packages Test on: push: @@ -8,7 +8,7 @@ on: # - go/** pull_request: paths: - - go/** + - go/go-sql/** jobs: unittests: @@ -23,11 +23,11 @@ jobs: - name: Build run: go build -v ./... - working-directory: ./go + working-directory: ./go/go-sql - name: Test run: go test -v ./... - working-directory: ./go + working-directory: ./go/go-sql gofmt: runs-on: ubuntu-latest From 50aff881ea2618061f71456b8016c723ef199059 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Wed, 28 Sep 2022 18:00:16 +0530 Subject: [PATCH 21/27] updated github workflow --- .github/workflows/go-tests.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml index c857981a..f7d92a45 100644 --- a/.github/workflows/go-tests.yaml +++ b/.github/workflows/go-tests.yaml @@ -1,11 +1,11 @@ -name: go-sql Packages Test +name: go-sql package test on: push: -# branches: -# - master -# paths: -# - go/** + branches: + - master + paths: + - go/go-sql/** pull_request: paths: - go/go-sql/** From 266ff1e3cc95b9bd897475d73210cd35578a5e7d Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Thu, 29 Sep 2022 11:14:12 +0530 Subject: [PATCH 22/27] renamed github workflow --- .github/workflows/{go-tests.yaml => go-sql-tests.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{go-tests.yaml => go-sql-tests.yaml} (100%) diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-sql-tests.yaml similarity index 100% rename from .github/workflows/go-tests.yaml rename to .github/workflows/go-sql-tests.yaml From ec742863dcc569cb422dd5880e8b1c479008f147 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 30 Sep 2022 11:04:23 +0530 Subject: [PATCH 23/27] Code structure refactoring --- go/core/README.md | 28 +++++++++ go/core/core.go | 76 +++++++++++++++++++++++++ go/core/go.mod | 7 +++ go/core/go.sum | 11 ++++ go/go-sql/.vscode/launch.json | 15 +++++ go/go-sql/README.md | 44 +++++---------- go/go-sql/go-sql.go | 103 +++++----------------------------- go/go-sql/go-sql_test.go | 12 ++-- go/go-sql/go.mod | 8 ++- go/go-sql/go.sum | 2 - go/http-net/README.md | 71 +++++++++++++++++++++++ go/http-net/go.mod | 12 ++++ go/http-net/go.sum | 4 ++ go/http-net/http-net.go | 36 ++++++++++++ 14 files changed, 301 insertions(+), 128 deletions(-) create mode 100644 go/core/README.md create mode 100644 go/core/core.go create mode 100644 go/core/go.mod create mode 100644 go/core/go.sum create mode 100644 go/go-sql/.vscode/launch.json create mode 100644 go/http-net/README.md create mode 100644 go/http-net/go.mod create mode 100644 go/http-net/go.sum create mode 100644 go/http-net/http-net.go diff --git a/go/core/README.md b/go/core/README.md new file mode 100644 index 00000000..326bc3b7 --- /dev/null +++ b/go/core/README.md @@ -0,0 +1,28 @@ +# SQLCommenter Core [In development] + +SQLcommenter is a plugin/middleware/wrapper to augment application related information/tags with SQL Statements that can be used later to correlate user code with SQL statements. + +This package contains configuration options, framework interface and support functions for all the sqlcommenter go modules + +## Installation + +This is a support package and will be installed indirectly by other go sqlcommenter packages + +## Usages + +### Configuration + +Users are given control over what tags they want to append by using `core.CommenterOptions` struct. + +```go +type CommenterOptions struct { + EnableDBDriver bool + EnableTraceparent bool // OpenTelemetry trace information + EnableRoute bool // applicable for web frameworks + EnableFramework bool // applicable for web frameworks + EnableController bool // applicable for web frameworks + EnableAction bool // applicable for web frameworks + } +``` + + diff --git a/go/core/core.go b/go/core/core.go new file mode 100644 index 00000000..6ffaee2e --- /dev/null +++ b/go/core/core.go @@ -0,0 +1,76 @@ +package core + +import ( + "context" + "fmt" + "net/url" + "reflect" + "runtime" + "sort" + "strings" + + "go.opentelemetry.io/otel/propagation" +) + +const ( + Route string = "route" + Controller string = "controller" + Action string = "action" + Framework string = "framework" + Driver string = "driver" + Traceparent string = "traceparent" +) + +type CommenterOptions struct { + EnableDBDriver bool + EnableRoute bool + EnableFramework bool + EnableController bool + EnableAction bool + EnableTraceparent bool +} + +func encodeURL(k string) string { + return url.QueryEscape(string(k)) +} + +func GetFunctionName(i interface{}) string { + return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() +} + +func ConvertMapToComment(tags map[string]string) string { + var sb strings.Builder + i, sz := 0, len(tags) + + //sort by keys + sortedKeys := make([]string, 0, len(tags)) + for k := range tags { + sortedKeys = append(sortedKeys, k) + } + sort.Strings(sortedKeys) + + for _, key := range sortedKeys { + if i == sz-1 { + sb.WriteString(fmt.Sprintf("%s=%v", encodeURL(key), encodeURL(tags[key]))) + } else { + sb.WriteString(fmt.Sprintf("%s=%v,", encodeURL(key), encodeURL(tags[key]))) + } + i++ + } + return sb.String() +} + +func ExtractTraceparent(ctx context.Context) propagation.MapCarrier { + // Serialize the context into carrier + propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + carrier := propagation.MapCarrier{} + propgator.Inject(ctx, carrier) + return carrier +} + +type HttpRequestTagger interface { + Route() string + Action() string + Framework() string + GetContext() context.Context +} diff --git a/go/core/go.mod b/go/core/go.mod new file mode 100644 index 00000000..76cac496 --- /dev/null +++ b/go/core/go.mod @@ -0,0 +1,7 @@ +module google.com/sqlcommenter/core + +go 1.19 + +require go.opentelemetry.io/otel v1.10.0 + +require go.opentelemetry.io/otel/trace v1.10.0 // indirect diff --git a/go/core/go.sum b/go/core/go.sum new file mode 100644 index 00000000..c9ab1f94 --- /dev/null +++ b/go/core/go.sum @@ -0,0 +1,11 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/go/go-sql/.vscode/launch.json b/go/go-sql/.vscode/launch.json new file mode 100644 index 00000000..2a1e8a72 --- /dev/null +++ b/go/go-sql/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "/Users/thiyagunataraj/Documents/Sqlcommenter-new/sqlcommenter/go/" + } + ] +} \ No newline at end of file diff --git a/go/go-sql/README.md b/go/go-sql/README.md index d19afe0c..c6b7b16f 100644 --- a/go/go-sql/README.md +++ b/go/go-sql/README.md @@ -1,4 +1,4 @@ -# Sqlcommenter [In development] +# go-sql-driver [In development] SQLcommenter is a plugin/middleware/wrapper to augment application related information/tags with SQL Statements that can be used later to correlate user code with SQL statements. @@ -7,28 +7,29 @@ SQLcommenter is a plugin/middleware/wrapper to augment application related infor ### Install from source * Clone the source -* In terminal go inside the client folder location where we need to import google-sqlcommenter package and enter the below commands +* In terminal go inside the client folder location where we need to import sqlcommenter go-sql module and enter the below commands ```shell -go mod edit -replace google.com/sqlcommenter=path/to/google/sqlcommenter/go +go mod edit -replace google.com/sqlcommenter=path/to/google/sqlcommenter/go-sql go mod tiny + +go get google.com/sqlcommenter/gosql ``` ### Install from github [To be added] -## Usages +## Usage -### go-sql-driver -Please use the sqlcommenter's default database driver to execute statements. \ +Please use the sqlcommenter's default go-sql database driver to execute statements. \ Due to inherent nature of Go, the safer way to pass information from framework to database driver is via `context`. So, it is recommended to use the context based methods of `DB` interface like `QueryContext`, `ExecContext` and `PrepareContext`. ```go db, err := sqlcommenter.Open("", "", sqlcommenter.CommenterOptions{:}) ``` -#### Configuration +### Configuration -Users are given control over what tags they want to append by using `sqlcommenter.CommenterOptions` struct. +Users are given control over what tags they want to append by using `core.CommenterOptions` struct. ```go type CommenterOptions struct { @@ -41,32 +42,15 @@ type CommenterOptions struct { } ``` -### net/http -Populate the request context with sqlcommenter.AddHttpRouterTags(r) function in a custom middleware. -#### Note -* We only support the `database/sql` driver and have provided an implementation for that. -* ORM related tags are added to the driver only when the tags are enabled in the commenter's driver's config and also the request context should passed to the querying functions +### Framework Supported +* [http/net](.../../../http-net/README.md) -#### Example -```go -// middleware is used to intercept incoming HTTP calls and populate request context with commenter tags. -func middleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := sqlcommenter.AddHttpRouterTags(r, next) - next.ServeHTTP(w, r.WithContext(ctx)) - }) -} -``` ## Options With Go SqlCommenter, we have configuration to choose which tags to be appended to the comment. -| Options | Included by default? | go-sql-orm | net/http | Notes | -| --------------- | :------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---: | -| `DBDriver` | | [ go-sql-driver](https://pkg.go.dev/database/sql/driver) | | -| `Action` | | | [net/http handle](https://pkg.go.dev/net/http#Handle) | | -| `Route` | | | [net/http routing path](https://pkg.go.dev/github.com/gorilla/mux#Route.URLPath) | | -| `Framework` | | | [net/http](https://pkg.go.dev/net/http) | | -| `Opentelemetry` | | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | | +| Options | Included by default? | go-sql-driver | +| ---------- | -------------------- | -------------------------------------------------------- | +| `DBDriver` | | [ go-sql-driver](https://pkg.go.dev/database/sql/driver) | \ No newline at end of file diff --git a/go/go-sql/go-sql.go b/go/go-sql/go-sql.go index 05ddf6ca..10aeb266 100644 --- a/go/go-sql/go-sql.go +++ b/go/go-sql/go-sql.go @@ -18,40 +18,17 @@ import ( "context" "database/sql" "fmt" - "net/http" - "net/url" - "reflect" - "runtime" - "sort" "strings" - "go.opentelemetry.io/otel/propagation" -) - -const ( - route string = "route" - controller string = "controller" - action string = "action" - framework string = "framework" - driver string = "driver" - traceparent string = "traceparent" + "google.com/sqlcommenter/core" ) type DB struct { *sql.DB - options CommenterOptions -} - -type CommenterOptions struct { - EnableDBDriver bool - EnableRoute bool - EnableFramework bool - EnableController bool - EnableAction bool - EnableTraceparent bool + options core.CommenterOptions } -func Open(driverName string, dataSourceName string, options CommenterOptions) (*DB, error) { +func Open(driverName string, dataSourceName string, options core.CommenterOptions) (*DB, error) { db, err := sql.Open(driverName, dataSourceName) return &DB{DB: db, options: options}, err } @@ -88,18 +65,6 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, erro // ***** Query Functions ***** -// ***** Framework Functions ***** - -func AddHttpRouterTags(r *http.Request, next any) context.Context { // any type is set because we need to refrain from importing http-router package - ctx := context.Background() - ctx = context.WithValue(ctx, route, r.URL.Path) - ctx = context.WithValue(ctx, action, getFunctionName(next)) - ctx = context.WithValue(ctx, framework, "net/http") - return ctx -} - -// ***** Framework Functions ***** - // ***** Commenter Functions ***** func (db *DB) withComment(ctx context.Context, query string) string { @@ -107,34 +72,34 @@ func (db *DB) withComment(ctx context.Context, query string) string { query = strings.TrimSpace(query) // Sorted alphabetically - if db.options.EnableAction && (ctx.Value(action) != nil) { - commentsMap[action] = ctx.Value(action).(string) + if db.options.EnableAction && (ctx.Value(core.Action) != nil) { + commentsMap[core.Action] = ctx.Value(core.Action).(string) } // `driver` information should not be coming from framework. // So, explicitly adding that here. if db.options.EnableDBDriver { - commentsMap[driver] = "database/sql" + commentsMap[core.Driver] = "database/sql" } - if db.options.EnableFramework && (ctx.Value(framework) != nil) { - commentsMap[framework] = ctx.Value(framework).(string) + if db.options.EnableFramework && (ctx.Value(core.Framework) != nil) { + commentsMap[core.Framework] = ctx.Value(core.Framework).(string) } - if db.options.EnableRoute && (ctx.Value(route) != nil) { - commentsMap[route] = ctx.Value(route).(string) + if db.options.EnableRoute && (ctx.Value(core.Route) != nil) { + commentsMap[core.Route] = ctx.Value(core.Route).(string) } if db.options.EnableTraceparent { - carrier := extractTraceparent(ctx) + carrier := core.ExtractTraceparent(ctx) if val, ok := carrier["traceparent"]; ok { - commentsMap[traceparent] = val + commentsMap[core.Traceparent] = val } } var commentsString string = "" if len(commentsMap) > 0 { // Converts comments map to string and appends it to query - commentsString = fmt.Sprintf("/*%s*/", convertMapToComment(commentsMap)) + commentsString = fmt.Sprintf("/*%s*/", core.ConvertMapToComment(commentsMap)) } // A semicolon at the end of the SQL statement means the query ends there. @@ -146,45 +111,3 @@ func (db *DB) withComment(ctx context.Context, query string) string { } // ***** Commenter Functions ***** - -// ***** Util Functions ***** - -func encodeURL(k string) string { - return url.QueryEscape(string(k)) -} - -func getFunctionName(i interface{}) string { - return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() -} - -func convertMapToComment(tags map[string]string) string { - var sb strings.Builder - i, sz := 0, len(tags) - - //sort by keys - sortedKeys := make([]string, 0, len(tags)) - for k := range tags { - sortedKeys = append(sortedKeys, k) - } - sort.Strings(sortedKeys) - - for _, key := range sortedKeys { - if i == sz-1 { - sb.WriteString(fmt.Sprintf("%s=%v", encodeURL(key), encodeURL(tags[key]))) - } else { - sb.WriteString(fmt.Sprintf("%s=%v,", encodeURL(key), encodeURL(tags[key]))) - } - i++ - } - return sb.String() -} - -func extractTraceparent(ctx context.Context) propagation.MapCarrier { - // Serialize the context into carrier - propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) - carrier := propagation.MapCarrier{} - propgator.Inject(ctx, carrier) - return carrier -} - -// ***** Util Functions ***** diff --git a/go/go-sql/go-sql_test.go b/go/go-sql/go-sql_test.go index be03518a..2a6dfd8b 100644 --- a/go/go-sql/go-sql_test.go +++ b/go/go-sql/go-sql_test.go @@ -9,6 +9,8 @@ import ( "github.com/DATA-DOG/go-sqlmock" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" sdktrace "go.opentelemetry.io/otel/sdk/trace" + "google.com/sqlcommenter/core" + httpnet "google.com/sqlcommenter/http-net" ) var engine, connectionParams = "mysql", "root:root@/gotest" @@ -16,7 +18,7 @@ var engine, connectionParams = "mysql", "root:root@/gotest" func TestDisabled(t *testing.T) { mockDB, _, err := sqlmock.New() - db := DB{DB: mockDB, options: CommenterOptions{}} + db := DB{DB: mockDB, options: core.CommenterOptions{}} if err != nil { t.Fatalf("MockSQL failed with unexpected error: %s", err) } @@ -30,13 +32,13 @@ func TestDisabled(t *testing.T) { func TestHTTP_Net(t *testing.T) { mockDB, _, err := sqlmock.New() - db := DB{DB: mockDB, options: CommenterOptions{EnableDBDriver: true, EnableRoute: true, EnableFramework: true}} + db := DB{DB: mockDB, options: core.CommenterOptions{EnableDBDriver: true, EnableRoute: true, EnableFramework: true}} if err != nil { t.Fatalf("MockSQL failed with unexpected error: %s", err) } r, _ := http.NewRequest("GET", "hello/1", nil) - ctx := AddHttpRouterTags(r, context.Background()) + ctx := httpnet.NewHttpNet(r, context.Background()).AddTags(r.Context()) got := db.withComment(ctx, "Select 1") want := "Select 1/*driver=database%2Fsql,framework=net%2Fhttp,route=hello%2F1*/" @@ -49,7 +51,7 @@ func TestHTTP_Net(t *testing.T) { func TestQueryWithSemicolon(t *testing.T) { mockDB, _, err := sqlmock.New() - db := DB{DB: mockDB, options: CommenterOptions{EnableDBDriver: true}} + db := DB{DB: mockDB, options: core.CommenterOptions{EnableDBDriver: true}} if err != nil { t.Fatalf("MockSQL failed with unexpected error: %s", err) } @@ -64,7 +66,7 @@ func TestQueryWithSemicolon(t *testing.T) { func TestOtelIntegration(t *testing.T) { mockDB, _, err := sqlmock.New() - db := DB{DB: mockDB, options: CommenterOptions{EnableTraceparent: true}} + db := DB{DB: mockDB, options: core.CommenterOptions{EnableTraceparent: true}} if err != nil { t.Fatalf("MockSQL failed with unexpected error: %s", err) } diff --git a/go/go-sql/go.mod b/go/go-sql/go.mod index 201245cb..0159eefa 100644 --- a/go/go-sql/go.mod +++ b/go/go-sql/go.mod @@ -3,13 +3,14 @@ module google.com/sqlcommenter/gosql go 1.19 require ( - go.opentelemetry.io/otel v1.10.0 go.opentelemetry.io/otel/sdk v1.10.0 + google.com/sqlcommenter/core v0.0.0-00010101000000-000000000000 ) require ( github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + go.opentelemetry.io/otel v1.10.0 // indirect golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 // indirect ) @@ -17,4 +18,9 @@ require ( github.com/DATA-DOG/go-sqlmock v1.5.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 go.opentelemetry.io/otel/trace v1.10.0 // indirect + google.com/sqlcommenter/http-net v0.0.0-00010101000000-000000000000 ) + +replace google.com/sqlcommenter/core => ../core/. + +replace google.com/sqlcommenter/http-net => ../http-net/. diff --git a/go/go-sql/go.sum b/go/go-sql/go.sum index 14fae557..6909e458 100644 --- a/go/go-sql/go.sum +++ b/go/go-sql/go.sum @@ -17,8 +17,6 @@ go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpT go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 h1:cy1ko5847T/lJ45eyg/7uLprIE/amW5IXxGtEnQdYMI= golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/go/http-net/README.md b/go/http-net/README.md new file mode 100644 index 00000000..8622ca8b --- /dev/null +++ b/go/http-net/README.md @@ -0,0 +1,71 @@ +# http-net [In development] + +SQLcommenter is a plugin/middleware/wrapper to augment application related information/tags with SQL Statements that can be used later to correlate user code with SQL statements. + +## Installation + +### Install from source + +* Clone the source +* In terminal go inside the client folder location where we need to import sqlcommenter http/net module and enter the below commands + +```shell +go mod edit -replace google.com/sqlcommenter=path/to/google/sqlcommenter/http-net + +go mod tiny + +go get google.com/sqlcommenter/http-net +``` +### Install from github [To be added] + +## Usage + +Please use the sqlcommenter's default go-sql database driver to execute statements. \ +Due to inherent nature of Go, the safer way to pass information from framework to database driver is via `context`. So, it is recommended to use the context based methods of `DB` interface like `QueryContext`, `ExecContext` and `PrepareContext`. + +```go +db, err := sqlcommenter.Open("", "", sqlcommenter.CommenterOptions{:}) +``` + +### Configuration + +Users are given control over what tags they want to append by using `core.CommenterOptions` struct. + +```go +type CommenterOptions struct { + EnableDBDriver bool + EnableTraceparent bool // OpenTelemetry trace information + EnableRoute bool // applicable for web frameworks + EnableFramework bool // applicable for web frameworks + EnableController bool // applicable for web frameworks + EnableAction bool // applicable for web frameworks + } +``` + + +#### Note +* We only support the `database/sql` driver and have provided an implementation for that. +* ORM related tags are added to the driver only when the tags are enabled in the commenter's driver's config and also the request context should passed to the querying functions +* The middleware implementing this sqlcommenter http-net module should be added at the last + +#### Example +```go +// middleware is used to intercept incoming HTTP calls and populate request context with commenter tags. +func middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := httpnet.NewHttpNet(r, next).AddTags(r.Context()) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} +``` + +## Options + +With Go SqlCommenter, we have configuration to choose which tags to be appended to the comment. + +| Options | Included by default? | net/http | +| --------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Action` | | [net/http handle](https://pkg.go.dev/net/http#Handle) | +| `Route` | | [net/http routing path](https://pkg.go.dev/github.com/gorilla/mux#Route.URLPath) | +| `Framework` | | [net/http](https://pkg.go.dev/net/http) | +| `Opentelemetry` | | [W3C TraceContext.Traceparent](https://www.w3.org/TR/trace-context/#traceparent-field), [W3C TraceContext.Tracestate](https://www.w3.org/TR/trace-context/#tracestate-field) | diff --git a/go/http-net/go.mod b/go/http-net/go.mod new file mode 100644 index 00000000..73ee52cc --- /dev/null +++ b/go/http-net/go.mod @@ -0,0 +1,12 @@ +module google.com/sqlcommenter/http-net + +replace google.com/sqlcommenter/core => ../core/. + +go 1.19 + +require google.com/sqlcommenter/core v0.0.0-00010101000000-000000000000 + +require ( + go.opentelemetry.io/otel v1.10.0 // indirect + go.opentelemetry.io/otel/trace v1.10.0 // indirect +) diff --git a/go/http-net/go.sum b/go/http-net/go.sum new file mode 100644 index 00000000..03c59d2f --- /dev/null +++ b/go/http-net/go.sum @@ -0,0 +1,4 @@ +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= diff --git a/go/http-net/http-net.go b/go/http-net/http-net.go new file mode 100644 index 00000000..ba186435 --- /dev/null +++ b/go/http-net/http-net.go @@ -0,0 +1,36 @@ +package httpnet + +import ( + "context" + "net/http" + + "google.com/sqlcommenter/core" +) + +type HttpNet struct { + r *http.Request + next any +} + +func NewHttpNet(r *http.Request, next any) *HttpNet { + return &HttpNet{r, next} +} + +func (h *HttpNet) Route() string { + return h.r.URL.Path +} + +func (h *HttpNet) Action() string { + return core.GetFunctionName(h.next) +} + +func (h *HttpNet) Framework() string { + return "net/http" +} + +func (h *HttpNet) AddTags(ctx context.Context) context.Context { + ctx = context.WithValue(ctx, core.Route, h.Route()) + ctx = context.WithValue(ctx, core.Action, h.Action()) + ctx = context.WithValue(ctx, core.Framework, h.Framework()) + return ctx +} From 2968a7346e3408837a4f75b4368af5802201ee50 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 30 Sep 2022 13:27:41 +0530 Subject: [PATCH 24/27] PR changes --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cc3016a8..d66c742a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ php/sqlcommenter-php/packages/sqlcommenter-laravel/vendor/* -.idea/** \ No newline at end of file +.idea/** +**/.vscode/** From cdb2c15a2133026d60a87006ae84528c293fb7f2 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 30 Sep 2022 13:29:05 +0530 Subject: [PATCH 25/27] PR changes --- go/core/core.go | 2 +- go/go-sql/.vscode/launch.json | 15 --------------- go/go-sql/README.md | 4 ++-- go/http-net/README.md | 2 +- 4 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 go/go-sql/.vscode/launch.json diff --git a/go/core/core.go b/go/core/core.go index 6ffaee2e..ff1bea39 100644 --- a/go/core/core.go +++ b/go/core/core.go @@ -68,7 +68,7 @@ func ExtractTraceparent(ctx context.Context) propagation.MapCarrier { return carrier } -type HttpRequestTagger interface { +type RequestTagger interface { Route() string Action() string Framework() string diff --git a/go/go-sql/.vscode/launch.json b/go/go-sql/.vscode/launch.json deleted file mode 100644 index 2a1e8a72..00000000 --- a/go/go-sql/.vscode/launch.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Package", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "/Users/thiyagunataraj/Documents/Sqlcommenter-new/sqlcommenter/go/" - } - ] -} \ No newline at end of file diff --git a/go/go-sql/README.md b/go/go-sql/README.md index c85777f2..f8aeb1e2 100644 --- a/go/go-sql/README.md +++ b/go/go-sql/README.md @@ -20,11 +20,11 @@ go get google.com/sqlcommenter/gosql ## Usage -Please use the sqlcommenter's default go-sql database driver to execute statements. \ +Please use the sqlcommenter's default go-sql database driver to execute statements. Due to inherent nature of Go, the safer way to pass information from framework to database driver is via `context`. So, it is recommended to use the context based methods of `DB` interface like `QueryContext`, `ExecContext` and `PrepareContext`. ```go -db, err := sqlcommenter.Open("", "", sqlcommenter.CommenterOptions{:}) +db, err := gosql.Open("", "", sqlcommenter.CommenterOptions{:}) ``` ### Configuration diff --git a/go/http-net/README.md b/go/http-net/README.md index 8622ca8b..6c148954 100644 --- a/go/http-net/README.md +++ b/go/http-net/README.md @@ -24,7 +24,7 @@ Please use the sqlcommenter's default go-sql database driver to execute statemen Due to inherent nature of Go, the safer way to pass information from framework to database driver is via `context`. So, it is recommended to use the context based methods of `DB` interface like `QueryContext`, `ExecContext` and `PrepareContext`. ```go -db, err := sqlcommenter.Open("", "", sqlcommenter.CommenterOptions{:}) +db, err := gosql.Open("", "", sqlcommenter.CommenterOptions{:}) ``` ### Configuration From fd5c5080f3f53120a3ad47a09aa2283c7aeb78e2 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 30 Sep 2022 13:53:23 +0530 Subject: [PATCH 26/27] PR changes --- go/core/core.go | 14 ++++++++ go/go-sql/go-sql_test.go | 14 ++++++++ go/http-net/http-net.go | 14 ++++++++ go/samples/http-sql-sample/go.mod | 28 +++++++++++++++ go/samples/http-sql-sample/go.sum | 23 ++++++++++++ go/samples/http-sql-sample/main.go | 56 ++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+) create mode 100644 go/samples/http-sql-sample/go.mod create mode 100644 go/samples/http-sql-sample/go.sum create mode 100644 go/samples/http-sql-sample/main.go diff --git a/go/core/core.go b/go/core/core.go index ff1bea39..8d3a5a83 100644 --- a/go/core/core.go +++ b/go/core/core.go @@ -1,3 +1,17 @@ +// Copyright 2022 Google LLC +// +// 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 core import ( diff --git a/go/go-sql/go-sql_test.go b/go/go-sql/go-sql_test.go index 2a6dfd8b..3cc6fbda 100644 --- a/go/go-sql/go-sql_test.go +++ b/go/go-sql/go-sql_test.go @@ -1,3 +1,17 @@ +// Copyright 2022 Google LLC +// +// 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 gosql import ( diff --git a/go/http-net/http-net.go b/go/http-net/http-net.go index ba186435..b7aafa2b 100644 --- a/go/http-net/http-net.go +++ b/go/http-net/http-net.go @@ -1,3 +1,17 @@ +// Copyright 2022 Google LLC +// +// 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 httpnet import ( diff --git a/go/samples/http-sql-sample/go.mod b/go/samples/http-sql-sample/go.mod new file mode 100644 index 00000000..5ba03f5a --- /dev/null +++ b/go/samples/http-sql-sample/go.mod @@ -0,0 +1,28 @@ +module http-sql-sample + +go 1.19 + +require ( + github.com/go-sql-driver/mysql v1.6.0 + go.opentelemetry.io/otel v1.10.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 + go.opentelemetry.io/otel/sdk v1.10.0 + google.com/sqlcommenter/http-net v0.0.0-00010101000000-000000000000 +) + +require ( + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + go.opentelemetry.io/otel/trace v1.10.0 // indirect + golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 // indirect + google.com/sqlcommenter/core v0.0.0-00010101000000-000000000000 + google.com/sqlcommenter/go-sql v0.0.0-00010101000000-000000000000 +) + +// replace your local path if choosing local install + +//replace google.com/sqlcommenter/core => /Users/thiyagunataraj/Documents/Sqlcommenter-new/sqlcommenter/go/core + +//replace google.com/sqlcommenter/go-sql => /Users/thiyagunataraj/Documents/Sqlcommenter-new/sqlcommenter/go/go-sql + +//replace google.com/sqlcommenter/http-net => /Users/thiyagunataraj/Documents/Sqlcommenter-new/sqlcommenter/go/http-net diff --git a/go/samples/http-sql-sample/go.sum b/go/samples/http-sql-sample/go.sum new file mode 100644 index 00000000..7b4e18c9 --- /dev/null +++ b/go/samples/http-sql-sample/go.sum @@ -0,0 +1,23 @@ +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 h1:c9UtMu/qnbLlVwTwt+ABrURrioEruapIslTDYZHJe2w= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0/go.mod h1:h3Lrh9t3Dnqp3NPwAZx7i37UFX7xrfnO1D+fuClREOA= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= +golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 h1:cy1ko5847T/lJ45eyg/7uLprIE/amW5IXxGtEnQdYMI= +golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/go/samples/http-sql-sample/main.go b/go/samples/http-sql-sample/main.go new file mode 100644 index 00000000..317b5e05 --- /dev/null +++ b/go/samples/http-sql-sample/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "log" + "net/http" + + _ "github.com/go-sql-driver/mysql" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "google.com/sqlcommenter/core" + gosql "google.com/sqlcommenter/go-sql" + httpnet "google.com/sqlcommenter/http-net" +) + +func Index(w http.ResponseWriter, r *http.Request) { + + exp, _ := stdouttrace.New(stdouttrace.WithPrettyPrint()) + bsp := sdktrace.NewSimpleSpanProcessor(exp) // You should use batch span processor in prod + tp := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithSpanProcessor(bsp), + ) + + ctx, span := tp.Tracer("foo").Start(r.Context(), "parent-span-name") + defer span.End() + + db, err := gosql.Open("mysql", "root:root@/gotest", core.CommenterOptions{EnableDBDriver: true, EnableRoute: true, EnableAction: true, EnableFramework: true, EnableTraceparent: true}) + if err != nil { + fmt.Println(err) + } else { + db.ExecContext(ctx, "Select 11;") + db.Exec("Select 2;") + db.Prepare("Select 10") + db.PrepareContext(ctx, "Select 10") + } + fmt.Fprintf(w, "Hello World!") +} + +// middleware is used to intercept incoming HTTP calls and apply general functions upon them. +func middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := httpnet.NewHttpNet(r, next).AddTags(r.Context()) + log.Printf("HTTP request sent to %s from %v", r.URL.Path, next) + next.ServeHTTP(w, r.WithContext(ctx)) + + }) +} + +func main() { + mux := http.NewServeMux() + finalHandler := http.HandlerFunc(Index) + mux.Handle("/", middleware((finalHandler))) + + log.Fatal(http.ListenAndServe(":8080", mux)) +} From 72278f432ab9dfac7f9b89d1e9dadd586252b715 Mon Sep 17 00:00:00 2001 From: Thiyagu55 Date: Fri, 30 Sep 2022 14:10:16 +0530 Subject: [PATCH 27/27] PR changes --- go/core/core.go | 4 ++-- go/http-net/http-net.go | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go/core/core.go b/go/core/core.go index 8d3a5a83..08b3bb8e 100644 --- a/go/core/core.go +++ b/go/core/core.go @@ -76,9 +76,9 @@ func ConvertMapToComment(tags map[string]string) string { func ExtractTraceparent(ctx context.Context) propagation.MapCarrier { // Serialize the context into carrier - propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + textMapPropogator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) carrier := propagation.MapCarrier{} - propgator.Inject(ctx, carrier) + textMapPropogator.Inject(ctx, carrier) return carrier } diff --git a/go/http-net/http-net.go b/go/http-net/http-net.go index b7aafa2b..5dea2c38 100644 --- a/go/http-net/http-net.go +++ b/go/http-net/http-net.go @@ -21,28 +21,28 @@ import ( "google.com/sqlcommenter/core" ) -type HttpNet struct { +type HTTPRequestTagger struct { r *http.Request next any } -func NewHttpNet(r *http.Request, next any) *HttpNet { - return &HttpNet{r, next} +func NewHttpNet(r *http.Request, next any) *HTTPRequestTagger { + return &HTTPRequestTagger{r, next} } -func (h *HttpNet) Route() string { +func (h *HTTPRequestTagger) Route() string { return h.r.URL.Path } -func (h *HttpNet) Action() string { +func (h *HTTPRequestTagger) Action() string { return core.GetFunctionName(h.next) } -func (h *HttpNet) Framework() string { +func (h *HTTPRequestTagger) Framework() string { return "net/http" } -func (h *HttpNet) AddTags(ctx context.Context) context.Context { +func (h *HTTPRequestTagger) AddTags(ctx context.Context) context.Context { ctx = context.WithValue(ctx, core.Route, h.Route()) ctx = context.WithValue(ctx, core.Action, h.Action()) ctx = context.WithValue(ctx, core.Framework, h.Framework())