otel.go 2.8 KB

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