finagle-thrift 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+
3
+ require 'thrift'
4
+
5
+ require 'finagle-thrift/thrift/tracing_types'
6
+ # require 'finagle-thrift/thrift/tracing_constants'
7
+
8
+ require 'finagle-thrift/client'
9
+ require 'finagle-thrift/thrift_client'
10
+ require 'finagle-thrift/trace'
11
+ require 'finagle-thrift/tracer'
12
+
13
+ module FinagleThrift
14
+ extend self
15
+ def enable_tracing!(service, client_id = nil, service_name = nil)
16
+ raise ArgumentError, "client_id must be nil or of type FinagleThrift::ClientId" if client_id && !client_id.is_a?(FinagleThrift::ClientId)
17
+ class << service
18
+ include ::FinagleThrift::ThriftClient
19
+ end
20
+
21
+ client_class = service.client_class
22
+ client_class.class_eval do
23
+ include ::FinagleThrift::Client
24
+ end
25
+ client_class.send(:define_method, :client_id) { client_id }
26
+ client_class.send(:define_method, :trace_service_name) { service_name }
27
+ end
28
+ end
@@ -0,0 +1,85 @@
1
+ module FinagleThrift
2
+ module Client
3
+ CanTraceMethodName = "__can__finagle__trace__v3__"
4
+
5
+ include ::Thrift::Client
6
+
7
+ alias_method :_orig_send_message, :send_message
8
+ alias_method :_orig_receive_message, :receive_message
9
+
10
+ def initialize(iprot, oprot=nil)
11
+ super
12
+ @upgraded = false
13
+ @client_port = 0
14
+ attempt_upgrade!
15
+ end
16
+
17
+ def send_message(name, args_class, args = {})
18
+ if @upgraded
19
+ header = ::FinagleThrift::RequestHeader.new
20
+ header.trace_id = Trace.id.trace_id.to_i
21
+ header.parent_span_id = Trace.id.parent_id.to_i
22
+ header.span_id = Trace.id.span_id.to_i
23
+ header.sampled = Trace.id.sampled?
24
+ header.debug = false
25
+
26
+ header.client_id = client_id if client_id
27
+
28
+ header.write(@oprot)
29
+ end
30
+ Trace.record(Trace::Annotation.new(Trace::Annotation::CLIENT_SEND, self.endpoint))
31
+
32
+ _orig_send_message(name, args_class, args)
33
+ end
34
+
35
+ def receive_message(klass)
36
+ if @upgraded
37
+ response = ::FinagleThrift::ResponseHeader.new
38
+ response.read(@iprot)
39
+ end
40
+ result = _orig_receive_message(klass)
41
+ Trace.record(Trace::Annotation.new(Trace::Annotation::CLIENT_RECV, self.endpoint))
42
+ result
43
+ end
44
+
45
+ protected
46
+ def client_id
47
+ nil
48
+ end
49
+
50
+ def trace_service_name
51
+ nil
52
+ end
53
+
54
+ def endpoint
55
+ @endpoint ||= Trace.default_endpoint.with_port(@client_port).with_service_name(trace_service_name)
56
+ end
57
+
58
+ private
59
+ def attempt_upgrade!
60
+ _orig_send_message(CanTraceMethodName, ::FinagleThrift::ConnectionOptions)
61
+ begin
62
+ extract_client_port
63
+ _orig_receive_message(::FinagleThrift::UpgradeReply)
64
+ @upgraded = true
65
+ rescue ::Thrift::ApplicationException
66
+ @upgraded = false
67
+ end
68
+ rescue
69
+ @upgraded = false
70
+ raise
71
+ end
72
+
73
+ def extract_client_port
74
+ @client_port = begin
75
+ # im sorry
76
+ trans = @oprot.instance_variable_get("@trans")
77
+ transport = trans.instance_variable_get("@transport")
78
+ handle = transport.instance_variable_get("@handle")
79
+ Socket.unpack_sockaddr_in(handle.getsockname).first
80
+ rescue
81
+ 0
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,18 @@
1
+ #
2
+ # Autogenerated by Thrift
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'tracing_types'
8
+
9
+ module FinagleThrift
10
+ CLIENT_SEND = %q"cs"
11
+
12
+ CLIENT_RECV = %q"cr"
13
+
14
+ SERVER_SEND = %q"ss"
15
+
16
+ SERVER_RECV = %q"sr"
17
+
18
+ end
@@ -0,0 +1,210 @@
1
+ #
2
+ # Autogenerated by Thrift
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+
8
+ module FinagleThrift
9
+ module AnnotationType
10
+ BOOL = 0
11
+ BYTES = 1
12
+ I16 = 2
13
+ I32 = 3
14
+ I64 = 4
15
+ DOUBLE = 5
16
+ STRING = 6
17
+ VALUE_MAP = {0 => "BOOL", 1 => "BYTES", 2 => "I16", 3 => "I32", 4 => "I64", 5 => "DOUBLE", 6 => "STRING"}
18
+ VALID_VALUES = Set.new([BOOL, BYTES, I16, I32, I64, DOUBLE, STRING]).freeze
19
+ end
20
+
21
+ class Endpoint
22
+ include ::Thrift::Struct, ::Thrift::Struct_Union
23
+ IPV4 = 1
24
+ PORT = 2
25
+ SERVICE_NAME = 3
26
+
27
+ FIELDS = {
28
+ IPV4 => {:type => ::Thrift::Types::I32, :name => 'ipv4'},
29
+ PORT => {:type => ::Thrift::Types::I16, :name => 'port'},
30
+ SERVICE_NAME => {:type => ::Thrift::Types::STRING, :name => 'service_name'}
31
+ }
32
+
33
+ def struct_fields; FIELDS; end
34
+
35
+ def validate
36
+ end
37
+
38
+ ::Thrift::Struct.generate_accessors self
39
+ end
40
+
41
+ class Annotation
42
+ include ::Thrift::Struct, ::Thrift::Struct_Union
43
+ TIMESTAMP = 1
44
+ VALUE = 2
45
+ HOST = 3
46
+
47
+ FIELDS = {
48
+ TIMESTAMP => {:type => ::Thrift::Types::I64, :name => 'timestamp'},
49
+ VALUE => {:type => ::Thrift::Types::STRING, :name => 'value'},
50
+ HOST => {:type => ::Thrift::Types::STRUCT, :name => 'host', :class => FinagleThrift::Endpoint, :optional => true}
51
+ }
52
+
53
+ def struct_fields; FIELDS; end
54
+
55
+ def validate
56
+ end
57
+
58
+ ::Thrift::Struct.generate_accessors self
59
+ end
60
+
61
+ class BinaryAnnotation
62
+ include ::Thrift::Struct, ::Thrift::Struct_Union
63
+ KEY = 1
64
+ VALUE = 2
65
+ ANNOTATION_TYPE = 3
66
+ HOST = 4
67
+
68
+ FIELDS = {
69
+ KEY => {:type => ::Thrift::Types::STRING, :name => 'key'},
70
+ VALUE => {:type => ::Thrift::Types::STRING, :name => 'value', :binary => true},
71
+ ANNOTATION_TYPE => {:type => ::Thrift::Types::I32, :name => 'annotation_type', :enum_class => FinagleThrift::AnnotationType},
72
+ HOST => {:type => ::Thrift::Types::STRUCT, :name => 'host', :class => FinagleThrift::Endpoint, :optional => true}
73
+ }
74
+
75
+ def struct_fields; FIELDS; end
76
+
77
+ def validate
78
+ unless @annotation_type.nil? || FinagleThrift::AnnotationType::VALID_VALUES.include?(@annotation_type)
79
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field annotation_type!')
80
+ end
81
+ end
82
+
83
+ ::Thrift::Struct.generate_accessors self
84
+ end
85
+
86
+ class Span
87
+ include ::Thrift::Struct, ::Thrift::Struct_Union
88
+ TRACE_ID = 1
89
+ NAME = 3
90
+ ID = 4
91
+ PARENT_ID = 5
92
+ ANNOTATIONS = 6
93
+ BINARY_ANNOTATIONS = 8
94
+
95
+ FIELDS = {
96
+ TRACE_ID => {:type => ::Thrift::Types::I64, :name => 'trace_id'},
97
+ NAME => {:type => ::Thrift::Types::STRING, :name => 'name'},
98
+ ID => {:type => ::Thrift::Types::I64, :name => 'id'},
99
+ PARENT_ID => {:type => ::Thrift::Types::I64, :name => 'parent_id', :optional => true},
100
+ ANNOTATIONS => {:type => ::Thrift::Types::LIST, :name => 'annotations', :element => {:type => ::Thrift::Types::STRUCT, :class => FinagleThrift::Annotation}},
101
+ BINARY_ANNOTATIONS => {:type => ::Thrift::Types::LIST, :name => 'binary_annotations', :element => {:type => ::Thrift::Types::STRUCT, :class => FinagleThrift::BinaryAnnotation}}
102
+ }
103
+
104
+ def struct_fields; FIELDS; end
105
+
106
+ def validate
107
+ end
108
+
109
+ ::Thrift::Struct.generate_accessors self
110
+ end
111
+
112
+ # At connection time, we can let the server know who we are so
113
+ # they can book keep and optionally reject unknown clients.
114
+ class ClientId
115
+ include ::Thrift::Struct, ::Thrift::Struct_Union
116
+ NAME = 1
117
+
118
+ FIELDS = {
119
+ NAME => {:type => ::Thrift::Types::STRING, :name => 'name'}
120
+ }
121
+
122
+ def struct_fields; FIELDS; end
123
+
124
+ def validate
125
+ end
126
+
127
+ ::Thrift::Struct.generate_accessors self
128
+ end
129
+
130
+ # RequestHeader defines headers for the request. These carry the span data, and
131
+ # a flag indicating whether the request is to be debugged.
132
+ class RequestHeader
133
+ include ::Thrift::Struct, ::Thrift::Struct_Union
134
+ TRACE_ID = 1
135
+ SPAN_ID = 2
136
+ PARENT_SPAN_ID = 3
137
+ DEBUG = 4
138
+ SAMPLED = 5
139
+ CLIENT_ID = 6
140
+
141
+ FIELDS = {
142
+ TRACE_ID => {:type => ::Thrift::Types::I64, :name => 'trace_id'},
143
+ SPAN_ID => {:type => ::Thrift::Types::I64, :name => 'span_id'},
144
+ PARENT_SPAN_ID => {:type => ::Thrift::Types::I64, :name => 'parent_span_id', :optional => true},
145
+ DEBUG => {:type => ::Thrift::Types::BOOL, :name => 'debug'},
146
+ SAMPLED => {:type => ::Thrift::Types::BOOL, :name => 'sampled', :optional => true},
147
+ CLIENT_ID => {:type => ::Thrift::Types::STRUCT, :name => 'client_id', :class => FinagleThrift::ClientId, :optional => true}
148
+ }
149
+
150
+ def struct_fields; FIELDS; end
151
+
152
+ def validate
153
+ end
154
+
155
+ ::Thrift::Struct.generate_accessors self
156
+ end
157
+
158
+ # The Response carries a reply header for tracing. These are
159
+ # empty unless the request is being debugged, in which case a
160
+ # transcript is copied.
161
+ class ResponseHeader
162
+ include ::Thrift::Struct, ::Thrift::Struct_Union
163
+ SPANS = 1
164
+
165
+ FIELDS = {
166
+ SPANS => {:type => ::Thrift::Types::LIST, :name => 'spans', :element => {:type => ::Thrift::Types::STRUCT, :class => FinagleThrift::Span}}
167
+ }
168
+
169
+ def struct_fields; FIELDS; end
170
+
171
+ def validate
172
+ end
173
+
174
+ ::Thrift::Struct.generate_accessors self
175
+ end
176
+
177
+ # These are connection-level options negotiated during protocol
178
+ # upgrade.
179
+ class ConnectionOptions
180
+ include ::Thrift::Struct, ::Thrift::Struct_Union
181
+
182
+ FIELDS = {
183
+
184
+ }
185
+
186
+ def struct_fields; FIELDS; end
187
+
188
+ def validate
189
+ end
190
+
191
+ ::Thrift::Struct.generate_accessors self
192
+ end
193
+
194
+ # This is the struct that a successful upgrade will reply with.
195
+ class UpgradeReply
196
+ include ::Thrift::Struct, ::Thrift::Struct_Union
197
+
198
+ FIELDS = {
199
+
200
+ }
201
+
202
+ def struct_fields; FIELDS; end
203
+
204
+ def validate
205
+ end
206
+
207
+ ::Thrift::Struct.generate_accessors self
208
+ end
209
+
210
+ end
@@ -0,0 +1,10 @@
1
+ module FinagleThrift
2
+ module ThriftClient
3
+ def handled_proxy(method_name, *args)
4
+ Trace.push(Trace.id.next_id) do
5
+ Trace.set_rpc_name(method_name)
6
+ super(method_name, *args)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,135 @@
1
+ module Trace
2
+ extend self
3
+ DEFAULT_SAMPLE_RATE = 0.001
4
+ TRACE_ID_UPPER_BOUND = 2 ** 64
5
+
6
+ def id
7
+ if stack.empty?
8
+ span_id = generate_id
9
+ trace_id = TraceId.new(span_id, nil, span_id, should_sample?)
10
+ stack.push(trace_id)
11
+ end
12
+ stack.last
13
+ end
14
+
15
+ def push(trace_id)
16
+ stack.push(trace_id)
17
+ if block_given?
18
+ begin
19
+ yield
20
+ ensure
21
+ pop
22
+ end
23
+ end
24
+ end
25
+
26
+ def pop
27
+ stack.pop
28
+ end
29
+
30
+ def unwind
31
+ if block_given?
32
+ begin
33
+ saved_stack = stack.dup
34
+ yield
35
+ ensure
36
+ @stack = saved
37
+ end
38
+ end
39
+ end
40
+
41
+ def record(annotation)
42
+ tracer.record(id, annotation) unless stack.empty?
43
+ end
44
+
45
+ def set_rpc_name(name)
46
+ tracer.set_rpc_name(id, name) unless stack.empty?
47
+ end
48
+
49
+ def sample_rate=(sample_rate)
50
+ if sample_rate > 1 || sample_rate < 0
51
+ raise ArgumentError.new("sample rate must be [0,1]")
52
+ end
53
+ @sample_rate = sample_rate
54
+ end
55
+
56
+ def tracer=(tracer)
57
+ @tracer = tracer
58
+ end
59
+
60
+ class TraceId
61
+ attr_reader :trace_id, :parent_id, :span_id, :sampled
62
+ alias :sampled? :sampled
63
+ def initialize(trace_id, parent_id, span_id, sampled)
64
+ @trace_id = SpanId.from_value(trace_id)
65
+ @parent_id = parent_id.nil? ? nil : SpanId.from_value(parent_id)
66
+ @span_id = SpanId.from_value(span_id)
67
+ @sampled = !!sampled
68
+ end
69
+
70
+ def next_id
71
+ TraceId.new(@trace_id, @span_id, Trace.generate_id, @sampled)
72
+ end
73
+
74
+ def to_s
75
+ "TraceId(trace_id = #{@trace_id.to_s}, parent_id = #{@parent_id.to_s}, span_id = #{@span_id.to_s}, sampled = #{@sampled.to_s})"
76
+ end
77
+ end
78
+
79
+ class SpanId
80
+ HEX_REGEX = /^[a-f0-9]{16}$/i
81
+ MAX_SIGNED_I64 = 9223372036854775807
82
+ MASK = (2 ** 64) - 1
83
+
84
+ def self.from_value(v)
85
+ if v.is_a?(String) && v =~ HEX_REGEX
86
+ new(v.hex)
87
+ elsif v.is_a?(Numeric)
88
+ new(v)
89
+ elsif v.is_a?(SpanId)
90
+ v
91
+ end
92
+ end
93
+
94
+ def initialize(value)
95
+ @value = value
96
+ @i64 = if @value > MAX_SIGNED_I64
97
+ -1 * ((@value ^ MASK) + 1)
98
+ else
99
+ @value
100
+ end
101
+ end
102
+
103
+ def to_s; "%016x" % @value; end
104
+ def to_i; @i64; end
105
+ end
106
+
107
+ def generate_id
108
+ rand(TRACE_ID_UPPER_BOUND)
109
+ end
110
+
111
+ def should_sample?
112
+ rand < (@sample_rate || DEFAULT_SAMPLE_RATE)
113
+ end
114
+
115
+ def default_endpoint=(endpoint)
116
+ @default_endpoint = endpoint
117
+ end
118
+
119
+ def default_endpoint
120
+ @default_endpoint ||= begin
121
+ Endpoint.new(Endpoint.host_to_i32(Socket.gethostname), 0, "finagle-ruby")
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def stack
128
+ @stack ||= []
129
+ end
130
+
131
+ def tracer
132
+ @tracer ||= NullTracer.new
133
+ end
134
+
135
+ end
@@ -0,0 +1,245 @@
1
+ module Trace
2
+ class Tracer
3
+ def record(id, annotation)
4
+ raise "not implemented"
5
+ end
6
+
7
+ def set_rpc_name(id, name)
8
+ raise "not implemented"
9
+ end
10
+ end
11
+
12
+ class NullTracer < Tracer
13
+ def record(id, annotation)
14
+ end
15
+
16
+ def set_rpc_name(id, name)
17
+ end
18
+ end
19
+
20
+ class FanoutTracer < Tracer
21
+ def initialize(tracers)
22
+ @tracers = tracers
23
+ end
24
+
25
+ def record(id, annotation)
26
+ @tracers.each { |tracer| tracer.record(id, annotation) }
27
+ end
28
+
29
+ def set_rpc_name(id, name)
30
+ @tracers.each { |tracer| tracer.set_rpc_name(id, name) }
31
+ end
32
+ end
33
+
34
+ class FileTracer < Tracer
35
+ def initialize
36
+ @last_trace_id = nil
37
+ @file = nil
38
+ end
39
+
40
+ def record(id, annotation)
41
+ return unless id.sampled?
42
+ file = get_file_for_id(id)
43
+ file.puts("#{id.to_s}: #{annotation.to_s}")
44
+ file.flush if (annotation.is_a?(Annotation) && annotation.value == Annotation::SERVER_SEND)
45
+ end
46
+
47
+ def set_rpc_name(id, name)
48
+ return unless id.sampled?
49
+ get_file_for_id(id).puts("#{id.to_s}: name = #{name}")
50
+ end
51
+
52
+ private
53
+ def get_file_for_id(id)
54
+ id = id.trace_id.to_i
55
+ if @last_trace_id != id
56
+ @last_trace_id = id
57
+ @file.close if @file
58
+ @file = File.open("/tmp/traces/#{id}.log", "a")
59
+ end
60
+ @file
61
+ end
62
+ end
63
+
64
+ class ZipkinTracer < Tracer
65
+ TRACER_CATEGORY = "zipkin"
66
+ def initialize(scribe, max_buffer)
67
+ @scribe = scribe
68
+ @max_buffer = max_buffer
69
+ reset
70
+ end
71
+
72
+ def record(id, annotation)
73
+ return unless id.sampled?
74
+ span = get_span_for_id(id)
75
+
76
+ case annotation
77
+ when BinaryAnnotation
78
+ span.binary_annotations << annotation
79
+ when Annotation
80
+ span.annotations << annotation
81
+ end
82
+
83
+ @count += 1
84
+ if @count >= @max_buffer || (annotation.is_a?(Annotation) && annotation.value == Annotation::SERVER_SEND)
85
+ flush!
86
+ end
87
+ end
88
+
89
+ def set_rpc_name(id, name)
90
+ return unless id.sampled?
91
+ span = get_span_for_id(id)
92
+ span.name = name.to_s
93
+ end
94
+
95
+ private
96
+ def get_span_for_id(id)
97
+ key = id.span_id.to_s
98
+ @spans[key] ||= begin
99
+ Span.new("", id)
100
+ end
101
+ end
102
+
103
+ def reset
104
+ @count = 0
105
+ @spans = {}
106
+ end
107
+
108
+ def flush!
109
+ @scribe.batch do
110
+ messages = @spans.values.map do |span|
111
+ buf = ''
112
+ trans = Thrift::MemoryBufferTransport.new(buf)
113
+ oprot = Thrift::BinaryProtocol.new(trans)
114
+ span.to_thrift.write(oprot)
115
+ binary = Base64.encode64(buf).gsub("\n", "")
116
+ @scribe.log(binary, TRACER_CATEGORY)
117
+ end
118
+ end
119
+ reset
120
+ end
121
+ end
122
+
123
+ class Span
124
+ attr_accessor :name, :annotations, :binary_annotations
125
+ def initialize(name, span_id)
126
+ @name = name
127
+ @span_id = span_id
128
+ @annotations = []
129
+ @binary_annotations = []
130
+ end
131
+
132
+ def to_thrift
133
+ FinagleThrift::Span.new(
134
+ :name => @name,
135
+ :trace_id => @span_id.trace_id.to_i,
136
+ :id => @span_id.span_id.to_i,
137
+ :parent_id => @span_id.parent_id.nil? ? nil : @span_id.parent_id.to_i,
138
+ :annotations => @annotations.map { |a| a.to_thrift },
139
+ :binary_annotations => @binary_annotations.map { |a| a.to_thrift }
140
+ )
141
+ end
142
+ end
143
+
144
+ class Annotation
145
+ CLIENT_SEND = "cs"
146
+ CLIENT_RECV = "cr"
147
+ SERVER_SEND = "ss"
148
+ SERVER_RECV = "sr"
149
+
150
+ attr_reader :value, :host, :timestamp
151
+ def initialize(value, host)
152
+ @timestamp = (Time.now.to_f * 1000 * 1000).to_i # micros
153
+ @value = value
154
+ @host = host
155
+ end
156
+
157
+ def to_thrift
158
+ thrift_host = host ? host.to_thrift : nil
159
+ FinagleThrift::Annotation.new(
160
+ :value => @value,
161
+ :host => thrift_host,
162
+ :timestamp => @timestamp
163
+ )
164
+ end
165
+
166
+ def to_s
167
+ "#{@value} at #{@timestamp} for (#{@host.to_s})"
168
+ end
169
+ end
170
+
171
+ class BinaryAnnotation
172
+ module Type
173
+ BOOL = "BOOL"
174
+ BYTES = "BYTES"
175
+ I16 = "I16"
176
+ I32 = "I32"
177
+ I64 = "I64"
178
+ DOUBLE = "DOUBLE"
179
+ STRING = "STRING"
180
+
181
+ def self.to_thrift(v)
182
+ FinagleThrift::AnnotationType::VALUE_MAP.index(v)
183
+ end
184
+ end
185
+
186
+ attr_reader :key, :value, :host
187
+ def initialize(key, value, annotation_type, host)
188
+ @key = key
189
+ @value = value
190
+ @annotation_type = annotation_type
191
+ @host = host
192
+ end
193
+
194
+ def to_thrift
195
+ thrift_host = host ? host.to_thrift : nil
196
+ FinagleThrift::BinaryAnnotation.new(
197
+ :key => @key,
198
+ :value => @value,
199
+ :annotation_type => Type.to_thrift(@annotation_type),
200
+ :host => thrift_host
201
+ )
202
+ end
203
+
204
+ end
205
+
206
+ class Endpoint < Struct.new(:ipv4, :port, :service_name)
207
+ MAX_I32 = ((2 ** 31) - 1)
208
+ MASK = (2 ** 32) - 1
209
+
210
+ def self.host_to_i32(host)
211
+ unsigned_i32 = Socket.getaddrinfo(host, nil)[0][3].split(".").map do |i|
212
+ i.to_i
213
+ end.inject(0) { |a,e| (a << 8) + e }
214
+
215
+ signed_i32 = if unsigned_i32 > MAX_I32
216
+ -1 * ((unsigned_i32 ^ MASK) + 1)
217
+ else
218
+ unsigned_i32
219
+ end
220
+
221
+ signed_i32
222
+ end
223
+
224
+ def with_port(port)
225
+ Endpoint.new(self.ipv4, port, self.service_name)
226
+ end
227
+
228
+ def with_service_name(service_name)
229
+ Endpoint.new(self.ipv4, self.port, service_name)
230
+ end
231
+
232
+ def to_thrift
233
+ FinagleThrift::Endpoint.new(
234
+ :ipv4 => self.ipv4,
235
+ :port => self.port,
236
+ :service_name => self.service_name
237
+ )
238
+ end
239
+
240
+ def to_s
241
+ "#{service_name}@#{ipv4}:#{port}"
242
+ end
243
+ end
244
+
245
+ end
@@ -0,0 +1,3 @@
1
+ module FinagleThrift
2
+ VERSION = "1.2.0"
3
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: finagle-thrift
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 2
9
+ - 0
10
+ version: 1.2.0
11
+ platform: ruby
12
+ authors:
13
+ - Arya Asemanfar
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-25 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: A Ruby client library for integrating into finagle's thrift tracing protocol
22
+ email:
23
+ - arya@twitter.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/finagle-thrift/client.rb
32
+ - lib/finagle-thrift/thrift/tracing_constants.rb
33
+ - lib/finagle-thrift/thrift/tracing_types.rb
34
+ - lib/finagle-thrift/thrift_client.rb
35
+ - lib/finagle-thrift/trace.rb
36
+ - lib/finagle-thrift/tracer.rb
37
+ - lib/finagle-thrift/version.rb
38
+ - lib/finagle-thrift.rb
39
+ homepage:
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ hash: 3
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 17
62
+ segments:
63
+ - 1
64
+ - 3
65
+ - 5
66
+ version: 1.3.5
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.15
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: ""
74
+ test_files: []
75
+