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/** 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..08b3bb8e --- /dev/null +++ b/go/core/core.go @@ -0,0 +1,90 @@ +// 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 ( + "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 + textMapPropogator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + carrier := propagation.MapCarrier{} + textMapPropogator.Inject(ctx, carrier) + return carrier +} + +type RequestTagger 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/README.md b/go/go-sql/README.md index d19afe0c..f8aeb1e2 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{:}) +db, err := gosql.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) | 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..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 ( @@ -9,6 +23,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 +32,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 +46,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 +65,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 +80,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..6c148954 --- /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 := gosql.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..5dea2c38 --- /dev/null +++ b/go/http-net/http-net.go @@ -0,0 +1,50 @@ +// 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 ( + "context" + "net/http" + + "google.com/sqlcommenter/core" +) + +type HTTPRequestTagger struct { + r *http.Request + next any +} + +func NewHttpNet(r *http.Request, next any) *HTTPRequestTagger { + return &HTTPRequestTagger{r, next} +} + +func (h *HTTPRequestTagger) Route() string { + return h.r.URL.Path +} + +func (h *HTTPRequestTagger) Action() string { + return core.GetFunctionName(h.next) +} + +func (h *HTTPRequestTagger) Framework() string { + return "net/http" +} + +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()) + return ctx +} 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)) +}