multiplayer_otlp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/multiplayer/exporters/http_exporter.rb +57 -0
- data/lib/multiplayer/middleware/middleware.rb +122 -0
- data/lib/multiplayer/middleware/request_middleware.rb +31 -0
- data/lib/multiplayer/middleware/response_middleware.rb +32 -0
- data/lib/multiplayer/multiplayer.rb +25 -0
- data/lib/multiplayer/utils/id_generator.rb +42 -0
- data/lib/multiplayer/utils/json_schema_generator.rb +36 -0
- data/lib/multiplayer/utils/trace_id_ratio_based_sampler.rb +57 -0
- data/lib/multiplayer/version.rb +3 -0
- data/lib/multiplayer_otlp.rb +4 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7eeb6ab03f33e4743bfebca755ccbceda2cd5d4ab6845b8253efd76959c56a1e
|
4
|
+
data.tar.gz: 0fb380313170e64a5e13973458fe4ffefb719e5f241f6ed91db5d5b5bae0c657
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5cfefcca13d72d096f0b1b58030cfaa20a8a9c3733137662b49a56f3e4b56ba4c312e3807f9d5035b9cfcd87749790316e12f455e6e9fda896cc5d6c3fefce1d
|
7
|
+
data.tar.gz: 3d8361914b09d0279f60055fac13fbad994100dbe933f381362029695c4c2defbef599561c4157a6cb1c25004749fec405309e9d390daaa9ca45219056e97236
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "json"
|
2
|
+
require "opentelemetry/sdk"
|
3
|
+
require "opentelemetry/exporter/otlp"
|
4
|
+
|
5
|
+
module Multiplayer
|
6
|
+
class ExporterConfig
|
7
|
+
attr_accessor :endpoint, :headers, :api_key
|
8
|
+
|
9
|
+
def initialize(endpoint: nil, headers: {}, api_key: nil)
|
10
|
+
@endpoint = endpoint
|
11
|
+
@headers = headers
|
12
|
+
@api_key = api_key
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Exporter < OpenTelemetry::Exporter::OTLP::Exporter
|
17
|
+
def initialize(config = Multiplayer::ExporterConfig.new)
|
18
|
+
|
19
|
+
config.endpoint ||= MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL
|
20
|
+
config.headers = (config.headers || {}).merge(
|
21
|
+
config.api_key ? { "Authorization" => config.api_key } : {}
|
22
|
+
)
|
23
|
+
super(endpoint: config.endpoint, headers: config.headers)
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_default_url(config)
|
27
|
+
config.url || MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.filter_mp_attributes(exporter)
|
31
|
+
original_export = exporter.method("export")
|
32
|
+
exporter.define_singleton_method("export") do |*args, &block|
|
33
|
+
args[0] = Exporter.prefilter(args[0])
|
34
|
+
original_export.call(*args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
exporter
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def self.prefilter(spans)
|
42
|
+
spans.map do |span|
|
43
|
+
new_attributes = span[:attributes].each_with_object({}) do |(key, value), acc|
|
44
|
+
unless key.start_with?(MULTIPLAYER_ATTRIBUTE_PREFIX)
|
45
|
+
acc[key] = value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
span_with_new_attributes = span.dup
|
50
|
+
span_with_new_attributes[:attributes] = new_attributes
|
51
|
+
|
52
|
+
span_with_new_attributes
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Multiplayer
|
4
|
+
class Middleware
|
5
|
+
attr_reader :headers_to_mask, :max_payload_size, :schemify_doc_span_payload, :mask_deb_span_payload
|
6
|
+
def initialize(app, options = {
|
7
|
+
headers_to_mask: [],
|
8
|
+
max_payload_size: nil,
|
9
|
+
schemify_doc_span_payload: true,
|
10
|
+
mask_deb_span_payload: true
|
11
|
+
}
|
12
|
+
)
|
13
|
+
@app = app
|
14
|
+
@headers_to_mask = options[:headers_to_mask] || []
|
15
|
+
@max_payload_size = options[:max_payload_size] || MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE
|
16
|
+
@schemify_doc_span_payload = options.key?(:schemify_doc_span_payload) ?
|
17
|
+
options[:schemify_doc_span_payload] :
|
18
|
+
true
|
19
|
+
@mask_deb_span_payload = options.key?(:mask_deb_span_payload) ?
|
20
|
+
options[:mask_deb_span_payload] :
|
21
|
+
true
|
22
|
+
|
23
|
+
if @max_payload_size > MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE
|
24
|
+
@max_payload_size = MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def mask_primitives(input, current_depth = 0)
|
31
|
+
return MASK_PLACEHOLDER if current_depth >= MAX_MASK_DEPTH
|
32
|
+
|
33
|
+
case input
|
34
|
+
when Hash
|
35
|
+
input.transform_values { |value| mask_primitives(value, current_depth + 1) }
|
36
|
+
when Array
|
37
|
+
input.map { |value| mask_primitives(value, current_depth + 1) }
|
38
|
+
when String, Numeric, TrueClass, FalseClass, NilClass, Symbol
|
39
|
+
MASK_PLACEHOLDER
|
40
|
+
else
|
41
|
+
input
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def mask_body(value)
|
46
|
+
payload_json = begin
|
47
|
+
JSON.parse(value)
|
48
|
+
rescue JSON::ParserError
|
49
|
+
value
|
50
|
+
end
|
51
|
+
|
52
|
+
masked_data = mask_primitives(payload_json)
|
53
|
+
|
54
|
+
unless masked_data.is_a?(String)
|
55
|
+
masked_data = masked_data.to_json
|
56
|
+
end
|
57
|
+
|
58
|
+
masked_data
|
59
|
+
end
|
60
|
+
|
61
|
+
def schemify(payload)
|
62
|
+
return "" if payload.nil?
|
63
|
+
payload_json = nil
|
64
|
+
|
65
|
+
if payload.is_a?(String)
|
66
|
+
begin
|
67
|
+
payload_json = JSON.parse(payload)
|
68
|
+
rescue JSON::ParserError
|
69
|
+
return payload
|
70
|
+
end
|
71
|
+
elsif payload.is_a?(Hash) || payload.is_a?(Array)
|
72
|
+
payload_json = payload
|
73
|
+
else
|
74
|
+
return payload
|
75
|
+
end
|
76
|
+
|
77
|
+
begin
|
78
|
+
Multiplayer::Utils::JsonSchemaGenerator.generate(payload_json)
|
79
|
+
rescue StandardError => exception
|
80
|
+
""
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def mask_headers(headers, custom_header_names_to_mask = [])
|
85
|
+
default_header_names_to_mask = ["set-cookie", "cookie", "authorization", "proxy-authorization"]
|
86
|
+
masked_headers = headers.dup
|
87
|
+
headers_to_mask = default_header_names_to_mask + custom_header_names_to_mask
|
88
|
+
|
89
|
+
headers_to_mask.each do |header_name|
|
90
|
+
masked_headers[header_name] = MASK_PLACEHOLDER if masked_headers.key?(header_name)
|
91
|
+
end
|
92
|
+
|
93
|
+
masked_headers
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Extracts request headers from the Rack environment
|
98
|
+
def extract_request_headers(env)
|
99
|
+
env.select { |k, _| k.start_with?("HTTP_") }
|
100
|
+
.transform_keys { |k| k.sub(/^HTTP_/, "").split("_").map(&:downcase).join("-") }
|
101
|
+
end
|
102
|
+
|
103
|
+
# Reads the request body safely
|
104
|
+
def extract_request_body(request)
|
105
|
+
body = request.body.read
|
106
|
+
request.body.rewind # Rewind the stream for downstream middlewares
|
107
|
+
end
|
108
|
+
|
109
|
+
# Reads the response body safely
|
110
|
+
def extract_response_body(response)
|
111
|
+
body = []
|
112
|
+
response.each { |part| body << part }
|
113
|
+
body.join
|
114
|
+
end
|
115
|
+
|
116
|
+
# Truncates payload if maxPayloadSize is set
|
117
|
+
def truncate_if_needed(data)
|
118
|
+
return data unless data.to_s.size > @max_payload_size
|
119
|
+
"#{data[0...@max_payload_size]}...[TRUNCATED]"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Multiplayer
|
2
|
+
class RequestMiddleware < Multiplayer::Middleware
|
3
|
+
def call(env)
|
4
|
+
current_span = OpenTelemetry::Trace.current_span
|
5
|
+
trace_id = current_span.context.trace_id.unpack1("H*")
|
6
|
+
request = Rack::Request.new(env)
|
7
|
+
|
8
|
+
request_headers = extract_request_headers(env)
|
9
|
+
masked_headers = mask_headers(request_headers, @headers_to_mask)
|
10
|
+
current_span.set_attribute(ATTR_MULTIPLAYER_HTTP_REQUEST_HEADERS, masked_headers.to_json)
|
11
|
+
|
12
|
+
if request_headers.key?("content-type") == "application/json"
|
13
|
+
request_body = (extract_request_body(request)).dup
|
14
|
+
|
15
|
+
if trace_id.start_with?(MULTIPLAYER_TRACE_DEBUG_PREFIX) && @mask_deb_span_payload
|
16
|
+
request_body = mask_body(request_body)
|
17
|
+
elsif trace_id.start_with?(MULTIPLAYER_TRACE_DOC_PREFIX) || @schemify_doc_span_payload
|
18
|
+
request_body = schemify(request_body)
|
19
|
+
elsif !request_body.is_a?(String)
|
20
|
+
request_body = JSON.generate(request_body)
|
21
|
+
end
|
22
|
+
|
23
|
+
request_body = truncate_if_needed(request_body)
|
24
|
+
|
25
|
+
current_span.set_attribute(ATTR_MULTIPLAYER_HTTP_REQUEST_BODY, request_body.is_a?(String) ? request_body : request_body.to_json)
|
26
|
+
end
|
27
|
+
|
28
|
+
@app.call(env)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Multiplayer
|
2
|
+
class ResponseMiddleware < Multiplayer::Middleware
|
3
|
+
def call(env)
|
4
|
+
status, headers, response = @app.call(env)
|
5
|
+
|
6
|
+
begin
|
7
|
+
current_span = OpenTelemetry::Trace.current_span
|
8
|
+
trace_id = current_span.context.trace_id.unpack1("H*")
|
9
|
+
|
10
|
+
headers["x-trace-id"] = trace_id
|
11
|
+
|
12
|
+
masked_headers = mask_headers(headers, @headers_to_mask)
|
13
|
+
response_body = (extract_response_body(response)).dup
|
14
|
+
|
15
|
+
if trace_id.start_with?(MULTIPLAYER_TRACE_DEBUG_PREFIX) && @mask_deb_span_payload
|
16
|
+
response_body = mask_body(response_body)
|
17
|
+
elsif trace_id.start_with?(MULTIPLAYER_TRACE_DOC_PREFIX) || @schemify_doc_span_payload
|
18
|
+
response_body = schemify(response_body)
|
19
|
+
elsif !response_body.is_a?(String)
|
20
|
+
response_body = JSON.generate(response_body)
|
21
|
+
end
|
22
|
+
response_body = truncate_if_needed(response_body)
|
23
|
+
|
24
|
+
current_span.set_attribute(ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS, masked_headers.to_json)
|
25
|
+
current_span.set_attribute(ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY, response_body.is_a?(String) ? response_body : response_body.to_json)
|
26
|
+
[ status, headers, response ]
|
27
|
+
rescue
|
28
|
+
[ status, headers, response ]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "utils/id_generator"
|
2
|
+
require_relative "utils/json_schema_generator"
|
3
|
+
require_relative "utils/trace_id_ratio_based_sampler"
|
4
|
+
require_relative "version"
|
5
|
+
require_relative "exporters/http_exporter"
|
6
|
+
require_relative "middleware/middleware"
|
7
|
+
require_relative "middleware/request_middleware"
|
8
|
+
require_relative "middleware/response_middleware"
|
9
|
+
|
10
|
+
module Multiplayer
|
11
|
+
MULTIPLAYER_TRACE_DOC_PREFIX = "d0cd0c"
|
12
|
+
MULTIPLAYER_TRACE_DEBUG_PREFIX = "debdeb"
|
13
|
+
MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL = "https://api.multiplayer.app/v1/traces"
|
14
|
+
MULTIPLAYER_OTEL_DEFAULT_LOGS_EXPORTER_URL = "https://api.multiplayer.app/v1/logs"
|
15
|
+
MULTIPLAYER_ATTRIBUTE_PREFIX = "multiplayer."
|
16
|
+
MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE = (ENV["MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE"] || "500000").to_i
|
17
|
+
ATTR_MULTIPLAYER_DEBUG_SESSION = "multiplayer.debug_session._id"
|
18
|
+
ATTR_MULTIPLAYER_HTTP_REQUEST_BODY = "multiplayer.http.request.body"
|
19
|
+
ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY = "multiplayer.http.response.body"
|
20
|
+
ATTR_MULTIPLAYER_HTTP_REQUEST_HEADERS = "multiplayer.http.request.headers"
|
21
|
+
ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS = "multiplayer.http.response.headers"
|
22
|
+
ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY_ENCODING = "multiplayer.http.response.body.encoding"
|
23
|
+
MASK_PLACEHOLDER = "***MASKED***"
|
24
|
+
MAX_MASK_DEPTH = 8
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "opentelemetry-sdk"
|
2
|
+
|
3
|
+
module Multiplayer
|
4
|
+
module Utils
|
5
|
+
class IdGenerator
|
6
|
+
include OpenTelemetry::Trace
|
7
|
+
attr_accessor :debug_session_short_id, :id_generator, :sampler
|
8
|
+
|
9
|
+
SHARED_CHAR_CODES_ARRAY = Array.new(32)
|
10
|
+
|
11
|
+
def initialize(auto_doc_traces_ratio = 0)
|
12
|
+
@debug_session_short_id = nil
|
13
|
+
@id_generator = IdGenerator.get_id_generator(16)
|
14
|
+
@sampler = TraceIdRatioBasedSampler.new(auto_doc_traces_ratio)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_trace_id
|
18
|
+
trace_id = @id_generator.call
|
19
|
+
if @debug_session_short_id
|
20
|
+
prefix = "#{MULTIPLAYER_TRACE_DEBUG_PREFIX}#{@debug_session_short_id}"
|
21
|
+
trace_id = "#{prefix}#{trace_id[prefix.length..-1]}"
|
22
|
+
elsif @sampler.is_mp_trace_id?(trace_id)
|
23
|
+
trace_id = "#{MULTIPLAYER_TRACE_DOC_PREFIX}#{trace_id[MULTIPLAYER_TRACE_DOC_PREFIX.length..-1]}"
|
24
|
+
end
|
25
|
+
[ trace_id ].pack("H*")
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.get_id_generator(bytes)
|
29
|
+
lambda do
|
30
|
+
(0...(bytes * 2)).each do |i|
|
31
|
+
SHARED_CHAR_CODES_ARRAY[i] = rand(16) + 48
|
32
|
+
# valid hex characters in the range 48-57 and 97-102
|
33
|
+
if SHARED_CHAR_CODES_ARRAY[i] >= 58
|
34
|
+
SHARED_CHAR_CODES_ARRAY[i] += 39
|
35
|
+
end
|
36
|
+
end
|
37
|
+
SHARED_CHAR_CODES_ARRAY[0...(bytes * 2)].map(&:chr).join
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "json-schema-generator"
|
2
|
+
|
3
|
+
module Multiplayer
|
4
|
+
module Utils
|
5
|
+
class JsonSchemaGenerator < JSON::SchemaGenerator
|
6
|
+
class << self
|
7
|
+
def generate(data)
|
8
|
+
generator = Multiplayer::JsonSchemaGenerator.new
|
9
|
+
generator.generate data
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@version = DRAFT4
|
15
|
+
@defaults = nil
|
16
|
+
|
17
|
+
@buffer = StringIO.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate(data)
|
21
|
+
statement_group = StatementGroup.new
|
22
|
+
case data
|
23
|
+
when Array
|
24
|
+
$stop = true
|
25
|
+
create_array(statement_group, data, [])
|
26
|
+
when Hash
|
27
|
+
create_hash(statement_group, data, [])
|
28
|
+
else
|
29
|
+
create_primitive(statement_group, "", data, [])
|
30
|
+
end
|
31
|
+
@buffer.puts statement_group
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "opentelemetry-sdk"
|
2
|
+
|
3
|
+
module Multiplayer
|
4
|
+
module Utils
|
5
|
+
class TraceIdRatioBasedSampler < OpenTelemetry::SDK::Trace::Samplers::TraceIdRatioBased
|
6
|
+
def initialize(ratio = 0)
|
7
|
+
@ratio = normalize(ratio)
|
8
|
+
@upper_bound = (@ratio * 0xffffffff).floor
|
9
|
+
super(@ratio)
|
10
|
+
end
|
11
|
+
|
12
|
+
def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
|
13
|
+
tracestate = OpenTelemetry::Trace.current_span(parent_context).context.tracestate
|
14
|
+
if self.is_mp_trace_id?(trace_id.unpack1("H*"))
|
15
|
+
OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: OpenTelemetry::SDK::Trace::Samplers::Decision::RECORD_AND_SAMPLE, tracestate: tracestate)
|
16
|
+
else
|
17
|
+
OpenTelemetry::SDK::Trace::Samplers::Result.new(decision: OpenTelemetry::SDK::Trace::Samplers::Decision::DROP, tracestate: tracestate)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_mp_trace_id?(trace_id)
|
22
|
+
trace_id.start_with?(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||
|
23
|
+
trace_id.start_with?(MULTIPLAYER_TRACE_DOC_PREFIX) ||
|
24
|
+
(self.valid_trace_id?(trace_id) && self.accumulate(trace_id) < @upper_bound)
|
25
|
+
end
|
26
|
+
|
27
|
+
def description
|
28
|
+
"MultiplayerTraceIdRatioBasedSampler#{@ratio}"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def valid_trace_id?(trace_id)
|
34
|
+
trace_id.is_a?(String) && trace_id.length == 32 && trace_id =~ /^([0-9a-f]{32})$/i
|
35
|
+
end
|
36
|
+
|
37
|
+
def normalize(ratio)
|
38
|
+
return 0 unless defined?(ratio) && ratio.is_a?(Numeric)
|
39
|
+
return 1 if ratio >= 1
|
40
|
+
return 0 if ratio <= 0
|
41
|
+
|
42
|
+
ratio
|
43
|
+
end
|
44
|
+
|
45
|
+
def accumulate(trace_id)
|
46
|
+
accumulation = 0
|
47
|
+
(0...trace_id.length / 8).each do |i|
|
48
|
+
pos = i * 8
|
49
|
+
part = trace_id[pos, 8].to_i(16)
|
50
|
+
accumulation = (accumulation ^ part) & 0xffffffff
|
51
|
+
end
|
52
|
+
accumulation
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multiplayer_otlp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Multiplayer Inc.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-12-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: opentelemetry-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: opentelemetry-exporter-otlp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.29.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.29.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json-schema-generator
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.0.9
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.9
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/multiplayer/exporters/http_exporter.rb
|
62
|
+
- lib/multiplayer/middleware/middleware.rb
|
63
|
+
- lib/multiplayer/middleware/request_middleware.rb
|
64
|
+
- lib/multiplayer/middleware/response_middleware.rb
|
65
|
+
- lib/multiplayer/multiplayer.rb
|
66
|
+
- lib/multiplayer/utils/id_generator.rb
|
67
|
+
- lib/multiplayer/utils/json_schema_generator.rb
|
68
|
+
- lib/multiplayer/utils/trace_id_ratio_based_sampler.rb
|
69
|
+
- lib/multiplayer/version.rb
|
70
|
+
- lib/multiplayer_otlp.rb
|
71
|
+
homepage: https://rubygems.org/gems/multiplayer_otlp
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '3.0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubygems_version: 3.5.22
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: Multiplayer OTLP library
|
94
|
+
test_files: []
|