otel.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package logs
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "time"
  6. otel "github.com/agoda-com/opentelemetry-logs-go"
  7. "github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs"
  8. "github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs/otlplogshttp"
  9. otelLogs "github.com/agoda-com/opentelemetry-logs-go/logs"
  10. sdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs"
  11. "github.com/coroot/coroot-node-agent/common"
  12. "github.com/coroot/coroot-node-agent/flags"
  13. "github.com/coroot/logparser"
  14. klog "github.com/sirupsen/logrus"
  15. "go.opentelemetry.io/otel/attribute"
  16. "go.opentelemetry.io/otel/sdk/resource"
  17. semconv "go.opentelemetry.io/otel/semconv/v1.18.0"
  18. )
  19. var otelLogger otelLogs.Logger
  20. func Init(machineId, hostname, version string) {
  21. endpointUrl := *flags.LogsEndpoint
  22. if endpointUrl == nil {
  23. klog.Infoln("no OpenTelemetry logs collector endpoint configured")
  24. return
  25. }
  26. klog.Infoln("OpenTelemetry logs collector endpoint:", endpointUrl.String())
  27. path := endpointUrl.Path
  28. if path == "" {
  29. path = "/"
  30. }
  31. opts := []otlplogshttp.Option{
  32. otlplogshttp.WithEndpoint(endpointUrl.Host),
  33. otlplogshttp.WithURLPath(path),
  34. otlplogshttp.WithHeaders(common.AuthHeaders()),
  35. otlplogshttp.WithTLSClientConfig(&tls.Config{InsecureSkipVerify: *flags.InsecureSkipVerify}),
  36. }
  37. if endpointUrl.Scheme != "https" {
  38. opts = append(opts, otlplogshttp.WithInsecure())
  39. }
  40. client := otlplogshttp.NewClient(opts...)
  41. exporter, _ := otlplogs.NewExporter(context.Background(), otlplogs.WithClient(client))
  42. loggerProvider := sdk.NewLoggerProvider(
  43. sdk.WithBatcher(exporter),
  44. sdk.WithResource(
  45. resource.NewWithAttributes(
  46. semconv.SchemaURL,
  47. semconv.ServiceName("coroot-node-agent"),
  48. semconv.HostName(hostname),
  49. semconv.HostID(machineId),
  50. ),
  51. ),
  52. )
  53. otel.SetLoggerProvider(loggerProvider)
  54. otelLogger = loggerProvider.Logger("coroot-node-agent", otelLogs.WithInstrumentationVersion(version))
  55. }
  56. func OtelLogEmitter(containerId string) logparser.OnMsgCallbackF {
  57. if otelLogger == nil {
  58. return nil
  59. }
  60. return func(ts time.Time, level logparser.Level, patternHash string, msg string) {
  61. severityText := level.String()
  62. severityNumber := otelLogs.UNSPECIFIED
  63. switch level {
  64. case logparser.LevelCritical:
  65. severityNumber = otelLogs.FATAL
  66. case logparser.LevelError:
  67. severityNumber = otelLogs.ERROR
  68. case logparser.LevelWarning:
  69. severityNumber = otelLogs.WARN
  70. case logparser.LevelInfo:
  71. severityNumber = otelLogs.INFO
  72. case logparser.LevelDebug:
  73. severityNumber = otelLogs.DEBUG
  74. }
  75. otelLogger.Emit(
  76. otelLogs.NewLogRecord(otelLogs.LogRecordConfig{
  77. ObservedTimestamp: ts,
  78. SeverityText: &severityText,
  79. SeverityNumber: &severityNumber,
  80. Body: &msg,
  81. Resource: resource.NewSchemaless(
  82. semconv.ServiceName(common.ContainerIdToOtelServiceName(containerId)),
  83. semconv.ContainerID(containerId),
  84. ),
  85. Attributes: &[]attribute.KeyValue{
  86. attribute.Key("pattern.hash").String(patternHash),
  87. },
  88. }),
  89. )
  90. }
  91. }