Hello Team, I am trying to instrument a sample go ...
# support
s
Hello Team, I am trying to instrument a sample go program and send it to Signoz as per https://signoz.io/docs/instrumentation/golang/. But the service does not show up on signoz dashboard. Can I get some help on figuring out the issue. Here is my code...
Copy code
package main

import (
	"context"
	"encoding/json"
	"io"
	"net/http"
	"os"
	"strconv"

	"<http://github.com/gin-gonic/gin|github.com/gin-gonic/gin>"
	_ "<http://github.com/go-sql-driver/mysql|github.com/go-sql-driver/mysql>"
	"<http://github.com/gorilla/mux|github.com/gorilla/mux>"
	"<http://github.com/jinzhu/gorm|github.com/jinzhu/gorm>"
	_ "<http://github.com/jinzhu/gorm/dialects/mysql|github.com/jinzhu/gorm/dialects/mysql>"
	"<http://github.com/rs/cors|github.com/rs/cors>"
	log "<http://github.com/sirupsen/logrus|github.com/sirupsen/logrus>"
	"<http://go.opentelemetry.io/otel|go.opentelemetry.io/otel>"
	"<http://go.opentelemetry.io/otel/attribute|go.opentelemetry.io/otel/attribute>"
	"<http://go.opentelemetry.io/otel/exporters/otlp/otlptrace|go.opentelemetry.io/otel/exporters/otlp/otlptrace>"
	"<http://go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc|go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc>"
	"<http://google.golang.org/grpc/credentials|google.golang.org/grpc/credentials>"

	"<http://go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin|go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin>"
	"<http://go.opentelemetry.io/otel/sdk/resource|go.opentelemetry.io/otel/sdk/resource>"
	sdktrace "<http://go.opentelemetry.io/otel/sdk/trace|go.opentelemetry.io/otel/sdk/trace>"
)

var db, _ = gorm.Open("mysql", "root:root@/todolist?charset=utf8&parseTime=True&loc=Local")

var (
	serviceName  = os.Getenv("SERVICE_NAME")
	collectorURL = os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
	insecure     = os.Getenv("INSECURE_MODE")
)

func initTracer() func(context.Context) error {

	secureOption := otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
	if len(insecure) > 0 {
		secureOption = otlptracegrpc.WithInsecure()
	}

	log.Printf("entering init trace", collectorURL)
	exporter, err := otlptrace.New(
		context.Background(),
		otlptracegrpc.NewClient(
			secureOption,
			otlptracegrpc.WithEndpoint(collectorURL),
		),
	)

	if err != nil {
		log.Fatal(err)
	}
	resources, err := resource.New(
		context.Background(),
		resource.WithAttributes(
			attribute.String("service.name", serviceName),
			attribute.String("library.language", "go"),
		),
	)
	if err != nil {
		log.Printf("Could not set resources: ", err)
	}
	otel.SetTracerProvider(
		sdktrace.NewTracerProvider(
			sdktrace.WithSampler(sdktrace.AlwaysSample()),
			sdktrace.WithBatcher(exporter),
			sdktrace.WithResource(resources),
		),
	)
	return exporter.Shutdown
}

type TodoItemModel struct {
	Id          int `gorm:"primary_key"`
	Description string
	Completed   bool
}

func CreateItem(w http.ResponseWriter, r *http.Request) {
	description := r.FormValue("description")
	log.WithFields(log.Fields{"description": description}).Info("Add new TodoItem. Saving to database.")
	todo := &TodoItemModel{Description: description, Completed: false}
	db.Create(&todo)
	result := db.Last(&todo)
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result.Value)

}

func UpdateItem(w http.ResponseWriter, r *http.Request) {
	// Get URL parameter from mux
	vars := mux.Vars(r)
	id, _ := strconv.Atoi(vars["id"])

	// Test if the TodoItem exist in DB
	err := GetItemByID(id)
	if err == false {
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, `{"updated": false, "error": "Record Not Found"}`)
	} else {
		completed, _ := strconv.ParseBool(r.FormValue("completed"))
		log.WithFields(log.Fields{"Id": id, "Completed": completed}).Info("Updating TodoItem")
		todo := &TodoItemModel{}
		db.First(&todo, id)
		todo.Completed = completed
		db.Save(&todo)
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, `{"updated": true}`)
	}
}

func DeleteItem(w http.ResponseWriter, r *http.Request) {
	// Get URL parameter from mux
	vars := mux.Vars(r)
	id, _ := strconv.Atoi(vars["id"])

	// Test if the TodoItem exist in DB
	err := GetItemByID(id)
	if err == false {
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, `{"deleted": false, "error": "Record Not Found"}`)
	} else {
		log.WithFields(log.Fields{"Id": id}).Info("Deleting TodoItem")
		todo := &TodoItemModel{}
		db.First(&todo, id)
		db.Delete(&todo)
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, `{"deleted": true}`)
	}
}

func GetItemByID(Id int) bool {
	todo := &TodoItemModel{}
	result := db.First(&todo, Id)
	if result.Error != nil {
		log.Warn("TodoItem not found in database")
		return false
	}
	return true
}

func GetCompletedItems(w http.ResponseWriter, r *http.Request) {
	<http://log.Info|log.Info>("Get completed TodoItems")
	completedTodoItems := GetTodoItems(true)
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(completedTodoItems)
}

func GetIncompleteItems(w http.ResponseWriter, r *http.Request) {
	<http://log.Info|log.Info>("Get Incomplete TodoItems")
	IncompleteTodoItems := GetTodoItems(false)
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(IncompleteTodoItems)
}

func GetTodoItems(completed bool) interface{} {
	var todos []TodoItemModel
	TodoItems := db.Where("completed = ?", completed).Find(&todos).Value
	return TodoItems
}

func Healthz(w http.ResponseWriter, r *http.Request) {
	<http://log.Info|log.Info>("API Health is OK")
	w.Header().Set("Content-Type", "application/json")
	io.WriteString(w, `{"alive": true}`)
}

func init() {
	log.SetFormatter(&log.TextFormatter{})
	log.SetReportCaller(true)
}

func main() {
	cleanup := initTracer()
	defer cleanup(context.Background())
	r := gin.Default()
	r.Use(otelgin.Middleware(serviceName))
	log.Println(serviceName, "serviceName")
	defer db.Close()
	db.Debug().DropTableIfExists(&TodoItemModel{})
	db.Debug().AutoMigrate(&TodoItemModel{})
	<http://log.Info|log.Info>("Starting Todolist API server")
	router := mux.NewRouter()
	router.HandleFunc("/healthz", Healthz).Methods("GET")
	router.HandleFunc("/todo-completed", GetCompletedItems).Methods("GET")
	router.HandleFunc("/todo-incomplete", GetIncompleteItems).Methods("GET")
	router.HandleFunc("/todo", CreateItem).Methods("POST")
	router.HandleFunc("/todo/{id}", UpdateItem).Methods("POST")
	router.HandleFunc("/todo/{id}", DeleteItem).Methods("DELETE")
	http.ListenAndServe(":8000", router)
	handler := cors.New(cors.Options{
		AllowedMethods: []string{"GET", "POST", "DELETE", "PATCH", "OPTIONS"},
	}).Handler(router)

	http.ListenAndServe(":8000", handler)
}
p
cc @Vishal Sharma @Srikanth Chekuri
a
@Sibaprasad Tripathy The problem lies in your main, there is no way for gorrila mux router to know if you have initialised open trace in gin
if you start using the 'r' variable you initialised in main using otel, only then you will see the otel magic happening
Copy code
r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
s
Thanks @Apoorva.