From ba7494a841fc555860fb319fc3fe30ca6b2607f7 Mon Sep 17 00:00:00 2001 From: sanojsubran Date: Tue, 25 Jun 2024 13:57:45 +0200 Subject: [PATCH 1/2] chore:added example for the sql instrumentation using sql.OpenDB API --- example/sql-opendb/README.md | 17 +++++++ example/sql-opendb/go.mod | 15 ++++++ example/sql-opendb/go.sum | 17 +++++++ example/sql-opendb/main.go | 96 ++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 example/sql-opendb/README.md create mode 100644 example/sql-opendb/go.mod create mode 100644 example/sql-opendb/go.sum create mode 100644 example/sql-opendb/main.go diff --git a/example/sql-opendb/README.md b/example/sql-opendb/README.md new file mode 100644 index 000000000..002b7bf75 --- /dev/null +++ b/example/sql-opendb/README.md @@ -0,0 +1,17 @@ +User Database Service +------------- +This application demonstrates the usage of `Instana Go Tracer SDK` for instrumenting database operations. In the provided example, one can understand how to use the Instana SDK to wrap the `sql.Connector` and use the `sql.OpenDB` API to make database calls. + +## Running the application +- An Instana Host agent must be running to collect the traces. +- Compile the example by issuing `go build -o server .` and run the application using `./server` + +## Querying the server +The available routes are, +- localhost:8080/adduser + +Sample query: curl -X GET http://localhost:8080/adduser + +## Output +After querying the above-mentioned route, you will be able to see the call traces in the Instana dashboard. + diff --git a/example/sql-opendb/go.mod b/example/sql-opendb/go.mod new file mode 100644 index 000000000..fa2a7c9b6 --- /dev/null +++ b/example/sql-opendb/go.mod @@ -0,0 +1,15 @@ +module sqlopendb + +go 1.22.4 + +require ( + github.com/instana/go-sensor v1.63.0 + github.com/mattn/go-sqlite3 v1.14.22 +) + +require ( + github.com/looplab/fsm v1.0.1 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect +) + +replace github.com/instana/go-sensor => ../../ diff --git a/example/sql-opendb/go.sum b/example/sql-opendb/go.sum new file mode 100644 index 000000000..a98942c33 --- /dev/null +++ b/example/sql-opendb/go.sum @@ -0,0 +1,17 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/looplab/fsm v1.0.1 h1:OEW0ORrIx095N/6lgoGkFkotqH6s7vaFPsgjLAaF5QU= +github.com/looplab/fsm v1.0.1/go.mod h1:PmD3fFvQEIsjMEfvZdrCDZ6y8VwKTwWNjlpEr6IKPO4= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/example/sql-opendb/main.go b/example/sql-opendb/main.go new file mode 100644 index 000000000..b2b2f6a50 --- /dev/null +++ b/example/sql-opendb/main.go @@ -0,0 +1,96 @@ +// (c) Copyright IBM Corp. 2024 + +package main + +import ( + "context" + "database/sql" + "database/sql/driver" + "log" + "net/http" + + instana "github.com/instana/go-sensor" + "github.com/mattn/go-sqlite3" +) + +func main() { + mux := http.NewServeMux() + + // Initialize Instana Sensor + collector := instana.InitCollector(&instana.Options{ + Service: "my-service", + }) + + // Instrument the HTTP handler using Instana + mux.HandleFunc("/adduser", instana.TracingHandlerFunc(collector, "/adduser", handlerHome(collector.LegacySensor()))) + + err := http.ListenAndServe(":8080", mux) + if err != nil { + log.Println("error with HTTP server:", err.Error()) + return + } +} + +func handlerHome(sensor *instana.Sensor) http.HandlerFunc { + + return func(w http.ResponseWriter, r *http.Request) { + dsn := "./users.db" + + connector := &CustomConnector{ + driver: &sqlite3.SQLiteDriver{}, + dsn: dsn, + } + + // Instrument the sql connector using Instana + wc := instana.WrapSQLConnector(sensor, "driver connection string", connector) + + // Use the wrapped connector to initialize the database client + db := sql.OpenDB(wc) + defer func(db *sql.DB) { + err := db.Close() + if err != nil { + log.Println("error closing db:", err.Error()) + } + }(db) + + // IMPORTANT: Since the HTTP handler is instrumented, it is essential to pass the request context for trace + // propagation. + ctx := r.Context() + + // Sample queries: Create a table if it doesn't already exist + createTableSQL := `CREATE TABLE IF NOT EXISTS users (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);` + _, err := db.ExecContext(ctx, createTableSQL) + if err != nil { + log.Fatal(err) + } + + // Sample queries: Insert an entry into the table + name := "John Doe" + age := 30 + insertUserSQL := `INSERT INTO users (name, age) VALUES (?, ?)` + _, err = db.ExecContext(ctx, insertUserSQL, name, age) + if err != nil { + log.Fatal(err) + } + + log.Println("Entry added to the database successfully!") + + w.Write([]byte("Entry added to the database successfully!")) + } + +} + +type CustomConnector struct { + driver *sqlite3.SQLiteDriver + dsn string +} + +// Connect establishes a new connection to the database +func (c *CustomConnector) Connect(ctx context.Context) (driver.Conn, error) { + return c.driver.Open(c.dsn) +} + +// Driver returns the underlying driver of the connector +func (c *CustomConnector) Driver() driver.Driver { + return c.driver +} From 8a6119eae491474f4e2d28702fb66455acf6809f Mon Sep 17 00:00:00 2001 From: sanojsubran Date: Tue, 25 Jun 2024 14:32:03 +0200 Subject: [PATCH 2/2] doc:updated README for the examples folder --- example/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/example/README.md b/example/README.md index 7a5e5e071..1c5ae983d 100644 --- a/example/README.md +++ b/example/README.md @@ -19,6 +19,7 @@ This folder contains examples of instrumenting the common use-cases with `github * [sql-mysql](./sql-mysql) - an example of instrumenting a SQL application using `go-sensor` SDK. * [sql-redis](./sql-redis) - an example of instrumenting a Redis application using `go-sensor` SDK. * [pgxv5](./pgxv5) - an example of instrumenting pgx v5 library using `go-sensor` SDK. +* [sql-opendb](./sql-opendb) - an example of instrumenting `sql.OpenDB` using `go-sensor` SDK. For more up-to-date instrumentation code examples please consult the respective package documentation page: