tracecap_opentelemetry 0.1.0
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/.gitignore +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +24 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/Rakefile +7 -0
- data/debug/benchmark.rb +22 -0
- data/ext/tracecap_opentelemetry/depend +8 -0
- data/ext/tracecap_opentelemetry/extconf.rb +15 -0
- data/ext/tracecap_opentelemetry/probes.d +12 -0
- data/ext/tracecap_opentelemetry/tracecap_opentelemetry.c +146 -0
- data/lib/tracecap_opentelemetry.rb +9 -0
- data/lib/tracecap_opentelemetry/exporter.rb +48 -0
- data/lib/tracecap_opentelemetry/version.rb +5 -0
- data/tracecap_opentelementry.gemspec +31 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fde9ea889bca035b08e7ba5bf42789128c409610eba1b82571b269f5a9b42590
|
4
|
+
data.tar.gz: 96cdf9ad2854bea43bdd885020bf39186ec1cc21000a58ada3b2ab3f6a123e03
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 89099e9f1000d1991df66175917ab6e9a79f643becbc4d38132d37be10309c508a0e670aca7e4ba6c4bf4a5e084644d11e054a7f03e256b53ae4a3df4296ed68
|
7
|
+
data.tar.gz: 56b336cb010aa999f965c43781fdb34f52de3abc8b3c7ddefaaf4361b91e77eb7c39d03bdfeee9a3bd28a67beb48b16525ae85e279e410186b21a8720abd2e07
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tracecap_opentelemetry (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
benchmark-ips (2.8.4)
|
10
|
+
rake (13.0.3)
|
11
|
+
rake-compiler (1.1.1)
|
12
|
+
rake
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
ruby
|
16
|
+
x86_64-linux
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
benchmark-ips
|
20
|
+
rake-compiler
|
21
|
+
tracecap_opentelemetry!
|
22
|
+
|
23
|
+
BUNDLED WITH
|
24
|
+
2.2.9
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Theo Julienne
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# tracecap-ruby-opentelemetry
|
2
|
+
|
3
|
+
Exports OpenTelemetry-compatible spans via USDT for tracecap ingestion.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'tracecap_opentelemetry'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install tracecap_opentelemetry
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To emit traces, use `TracecapOpenTelemetry::Exporter` as an OpenTelemetry exporter. `TracecapOpenTelemetry::active?` can also be used to see if a tracer is listening.
|
24
|
+
|
25
|
+
The spans can be traced directly with `dtrace`:
|
26
|
+
```
|
27
|
+
$ sudo dtrace -n 'ruby-span { trace(arg0); trace(copyinstr(arg1)); trace(copyinstr(arg2)); }'
|
28
|
+
```
|
29
|
+
|
30
|
+
## Contributing
|
31
|
+
|
32
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/tracecap/tracecap-ruby-opentelemetry.
|
33
|
+
|
34
|
+
## License
|
35
|
+
|
36
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/debug/benchmark.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
require 'tracecap_opentelemetry'
|
3
|
+
|
4
|
+
def recurse(n, &block)
|
5
|
+
if n > 0
|
6
|
+
recurse(n-1, &block)
|
7
|
+
else
|
8
|
+
block.call()
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
recurse(500) do # make the stack deep before benchmarking
|
13
|
+
Benchmark.ips do |x|
|
14
|
+
x.report("tracing") do
|
15
|
+
TracecapOpenTelemetry::emit_span(0, 0, "hello", "world", "{}")
|
16
|
+
end
|
17
|
+
|
18
|
+
x.report("active check") do
|
19
|
+
TracecapOpenTelemetry::active?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "mkmf"
|
2
|
+
|
3
|
+
create_makefile "tracecap_opentelemetry/tracecap_opentelemetry"
|
4
|
+
|
5
|
+
# patch in dtrace bits, since mkmf seems to be missing options to override this?
|
6
|
+
|
7
|
+
new_mf = []
|
8
|
+
File.open('Makefile', 'r') do |f|
|
9
|
+
f.each_line do |line|
|
10
|
+
line.gsub!(/^OBJS = /, 'OBJS = probes.o ') if RUBY_PLATFORM =~ /linux/
|
11
|
+
line.gsub!(/^HDRS = /, 'HDRS = probes.h ')
|
12
|
+
new_mf << line
|
13
|
+
end
|
14
|
+
end
|
15
|
+
File.write('Makefile', new_mf.join())
|
@@ -0,0 +1,12 @@
|
|
1
|
+
provider tracecap_ruby_opentracing {
|
2
|
+
probe ruby__span(uint64_t duration, const char *component, const char *description, struct ruby_span_extra *context);
|
3
|
+
};
|
4
|
+
struct ruby_span_extra {
|
5
|
+
uint64_t ns_since_end;
|
6
|
+
|
7
|
+
uint64_t rb_stack_len;
|
8
|
+
const char *rb_stack;
|
9
|
+
|
10
|
+
uint64_t metadata_len;
|
11
|
+
const char *metadata;
|
12
|
+
};
|
@@ -0,0 +1,146 @@
|
|
1
|
+
#include <sys/time.h>
|
2
|
+
#include <signal.h>
|
3
|
+
#include <pthread.h>
|
4
|
+
|
5
|
+
#include <ruby/ruby.h>
|
6
|
+
#include <ruby/debug.h>
|
7
|
+
|
8
|
+
#include "probes.h"
|
9
|
+
|
10
|
+
#define BUF_SIZE 2048
|
11
|
+
|
12
|
+
struct ruby_span_extra {
|
13
|
+
uint64_t ns_since_end;
|
14
|
+
|
15
|
+
uint64_t rb_stack_len;
|
16
|
+
const char *rb_stack;
|
17
|
+
|
18
|
+
uint64_t metadata_len;
|
19
|
+
const char *metadata;
|
20
|
+
};
|
21
|
+
|
22
|
+
static struct {
|
23
|
+
VALUE stack_written_frames[BUF_SIZE];
|
24
|
+
int stack_written_lines[BUF_SIZE];
|
25
|
+
char *stack_written_offsets[BUF_SIZE];
|
26
|
+
int stack_last_depth;
|
27
|
+
char stack[81920];
|
28
|
+
|
29
|
+
VALUE frames_buffer[BUF_SIZE];
|
30
|
+
int lines_buffer[BUF_SIZE];
|
31
|
+
} _tracecap_data;
|
32
|
+
|
33
|
+
static inline uint64_t tracecap_update_stack()
|
34
|
+
{
|
35
|
+
int num;
|
36
|
+
int stack_left = sizeof(_tracecap_data.stack);
|
37
|
+
|
38
|
+
// read in the latest set of frames/lines
|
39
|
+
num = rb_profile_frames(0, sizeof(_tracecap_data.frames_buffer) / sizeof(VALUE), _tracecap_data.frames_buffer, _tracecap_data.lines_buffer);
|
40
|
+
|
41
|
+
// work out how many are the same as previously calculated
|
42
|
+
int same = 0;
|
43
|
+
char *stack_curr = _tracecap_data.stack;
|
44
|
+
for (int i = 0; i < num && i < _tracecap_data.stack_last_depth; i++) {
|
45
|
+
if (_tracecap_data.frames_buffer[num - 1 - i] == _tracecap_data.stack_written_frames[i] && _tracecap_data.lines_buffer[num - 1 - i] == _tracecap_data.stack_written_lines[i])
|
46
|
+
same++;
|
47
|
+
else
|
48
|
+
break;
|
49
|
+
}
|
50
|
+
|
51
|
+
if (same > 0) {
|
52
|
+
stack_curr = _tracecap_data.stack_written_offsets[same - 1];
|
53
|
+
stack_left = (int)(_tracecap_data.stack + sizeof(_tracecap_data.stack) - stack_curr);
|
54
|
+
}
|
55
|
+
|
56
|
+
int i;
|
57
|
+
for (i = same; i < num; i++) {
|
58
|
+
VALUE frame = _tracecap_data.frames_buffer[num - 1 - i];
|
59
|
+
int line = _tracecap_data.lines_buffer[num - 1 - i];
|
60
|
+
|
61
|
+
_tracecap_data.stack_written_frames[i] = frame;
|
62
|
+
_tracecap_data.stack_written_lines[i] = line;
|
63
|
+
|
64
|
+
VALUE name = rb_profile_frame_full_label(frame);
|
65
|
+
VALUE file = rb_profile_frame_path(frame);
|
66
|
+
char *file_str = StringValueCStr(file);
|
67
|
+
char maybe_package[128] = {0};
|
68
|
+
char *gems_slash = strstr(file_str, "/gems/");
|
69
|
+
char *next = gems_slash;
|
70
|
+
|
71
|
+
// find the last occurance of /gems/
|
72
|
+
while (next != NULL && *next != 0) {
|
73
|
+
next = strstr(next + 1, "/gems/");
|
74
|
+
if (next != NULL) {
|
75
|
+
gems_slash = next;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
if (gems_slash != NULL) {
|
80
|
+
char *gem_name_start = gems_slash + strlen("/gems/");
|
81
|
+
char *inside_gem = strchr(gem_name_start, '/');
|
82
|
+
if (inside_gem != NULL) {
|
83
|
+
file_str = inside_gem + 1; // skip over '/'
|
84
|
+
snprintf(maybe_package, sizeof(maybe_package), "%.*s", (int)(inside_gem - gem_name_start), gem_name_start);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
if (stack_left > 0) {
|
89
|
+
int n = snprintf(stack_curr, stack_left, "%s:%s:%d:%s\n", maybe_package, file_str, line, StringValueCStr(name));
|
90
|
+
stack_left -= n;
|
91
|
+
stack_curr += n;
|
92
|
+
} else {
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
|
96
|
+
_tracecap_data.stack_written_offsets[i] = stack_curr;
|
97
|
+
}
|
98
|
+
|
99
|
+
*stack_curr = '\0';
|
100
|
+
_tracecap_data.stack_last_depth = i;
|
101
|
+
|
102
|
+
return (uint64_t)(stack_curr - _tracecap_data.stack);
|
103
|
+
}
|
104
|
+
|
105
|
+
VALUE rb_tracecap_emit_span(VALUE self, VALUE duration, VALUE since_end, VALUE component, VALUE description, VALUE metadata)
|
106
|
+
{
|
107
|
+
if (TRACECAP_RUBY_OPENTRACING_RUBY_SPAN_ENABLED()) {
|
108
|
+
uint64_t duration_ns = NUM2ULL(duration);
|
109
|
+
uint64_t since_end_ns = NUM2ULL(since_end);
|
110
|
+
const char *component_c = StringValueCStr(component);
|
111
|
+
const char *description_c = StringValueCStr(description);
|
112
|
+
|
113
|
+
struct ruby_span_extra span_extra;
|
114
|
+
|
115
|
+
int stack_len = tracecap_update_stack();
|
116
|
+
|
117
|
+
/*
|
118
|
+
probe ruby__span(uint64_t duration, const char *component, const char *description, struct ruby_span_extra *context);
|
119
|
+
We could optionally adjust `since_end` here to compensate for any additional time spent in this function.
|
120
|
+
*/
|
121
|
+
span_extra.ns_since_end = since_end_ns;
|
122
|
+
span_extra.rb_stack_len = stack_len;
|
123
|
+
span_extra.rb_stack = _tracecap_data.stack;
|
124
|
+
span_extra.metadata_len = (int)RSTRING_LEN(metadata);
|
125
|
+
span_extra.metadata = StringValuePtr(metadata);
|
126
|
+
TRACECAP_RUBY_OPENTRACING_RUBY_SPAN(duration_ns, component_c, description_c, &span_extra);
|
127
|
+
}
|
128
|
+
return Qnil;
|
129
|
+
}
|
130
|
+
|
131
|
+
VALUE
|
132
|
+
rb_tracecap_is_active(VALUE self)
|
133
|
+
{
|
134
|
+
return TRACECAP_RUBY_OPENTRACING_RUBY_SPAN_ENABLED() ? Qtrue : Qfalse;
|
135
|
+
}
|
136
|
+
|
137
|
+
void
|
138
|
+
Init_tracecap_opentelemetry(void) {
|
139
|
+
VALUE tracecap_opentelemetry;
|
140
|
+
|
141
|
+
_tracecap_data.stack_last_depth = 0;
|
142
|
+
|
143
|
+
tracecap_opentelemetry = rb_const_get(rb_cObject, rb_intern("TracecapOpenTelemetry"));
|
144
|
+
rb_define_singleton_method(tracecap_opentelemetry, "emit_span", rb_tracecap_emit_span, 5);
|
145
|
+
rb_define_singleton_method(tracecap_opentelemetry, "active?", rb_tracecap_is_active, 0);
|
146
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'opentelemetry/sdk'
|
4
|
+
|
5
|
+
module TracecapOpenTelemetry
|
6
|
+
class Exporter < OpenTelemetry::SDK::Trace::Export::InMemorySpanExporter # pretend to be this for now for 'simple_exporter?' check
|
7
|
+
def initialize
|
8
|
+
@stopped = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def export(spans, timeout: nil)
|
12
|
+
return FAILURE if @stopped
|
13
|
+
|
14
|
+
return SUCCESS unless TracecapOpenTelemetry::active?
|
15
|
+
|
16
|
+
Array(spans).each do |span|
|
17
|
+
tags = span.attributes
|
18
|
+
component = tags["db.system"] || tags["component"] || "Trace"
|
19
|
+
|
20
|
+
operation = span.name
|
21
|
+
|
22
|
+
context = tags.dup
|
23
|
+
context["span_id"] = span.hex_span_id
|
24
|
+
context["span_parent_id"] = span.hex_parent_span_id if span.hex_parent_span_id != "0000000000000000"
|
25
|
+
json_ctx = JSON.dump(context)
|
26
|
+
|
27
|
+
start_time_nsec = span.start_timestamp.to_i
|
28
|
+
end_time_nsec = span.end_timestamp.to_i
|
29
|
+
now_nsec = (Time.now.to_r * 1_000_000_000).to_i
|
30
|
+
duration = end_time_nsec - start_time_nsec
|
31
|
+
end_delta = now_nsec - end_time_nsec
|
32
|
+
|
33
|
+
TracecapOpenTelemetry::emit_span(duration, end_delta, component.to_s, operation.to_s, json_ctx)
|
34
|
+
end
|
35
|
+
|
36
|
+
SUCCESS
|
37
|
+
end
|
38
|
+
|
39
|
+
def force_flush(timeout: nil)
|
40
|
+
SUCCESS
|
41
|
+
end
|
42
|
+
|
43
|
+
def shutdown(timeout: nil)
|
44
|
+
@stopped = true
|
45
|
+
SUCCESS
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'lib/tracecap_opentelemetry/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "tracecap_opentelemetry"
|
5
|
+
spec.version = TracecapOpenTelemetry::VERSION
|
6
|
+
spec.authors = ["Theo Julienne"]
|
7
|
+
spec.email = ["theo.julienne@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = %q{Exports OpenTelemetry spans via USDT for tracecap ingestion}
|
10
|
+
spec.homepage = "https://github.com/tracecap/tracecap-ruby-opentelemetry"
|
11
|
+
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
13
|
+
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = "https://github.com/tracecap/tracecap-ruby-opentelemetry"
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
end
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.extensions << 'ext/tracecap_opentelemetry/extconf.rb'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'rake-compiler'
|
29
|
+
spec.add_development_dependency 'benchmark-ips'
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tracecap_opentelemetry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Theo Julienne
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-08-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake-compiler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: benchmark-ips
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- theo.julienne@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions:
|
46
|
+
- ext/tracecap_opentelemetry/extconf.rb
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- LICENSE
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- debug/benchmark.rb
|
56
|
+
- ext/tracecap_opentelemetry/depend
|
57
|
+
- ext/tracecap_opentelemetry/extconf.rb
|
58
|
+
- ext/tracecap_opentelemetry/probes.d
|
59
|
+
- ext/tracecap_opentelemetry/tracecap_opentelemetry.c
|
60
|
+
- lib/tracecap_opentelemetry.rb
|
61
|
+
- lib/tracecap_opentelemetry/exporter.rb
|
62
|
+
- lib/tracecap_opentelemetry/version.rb
|
63
|
+
- tracecap_opentelementry.gemspec
|
64
|
+
homepage: https://github.com/tracecap/tracecap-ruby-opentelemetry
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata:
|
68
|
+
homepage_uri: https://github.com/tracecap/tracecap-ruby-opentelemetry
|
69
|
+
source_code_uri: https://github.com/tracecap/tracecap-ruby-opentelemetry
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 2.3.0
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubygems_version: 3.2.9
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Exports OpenTelemetry spans via USDT for tracecap ingestion
|
89
|
+
test_files: []
|