gitlab-labkit 0.10.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2476531528be243ed0069feffe3bbfbc7d557556455616e7d4216aa686422409
4
- data.tar.gz: 43223820267f18725601573595ba607178788178b1922835becaf7c72d593b2f
3
+ metadata.gz: 54ad7f3ed011ed85b6f0c090f05cd47a4bf7c738fabd2a165bad85b6e4d288c0
4
+ data.tar.gz: c833a07fa745fe8286b9c000879de8b0f338c0d24b722e71dc5044c60dcc3b79
5
5
  SHA512:
6
- metadata.gz: 712fd95e6a754409e83a8b5ee690c1843b233794a33a7461dea2fdc84c49eb8e873c7298ee15087302c32b60faeca83fd3592a80e471640a3c80710fa094e54e
7
- data.tar.gz: e6d4d048caa06702bd47326574d105f32d9d5e7c27d3c619ac529e4cb35f671a7cfca92e1d9b6460a1b6080c90bc05306f2df17381ca6e104ad30a5171a22bb8
6
+ metadata.gz: 5c724e7322119314f35831c726900220842e2f473a48d81241a94cc2eb4f34da39bb38c843ba72b724a1b5d0dff5e1b115cec704468d49797d4c681c309cf7ba
7
+ data.tar.gz: 91e870d9af690c2b5f6ce7659954616880ee3313f710b49c89505cbe915c4606ef3d1032d905cbfd1be4e547d98c846baa6fed052836833e71dc7a59444c0727
@@ -21,7 +21,8 @@ module Labkit
21
21
  LOG_KEY = "meta"
22
22
  CORRELATION_ID_KEY = "correlation_id"
23
23
  RAW_KEYS = [CORRELATION_ID_KEY].freeze
24
- KNOWN_KEYS = %w[user project root_namespace subscription_plan caller_id].freeze
24
+ KNOWN_KEYS = %w[user project root_namespace subscription_plan caller_id
25
+ related_class feature_category].freeze
25
26
 
26
27
  class << self
27
28
  def with_context(attributes = {})
@@ -7,6 +7,16 @@ module Labkit
7
7
  # It is not part of the public API
8
8
  module GRPCCommon
9
9
  CORRELATION_METADATA_KEY = "x-gitlab-correlation-id"
10
+
11
+ def rpc_split(method)
12
+ owner = method.owner
13
+ method_name, = owner.rpc_descs.find do |k, _|
14
+ ::GRPC::GenericService.underscore(k.to_s) == method.name.to_s
15
+ end
16
+ method_name ||= "(unknown)"
17
+
18
+ [owner.service_name, method_name]
19
+ end
10
20
  end
11
21
  end
12
22
  end
@@ -4,6 +4,7 @@ module Labkit
4
4
  # Logging provides functionality for logging, such as
5
5
  # sanitization
6
6
  module Logging
7
+ autoload :GRPC, "labkit/logging/grpc"
7
8
  autoload :Sanitizer, "labkit/logging/sanitizer"
8
9
  end
9
10
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Logging
5
+ module GRPC
6
+ autoload :ServerInterceptor, "labkit/logging/grpc/server_interceptor"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "grpc"
4
+ require "json"
5
+
6
+ module Labkit
7
+ module Logging
8
+ module GRPC
9
+ class ServerInterceptor < ::GRPC::ServerInterceptor
10
+ include Labkit::Correlation::GRPC::GRPCCommon
11
+
12
+ CODE_STRINGS = {
13
+ ::GRPC::Core::StatusCodes::OK => "OK",
14
+ ::GRPC::Core::StatusCodes::CANCELLED => "Canceled",
15
+ ::GRPC::Core::StatusCodes::UNKNOWN => "Unknown",
16
+ ::GRPC::Core::StatusCodes::INVALID_ARGUMENT => "InvalidArgument",
17
+ ::GRPC::Core::StatusCodes::DEADLINE_EXCEEDED => "DeadlineExceeded",
18
+ ::GRPC::Core::StatusCodes::NOT_FOUND => "NotFound",
19
+ ::GRPC::Core::StatusCodes::ALREADY_EXISTS => "AlreadyExists",
20
+ ::GRPC::Core::StatusCodes::PERMISSION_DENIED => "PermissionDenied",
21
+ ::GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED => "ResourceExhausted",
22
+ ::GRPC::Core::StatusCodes::FAILED_PRECONDITION => "FailedPrecondition",
23
+ ::GRPC::Core::StatusCodes::ABORTED => "Aborted",
24
+ ::GRPC::Core::StatusCodes::OUT_OF_RANGE => "OutOfRange",
25
+ ::GRPC::Core::StatusCodes::UNIMPLEMENTED => "Unimplemented",
26
+ ::GRPC::Core::StatusCodes::INTERNAL => "Internal",
27
+ ::GRPC::Core::StatusCodes::UNAVAILABLE => "Unavailable",
28
+ ::GRPC::Core::StatusCodes::DATA_LOSS => "DataLoss",
29
+ ::GRPC::Core::StatusCodes::UNAUTHENTICATED => "Unauthenticated",
30
+ }.freeze
31
+
32
+ def initialize(log_file, default_tags)
33
+ @log_file = log_file
34
+ @log_file.sync = true
35
+ @default_tags = default_tags
36
+
37
+ super()
38
+ end
39
+
40
+ def request_response(request: nil, call: nil, method: nil)
41
+ log_request(method, call) { yield }
42
+ end
43
+
44
+ def server_streamer(request: nil, call: nil, method: nil)
45
+ log_request(method, call) { yield }
46
+ end
47
+
48
+ def client_streamer(call: nil, method: nil)
49
+ log_request(method, call) { yield }
50
+ end
51
+
52
+ def bidi_streamer(requests: nil, call: nil, method: nil)
53
+ log_request(method, call) { yield }
54
+ end
55
+
56
+ private
57
+
58
+ def log_request(method, call)
59
+ start = Time.now
60
+ code = ::GRPC::Core::StatusCodes::OK
61
+
62
+ yield
63
+ rescue StandardError => ex
64
+ code = ex.is_a?(::GRPC::BadStatus) ? ex.code : ::GRPC::Core::StatusCodes::UNKNOWN
65
+
66
+ raise
67
+ ensure
68
+ service_name, method_name = rpc_split(method)
69
+ message = @default_tags.merge(
70
+ 'grpc.time_ms': ((Time.now - start) * 1000.0).truncate(3),
71
+ 'grpc.code': CODE_STRINGS.fetch(code, code.to_s),
72
+ 'grpc.method': method_name,
73
+ 'grpc.service': service_name,
74
+ pid: Process.pid,
75
+ correlation_id: Labkit::Correlation::CorrelationId.current_id.to_s,
76
+ time: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%LZ"),
77
+ )
78
+
79
+ @log_file.puts(JSON.dump(message))
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -28,6 +28,10 @@ module Labkit
28
28
  ENV["GITLAB_TRACING_URL"]
29
29
  end
30
30
 
31
+ def self.stacktrace_operations
32
+ @stacktrace_operations ||= Set.new(ENV["GITLAB_TRACING_INCLUDE_STACKTRACE"].to_s.split(",").map(&:strip))
33
+ end
34
+
31
35
  def self.tracing_url_enabled?
32
36
  enabled? && tracing_url_template.present?
33
37
  end
@@ -14,6 +14,8 @@ module Labkit
14
14
  # for instrumenting GRPC calls with distributed tracing
15
15
  # in a GRPC Ruby server
16
16
  class ServerInterceptor < ::GRPC::ServerInterceptor
17
+ include Labkit::Correlation::GRPC::GRPCCommon
18
+
17
19
  def request_response(request: nil, call: nil, method: nil)
18
20
  wrap_with_tracing(call, method, "unary") do
19
21
  yield
@@ -40,16 +42,9 @@ module Labkit
40
42
 
41
43
  private
42
44
 
43
- def route_from_method(method)
44
- service_class = method.owner
45
- rpc_method = method.name.to_s.split("_").map(&:capitalize).join("")
46
-
47
- "/#{service_class.service_name}/#{rpc_method}"
48
- end
49
-
50
45
  def wrap_with_tracing(call, method, grpc_type)
51
46
  context = TracingUtils.tracer.extract(OpenTracing::FORMAT_TEXT_MAP, call.metadata)
52
- method_name = route_from_method(method)
47
+ method_name = "/#{rpc_split(method).join("/")}"
53
48
  tags = {
54
49
  "component" => "grpc",
55
50
  "span.kind" => "server",
@@ -17,6 +17,8 @@ module Labkit
17
17
  scope = scope_stack.pop
18
18
  span = scope.span
19
19
 
20
+ Labkit::Tracing::TracingUtils.log_common_fields_on_span(span, span_name(payload))
21
+
20
22
  exception = payload[:exception]
21
23
  Labkit::Tracing::TracingUtils.log_exception_on_span(span, exception) if exception
22
24
 
@@ -8,7 +8,7 @@ module Labkit
8
8
  # RedisInterceptorHelper is a helper for the RedisInterceptor. This is not a public API
9
9
  class RedisInterceptorHelper
10
10
  # For optimization, compile this once
11
- MASK_REDIS_RE = /^([\w-]+(?:\W+[\w-]+(?:\W+[\w-]+)?)?)(.?)/.freeze
11
+ MASK_REDIS_RE = /^([\w{}-]+(?:\W+[\w{}-]+(?:\W+[\w{}-]+)?)?)(.?)/.freeze
12
12
 
13
13
  def self.call_with_tracing(command, client)
14
14
  Labkit::Tracing::TracingUtils.with_tracing(operation_name: "redis.call", tags: tags_from_command(command, client)) do |_span|
@@ -99,6 +99,7 @@ module Labkit
99
99
  return "" if argument.empty?
100
100
 
101
101
  matches = argument.match(MASK_REDIS_RE)
102
+
102
103
  matches[2].empty? ? matches[0] : matches[0] + "*****"
103
104
  end
104
105
  private_class_method :mask_redis_arg
@@ -12,9 +12,7 @@ module Labkit
12
12
  scope = tracer.start_active_span(operation_name, child_of: child_of, tags: tags)
13
13
  span = scope.span
14
14
 
15
- # Add correlation details to the span if we have them
16
- correlation_id = Labkit::Correlation::CorrelationId.current_id
17
- span.set_tag("correlation_id", correlation_id) if correlation_id
15
+ log_common_fields_on_span(span, operation_name)
18
16
 
19
17
  begin
20
18
  yield span
@@ -35,11 +33,19 @@ module Labkit
35
33
  def self.postnotify_span(operation_name, start_time, end_time, tags: nil, child_of: nil, exception: nil)
36
34
  span = OpenTracing.start_span(operation_name, start_time: start_time, tags: tags, child_of: child_of)
37
35
 
36
+ log_common_fields_on_span(span, operation_name)
38
37
  log_exception_on_span(span, exception) if exception
39
38
 
40
39
  span.finish(end_time: end_time)
41
40
  end
42
41
 
42
+ # Add common fields to a span
43
+ def self.log_common_fields_on_span(span, operation_name)
44
+ correlation_id = Labkit::Correlation::CorrelationId.current_id
45
+ span.set_tag("correlation_id", correlation_id) if correlation_id
46
+ span.log_kv(stack: caller.join('\n')) if include_stacktrace?(operation_name)
47
+ end
48
+
43
49
  # Add exception logging to a span
44
50
  def self.log_exception_on_span(span, exception)
45
51
  span.set_tag("error", true)
@@ -60,6 +66,14 @@ module Labkit
60
66
  { :"event" => "error", :"error.kind" => exception.class.to_s, :"error.object" => Labkit::Logging::Sanitizer.sanitize_field(exception.to_s) }
61
67
  end
62
68
  end
69
+
70
+ def self.include_stacktrace?(operation_name)
71
+ @include_stacktrace ||= Hash.new do |result, name|
72
+ result[name] = Tracing.stacktrace_operations.any? { |stacktrace_operation| name.starts_with?(stacktrace_operation) }
73
+ end
74
+
75
+ @include_stacktrace[operation_name]
76
+ end
63
77
  end
64
78
  end
65
79
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-labkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newdigate
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-05 00:00:00.000000000 Z
11
+ date: 2020-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -279,6 +279,8 @@ files:
279
279
  - lib/labkit/correlation/grpc/grpc_common.rb
280
280
  - lib/labkit/correlation/grpc/server_interceptor.rb
281
281
  - lib/labkit/logging.rb
282
+ - lib/labkit/logging/grpc.rb
283
+ - lib/labkit/logging/grpc/server_interceptor.rb
282
284
  - lib/labkit/logging/sanitizer.rb
283
285
  - lib/labkit/middleware.rb
284
286
  - lib/labkit/middleware/rack.rb