Passed
Push — master ( 82b547...c72b96 )
by Tolga
01:32 queued 13s
created

pkg/telemetry/log.go   A

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 61
dl 0
loc 101
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A telemetry.NewOTLPHandler 0 15 2
A telemetry.NewGCPHandler 0 22 4
A telemetry.newResource 0 12 1
A telemetry.HandlerFactory 0 8 4
A telemetry.NewLog 0 9 1
1
package telemetry
2
3
import (
4
	"context"
5
	"errors"
6
	"fmt"
7
	"log/slog"
8
	"os"
9
	"runtime"
10
11
	"github.com/Permify/sloggcp"
12
	"github.com/agoda-com/opentelemetry-go/otelslog"
13
14
	"go.opentelemetry.io/otel/attribute"
15
16
	sdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs"
17
18
	"go.opentelemetry.io/otel/sdk/resource"
19
	semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
20
21
	"github.com/Permify/permify/internal"
22
	"github.com/Permify/permify/pkg/telemetry/logexporters"
23
)
24
25
// HandlerFactory - Create log handler according to given params
26
func HandlerFactory(name, endpoint string, insecure bool, urlpath string, headers map[string]string, protocol string, level slog.Leveler) (slog.Handler, error) {
27
	switch name {
28
	case "otlp", "otlp-http", "otlp-grpc":
29
		return NewOTLPHandler(endpoint, insecure, urlpath, headers, protocol, level.Level())
30
	case "gcp":
31
		return NewGCPHandler(headers, level)
32
	default:
33
		return nil, fmt.Errorf("%s log handler is unsupported", name)
34
	}
35
}
36
37
func NewOTLPHandler(endpoint string, insecure bool, urlPath string, headers map[string]string, protocol string, level slog.Leveler) (slog.Handler, error) {
38
	// Set up the OTLP exporter based on the protocol
39
	exporter, err := logexporters.ExporterFactory("otlp", endpoint, insecure, urlPath, headers, protocol)
40
	if err != nil {
41
		return nil, errors.New("failed to create OTLP exporter")
42
	}
43
44
	// Initialize the OpenTelemetry handler with the exporter
45
	lp := NewLog(exporter)
46
	otelHandler := otelslog.NewOtelHandler(lp, &otelslog.HandlerOptions{
47
		Level: level,
48
	})
49
50
	// Shut down the exporter when needed
51
	return otelHandler, nil
52
}
53
54
func NewGCPHandler(headers map[string]string, level slog.Leveler) (slog.Handler, error) {
55
	// Retrieve Google Cloud credentials from headers
56
	creds := headers["google-application-credentials"]
57
	projectId := headers["google-cloud-project"]
58
59
	if projectId == "" {
60
		return nil, errors.New("missing GOOGLE_CLOUD_PROJECT in headers")
61
	}
62
63
	// Set credentials for Google Cloud access
64
	if creds != "" {
65
		if err := os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", creds); err != nil {
66
			return nil, err
67
		}
68
	}
69
70
	// Initialize GCP-specific log handler
71
	logName := internal.Identifier
72
	gcpHandler := sloggcp.NewGoogleCloudSlogHandler(context.Background(), projectId, logName, &slog.HandlerOptions{
73
		Level: level,
74
	})
75
	return gcpHandler, nil
76
}
77
78
// NewLog - Creates new log
79
func NewLog(exporter sdk.LogRecordExporter) *sdk.LoggerProvider {
80
	// Create a logger provider with the exporter and resource
81
	lp := sdk.NewLoggerProvider(
82
		sdk.WithBatcher(exporter),
83
		sdk.WithResource(newResource()),
84
	)
85
86
	// Return the logger provider
87
	return lp
88
}
89
90
func newResource() *resource.Resource {
91
	hostName, _ := os.Hostname()
92
	return resource.NewWithAttributes(
93
		semconv.SchemaURL,
94
		semconv.ServiceNameKey.String("permify"),
95
		semconv.HostNameKey.String(hostName),
96
		attribute.String("id", internal.Identifier),
97
		attribute.String("project.id", internal.Identifier),
98
		attribute.String("version", internal.Version),
99
		attribute.String("host_name", hostName),
100
		attribute.String("os", runtime.GOOS),
101
		attribute.String("arch", runtime.GOARCH),
102
	)
103
}
104