277 lines
7.9 KiB
Go
277 lines
7.9 KiB
Go
package logger
|
|
|
|
import (
|
|
"context"
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
|
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
|
|
api "go.opentelemetry.io/otel/metric"
|
|
metricsdk "go.opentelemetry.io/otel/sdk/metric"
|
|
"go.opentelemetry.io/otel/sdk/resource"
|
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
"log"
|
|
)
|
|
|
|
func InitTracer() func(ctx context.Context) error {
|
|
var (
|
|
secureOption otlptracegrpc.Option
|
|
collectorURL = cfgSignoz.Traces.GRPCEndPoint
|
|
serviceName = cfgSignoz.ServiceName
|
|
)
|
|
|
|
if !cfgSignoz.Traces.Insecure {
|
|
secureOption = otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
|
|
} else {
|
|
secureOption = otlptracegrpc.WithInsecure()
|
|
}
|
|
|
|
exporter, err := otlptrace.New(
|
|
context.Background(),
|
|
otlptracegrpc.NewClient(
|
|
secureOption,
|
|
otlptracegrpc.WithEndpoint(collectorURL),
|
|
),
|
|
)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
resources, err := resource.New(
|
|
context.Background(),
|
|
resource.WithAttributes(
|
|
attribute.String("service.name", serviceName),
|
|
attribute.String("library.language", "go"),
|
|
),
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
otel.SetTracerProvider(
|
|
sdktrace.NewTracerProvider(
|
|
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
|
sdktrace.WithBatcher(exporter),
|
|
sdktrace.WithResource(resources),
|
|
),
|
|
)
|
|
return exporter.Shutdown
|
|
}
|
|
|
|
func exceptionsCounter(meter api.Meter) {
|
|
counter, err := meter.Int64Counter("exceptions", api.WithUnit("1"),
|
|
api.WithDescription("Counts exceptions since start"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in creating exceptions counter: ", err)
|
|
}
|
|
|
|
for {
|
|
// Increment the counter by 1.
|
|
// The attributes describe the exception.
|
|
counter.Add(context.Background(), 1, api.WithAttributes(attribute.KeyValue{
|
|
Key: attribute.Key("exception_type"), Value: attribute.StringValue("NullPointerException"),
|
|
}))
|
|
time.Sleep(time.Duration(rand.Int63n(5)) * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
// Example use cases for async counter
|
|
// - count the number of page faults
|
|
// - CPU time, which could be reported for each thread, each process or the
|
|
// entire system. For example "the CPU time for process
|
|
// A running in user mode, measured in seconds".
|
|
//
|
|
// Basically, any value that is monotonically increasing and happens in the background.
|
|
// The increments should be non-negative.
|
|
func pageFaultsCounter(meter api.Meter) {
|
|
counter, err := meter.Int64ObservableCounter(
|
|
"page_faults",
|
|
api.WithUnit("1"),
|
|
api.WithDescription("Counts page faults since start"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in creating page faults counter: ", err)
|
|
}
|
|
|
|
_, err = meter.RegisterCallback(
|
|
func(_ context.Context, o api.Observer) error {
|
|
attrSet := attribute.NewSet(attribute.String("process", "boo"))
|
|
withAttrSet := api.WithAttributeSet(attrSet)
|
|
o.ObserveInt64(counter, rand.Int63n(100), withAttrSet)
|
|
return nil
|
|
},
|
|
counter,
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in registering callback: ", err)
|
|
}
|
|
}
|
|
|
|
// Example use cases for Histogram
|
|
// - the request duration
|
|
// - the size of the response payload
|
|
func requestDurationHistogram(meter api.Meter) {
|
|
histogram, err := meter.Int64Histogram(
|
|
"http_request_duration",
|
|
api.WithUnit("ms"),
|
|
api.WithDescription("The HTTP request duration in milliseconds"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in creating request duration histogram: ", err)
|
|
}
|
|
|
|
for {
|
|
histogram.Record(context.Background(), rand.Int63n(1000), api.WithAttributes(attribute.String("path", "/api/boo")))
|
|
time.Sleep(time.Duration(rand.Int63n(5)) * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
// Asynchronous Gauge is an Instrument
|
|
// which reports non-additive value(s)
|
|
// (e.g. the room temperature - it makes no sense to report the
|
|
// temperature value from multiple rooms and sum them up) when the
|
|
// instrument is being observed.
|
|
|
|
// Example use cases for Async Gauge
|
|
// - the current room temperature
|
|
// - the CPU fan speed
|
|
|
|
// Note: if the values are additive (e.g. the process heap size -
|
|
// it makes sense to report the heap size from multiple processes and sum them up,
|
|
// so we get the total heap usage),
|
|
// use Asynchronous Counter or Asynchronous UpDownCounter.
|
|
|
|
func roomTemperatureGauge(meter api.Meter) {
|
|
gauge, err := meter.Float64ObservableGauge(
|
|
"room_temperature",
|
|
api.WithUnit("1"),
|
|
api.WithDescription("The room temperature in celsius"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in creating room temperature gauge: ", err)
|
|
}
|
|
|
|
_, err = meter.RegisterCallback(
|
|
func(_ context.Context, o api.Observer) error {
|
|
attrSet := attribute.NewSet(attribute.String("process", "boo"))
|
|
withAttrSet := api.WithAttributeSet(attrSet)
|
|
o.ObserveFloat64(gauge, rand.Float64()*100, withAttrSet)
|
|
return nil
|
|
},
|
|
gauge,
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in registering callback: ", err)
|
|
}
|
|
}
|
|
|
|
// UpDownCounter is an Instrument which supports increments and decrements.
|
|
// if the value is monotonically increasing, use Counter instead.
|
|
// Example use cases for UpDownCounter
|
|
// - the number of active requests
|
|
// - the number of items in a queue
|
|
|
|
func itemsInQueueUpDownCounter(meter api.Meter) {
|
|
counter, err := meter.Int64UpDownCounter(
|
|
"items_in_queue",
|
|
api.WithUnit("1"),
|
|
api.WithDescription("The number of items in the queue"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in creating items in queue up down counter: ", err)
|
|
}
|
|
|
|
for {
|
|
counter.Add(context.Background(), rand.Int63n(100), api.WithAttributes(attribute.String("queue", "A")))
|
|
time.Sleep(time.Duration(rand.Int63n(5)) * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
// Asynchronous UpDownCounter is an asynchronous Instrument
|
|
// which reports additive value(s)
|
|
// (e.g. the process heap size - it makes sense to report the heap size
|
|
// from multiple processes and sum them up, so we get the total heap usage)
|
|
// when the instrument is being observed.
|
|
//
|
|
// Example use cases for Asynchronous UpDownCounter
|
|
// - the process heap size
|
|
// - the approximate number of items in a lock-free circular buffer
|
|
|
|
func processHeapSizeUpDownCounter(meter api.Meter) {
|
|
counter, err := meter.Float64ObservableUpDownCounter(
|
|
"process_heap_size",
|
|
api.WithUnit("1"),
|
|
api.WithDescription("The process heap size"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in creating process heap size up down counter: ", err)
|
|
}
|
|
|
|
_, err = meter.RegisterCallback(
|
|
func(_ context.Context, o api.Observer) error {
|
|
attrSet := attribute.NewSet(attribute.String("process", "boo"))
|
|
withAttrSet := api.WithAttributeSet(attrSet)
|
|
o.ObserveFloat64(counter, rand.Float64()*100, withAttrSet)
|
|
return nil
|
|
},
|
|
counter,
|
|
)
|
|
if err != nil {
|
|
log.Fatal("Error in registering callback: ", err)
|
|
}
|
|
}
|
|
|
|
func InitMeter() (*metricsdk.MeterProvider, api.Meter) {
|
|
var (
|
|
secureOption otlpmetricgrpc.Option
|
|
)
|
|
if !cfgSignoz.Traces.Insecure {
|
|
secureOption = otlpmetricgrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
|
|
} else {
|
|
secureOption = otlpmetricgrpc.WithInsecure()
|
|
}
|
|
|
|
exporter, err := otlpmetricgrpc.New(
|
|
context.Background(),
|
|
secureOption,
|
|
otlpmetricgrpc.WithEndpoint(cfgSignoz.Traces.GRPCEndPoint),
|
|
)
|
|
|
|
if err != nil {
|
|
log.Fatalf("Failed to create exporter: %v", err)
|
|
}
|
|
|
|
res, err := resource.New(
|
|
context.Background(),
|
|
resource.WithAttributes(
|
|
attribute.String("service.name", cfgSignoz.ServiceName),
|
|
attribute.String("library.language", "go"),
|
|
),
|
|
)
|
|
if err != nil {
|
|
log.Fatalf("Could not set resources: %v", err)
|
|
}
|
|
|
|
// Register the exporter with an SDK via a periodic reader.
|
|
provider := metricsdk.NewMeterProvider(
|
|
metricsdk.WithResource(res),
|
|
metricsdk.WithReader(metricsdk.NewPeriodicReader(exporter)),
|
|
)
|
|
return provider, provider.Meter(cfgSignoz.ServiceName)
|
|
}
|
|
|
|
func GenerateMetrics(meter api.Meter) {
|
|
go exceptionsCounter(meter)
|
|
go pageFaultsCounter(meter)
|
|
go requestDurationHistogram(meter)
|
|
go roomTemperatureGauge(meter)
|
|
go itemsInQueueUpDownCounter(meter)
|
|
go processHeapSizeUpDownCounter(meter)
|
|
}
|