Class: Highlight::H

Inherits:
Object
  • Object
show all
Defined in:
lib/highlight.rb

Defined Under Namespace

Classes: HighlightHeaders

Constant Summary collapse

HIGHLIGHT_REQUEST_HEADER =
'X-Highlight-Request'.freeze
OTLP_HTTP =
'https://otel.highlight.io:4318'.freeze
HIGHLIGHT_PROJECT_ATTRIBUTE =
'highlight.project_id'.freeze
HIGHLIGHT_SESSION_ATTRIBUTE =
'highlight.session_id'.freeze
HIGHLIGHT_TRACE_ATTRIBUTE =
'highlight.trace_id'.freeze
LOG_EVENT =
'log'.freeze
LOG_SEVERITY_ATTRIBUTE =
'log.severity'.freeze
LOG_MESSAGE_ATTRIBUTE =
'log.message'.freeze
CODE_FILEPATH =
OpenTelemetry::SemanticConventions::Trace::CODE_FILEPATH
CODE_LINENO =
OpenTelemetry::SemanticConventions::Trace::CODE_LINENO
CODE_FUNCTION =
OpenTelemetry::SemanticConventions::Trace::CODE_FUNCTION

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_id, environment: '', otlp_endpoint: OTLP_HTTP) ⇒ H

Returns a new instance of H.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/highlight.rb', line 25

def initialize(project_id, environment: '', otlp_endpoint: OTLP_HTTP)
  @@instance = self # rubocop:disable Style/ClassVars

  @project_id = project_id
  @otlp_endpoint = otlp_endpoint

  OpenTelemetry::SDK.configure do |c|
    c.add_span_processor(OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
                           OpenTelemetry::Exporter::OTLP::Exporter.new(
                             endpoint: "#{@otlp_endpoint}/v1/traces", compression: 'gzip'
                           ), schedule_delay: 1000, max_export_batch_size: 128, max_queue_size: 1024
                         ))

    c.resource = OpenTelemetry::SDK::Resources::Resource.create(
      OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT => environment
    )

    yield c if block_given?
  end

  @tracer_provider = OpenTelemetry.tracer_provider
  @tracer = @tracer_provider.tracer('highlight-tracer')
end

Class Method Details

.instanceObject



21
22
23
# File 'lib/highlight.rb', line 21

def self.instance
  @@instance
end

.log_level_string(level) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/highlight.rb', line 106

def self.log_level_string(level)
  case level
  when Logger::UNKNOWN
    'UNKNOWN'
  when Logger::FATAL
    'FATAL'
  when Logger::ERROR
    'ERROR'
  when Logger::WARN
    'WARN'
  when Logger::INFO
    'INFO'
  when Logger::DEBUG
    'DEBUG'
  else
    'UNKNOWN'
  end
end

.parse_headers(headers) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/highlight.rb', line 98

def self.parse_headers(headers)
  if headers && headers[HIGHLIGHT_REQUEST_HEADER]
    session_id, request_id = headers[HIGHLIGHT_REQUEST_HEADER].split('/')
    return HighlightHeaders.new(session_id, request_id)
  end
  HighlightHeaders.new(nil, nil)
end

Instance Method Details

#flushObject



49
50
51
# File 'lib/highlight.rb', line 49

def flush
  @tracer_provider.force_flush
end

#record_exception(e, attrs = {}) ⇒ Object



66
67
68
69
70
71
# File 'lib/highlight.rb', line 66

def record_exception(e, attrs = {})
  span = OpenTelemetry::Trace.current_span
  return unless span

  span.record_exception(e, attributes: attrs)
end

#record_log(session_id, request_id, level, message, attrs = {}) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/highlight.rb', line 73

def record_log(session_id, request_id, level, message, attrs = {})
  caller_info = caller[0].split(':', 3)
  function = caller_info[2]
  if function
    # format: "in `<function_name>""
    function.delete_prefix!('in `')
    function.delete_suffix!('"')
  end
  @tracer.in_span('highlight-ctx', attributes: {
    HIGHLIGHT_PROJECT_ATTRIBUTE => @project_id,
    HIGHLIGHT_SESSION_ATTRIBUTE => session_id,
    HIGHLIGHT_TRACE_ATTRIBUTE => request_id
  }.compact) do |span|
    span.status = OpenTelemetry::Trace::Status.error(message) if [Logger::ERROR, Logger::FATAL].include?(level)
    span.add_event(LOG_EVENT, attributes: {
      LOG_SEVERITY_ATTRIBUTE => H.log_level_string(level),
      LOG_MESSAGE_ATTRIBUTE => message,
      CODE_FILEPATH => caller_info[0],
      CODE_LINENO => caller_info[1],
      CODE_FUNCTION => function
    }.merge(attrs))
  end
end

#trace(session_id, request_id, attrs = {}) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/highlight.rb', line 53

def trace(session_id, request_id, attrs = {})
  @tracer.in_span('highlight-ctx', attributes: {
    HIGHLIGHT_PROJECT_ATTRIBUTE => @project_id,
    HIGHLIGHT_SESSION_ATTRIBUTE => session_id,
    HIGHLIGHT_TRACE_ATTRIBUTE => request_id
  }.merge(attrs).compact) do |_span|
    yield
  rescue StandardError => e
    record_exception(e)
    raise
  end
end