appdash 0.6.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 832463798ecc366655cfe139b52dfdab61e4ad14
4
+ data.tar.gz: f5b7db5b952464cfe30f1aa93c673bb4252d2a9d
5
+ SHA512:
6
+ metadata.gz: 87131161bf4489115b1b559e342180e4538e9e48363e314ff9e947b393ccf8592bff625a7022d168ba7fb94f19f2786eb52451d63b4b01734f95aa192f41aee9
7
+ data.tar.gz: 04963a82c52bedb5fbd7a5b93feca849c0494b95b98e9a5264126ad2529339110b0eddc73622c9db5b33aeb12c0d483f1d342cb7c905e6772583c86e27eb1f2d
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ appdash (0.6.0)
5
+ protobuf
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activesupport (4.2.5)
11
+ i18n (~> 0.7)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.3, >= 0.3.4)
15
+ tzinfo (~> 1.1)
16
+ diff-lcs (1.2.5)
17
+ i18n (0.7.0)
18
+ json (1.8.3)
19
+ middleware (0.1.0)
20
+ minitest (5.8.3)
21
+ protobuf (3.5.5)
22
+ activesupport (>= 3.2)
23
+ middleware
24
+ thor
25
+ thread_safe
26
+ rack (1.6.4)
27
+ rake (10.4.2)
28
+ rspec (3.4.0)
29
+ rspec-core (~> 3.4.0)
30
+ rspec-expectations (~> 3.4.0)
31
+ rspec-mocks (~> 3.4.0)
32
+ rspec-core (3.4.1)
33
+ rspec-support (~> 3.4.0)
34
+ rspec-expectations (3.4.0)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.4.0)
37
+ rspec-mocks (3.4.0)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.4.0)
40
+ rspec-support (3.4.1)
41
+ thor (0.19.1)
42
+ thread_safe (0.3.5)
43
+ tzinfo (1.2.2)
44
+ thread_safe (~> 0.1)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ appdash!
51
+ bundler
52
+ rack
53
+ rake
54
+ rspec
55
+
56
+ BUNDLED WITH
57
+ 1.10.6
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Black Square Media
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ Ruby Appdash
2
+ ============
3
+
4
+ [Appdash](https://github.com/sourcegraph/appdash) client for Ruby.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'appdash'
11
+
12
+ Or install:
13
+
14
+ $ gem install appdash
15
+
16
+ Connect to an instance:
17
+
18
+ client = Appdash::Client.new host: "remote.host", port: 7701, max_buffer_size: 20
19
+
20
+ Collect spans:
21
+
22
+ client.span do |s|
23
+ s.name "Request"
24
+ s.log "a log entry with a timestamp"
25
+ end
26
+
27
+ For full options and event types, please see the [Documentation](http://www.rubydoc.info/gems/appdash).
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Make a pull request
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'bundler/gem_tasks'
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ task default: :spec
9
+
10
+ namespace :protobuf do
11
+ PROTO_ROOT = "./defs/appdash"
12
+
13
+ task :fetch do
14
+ target = "#{PROTO_ROOT}/collector.proto"
15
+ sh %(mkdir -p #{PROTO_ROOT})
16
+ sh %(curl -sSL https://raw.githubusercontent.com/sourcegraph/appdash/master/internal/wire/collector.proto | sed 's/package wire/package appdash/' > #{target})
17
+ end
18
+
19
+ task :compile do
20
+ Dir[PROTO_ROOT+"/**/*.proto"].each do |file|
21
+ sh "PB_NO_TAG_WARNINGS=1 protoc -I ./defs --ruby_out ./lib #{file}"
22
+ end
23
+ end
24
+
25
+ desc "Rebuild protobuf definitions"
26
+ task rebuild: [:fetch, :compile]
27
+
28
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "appdash"
5
+ s.version = "0.6.0"
6
+ s.authors = ["Black Square Media"]
7
+ s.email = ["dimitrij@blacksquaremedia.com"]
8
+ s.summary = %q{Appdash client for ruby}
9
+ s.description = %q{Ruby client for Appdash, Sourcegraph's application tracing system, based on Google's Dapper}
10
+ s.homepage = "https://github.com/bsm/appdash-rb"
11
+ s.required_ruby_version = '>= 1.9.0'
12
+
13
+ s.files = `git ls-files`.split($/)
14
+ s.test_files = s.files.grep(%r{^(spec)/})
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency(%q<protobuf>)
18
+
19
+ s.add_development_dependency(%q<rake>)
20
+ s.add_development_dependency(%q<rack>)
21
+ s.add_development_dependency(%q<bundler>)
22
+ s.add_development_dependency(%q<rspec>)
23
+ end
@@ -0,0 +1,30 @@
1
+ package appdash;
2
+
3
+ // CollectPacket is the message sent to a remote collector server by one of
4
+ // it's clients.
5
+ message CollectPacket {
6
+ // SpanID is the group of information which can uniquely identify the exact
7
+ // span being collected.
8
+ required group SpanID = 1 {
9
+ // trace is the root ID of the tree that contains all of the spans
10
+ // related to this one.
11
+ required fixed64 trace = 2;
12
+
13
+ // span is an ID that probabilistically uniquely identifies this span.
14
+ required fixed64 span = 3;
15
+
16
+ // parent is the ID of the parent span, if any.
17
+ optional fixed64 parent = 4;
18
+ }
19
+
20
+ // Annotation is any number of annotations for the span to be collected.
21
+ repeated group Annotation = 5 {
22
+ // key is the annotation's key.
23
+ required string key = 6;
24
+
25
+ // value is the annotation's value, which may be either human or
26
+ // machine readable, depending on the schema of the event that
27
+ // generated it.
28
+ optional bytes value = 7;
29
+ }
30
+ }
@@ -0,0 +1,4 @@
1
+ require 'appdash/wire'
2
+ require 'appdash/span'
3
+ require 'appdash/events'
4
+ require 'appdash/client'
@@ -0,0 +1,77 @@
1
+ require 'socket'
2
+ require 'thread'
3
+
4
+ module Appdash
5
+ class Client
6
+
7
+ # Client defaults
8
+ DEFAULTS = {
9
+ host: 'localhost',
10
+ port: 7701,
11
+ max_buffer_size: 1,
12
+ }.freeze
13
+
14
+ # Initializes a new client
15
+ # @param [Hash] opts
16
+ # @option opts [String] :host the hostname, defaults to localhost
17
+ # @option opts [Integer] :port the port, defaults to 7701
18
+ # @option opts [Integer] :max_buffer_size number of spans in the buffer before flushing, defaults to 1 (= no buffering)
19
+ def initialize(opts = {})
20
+ @config = DEFAULTS.merge(opts)
21
+ @sock = TCPSocket.new @config[:host], @config[:port]
22
+ @buffer = []
23
+ @mutex = Mutex.new
24
+ end
25
+
26
+ # Traces a new span with a series of associated events. Accepts an optional block. If no block is given you must flush
27
+ # to send data to the collector.
28
+ #
29
+ # @example manual flush
30
+ #
31
+ # span = client.span
32
+ # span.name "Request"
33
+ # span.message "A simple message"
34
+ # span.flush
35
+ #
36
+ # @example with block
37
+ #
38
+ # client.span do |span|
39
+ # span.name "Request"
40
+ # span.message "A simple message"
41
+ # end
42
+ def span(&block)
43
+ span = Appdash::Span.new(self)
44
+ return span unless block
45
+
46
+ begin
47
+ block.call(span)
48
+ ensure
49
+ span.flush
50
+ end
51
+ end
52
+
53
+ # Shutdown flushes any remaining buffered packets and closes the connection
54
+ def shutdown
55
+ flush_buffer!
56
+ @sock.shutdown
57
+ end
58
+
59
+ private
60
+
61
+ def write(packets)
62
+ packets.each do |packet|
63
+ raw = Protobuf::Field::VarintField.encode(packet.bytesize)+packet
64
+ @buffer.push(raw)
65
+ end
66
+ flush_buffer! unless @buffer.size < @config[:max_buffer_size]
67
+ end
68
+
69
+ def flush_buffer!
70
+ @mutex.synchronize do
71
+ @sock.write @buffer.join("\n") unless @buffer.empty?
72
+ @buffer.clear
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # This file is auto-generated. DO NOT EDIT!
5
+ #
6
+ require 'protobuf/message'
7
+
8
+ module Appdash
9
+
10
+ ##
11
+ # Message Classes
12
+ #
13
+ class CollectPacket < ::Protobuf::Message
14
+ class SpanID < ::Protobuf::Message; end
15
+ class Annotation < ::Protobuf::Message; end
16
+
17
+ end
18
+
19
+
20
+
21
+ ##
22
+ # Message Fields
23
+ #
24
+ class CollectPacket
25
+ class SpanID
26
+ required :fixed64, :trace, 2
27
+ required :fixed64, :span, 3
28
+ optional :fixed64, :parent, 4
29
+ end
30
+
31
+ class Annotation
32
+ required :string, :key, 6
33
+ optional :bytes, :value, 7
34
+ end
35
+
36
+ required ::Appdash::CollectPacket::SpanID, :spanid, 1
37
+ repeated ::Appdash::CollectPacket::Annotation, :annotation, 5
38
+ end
39
+
40
+ end
41
+
@@ -0,0 +1,62 @@
1
+ require 'appdash/wire'
2
+
3
+ module Appdash
4
+ module Event
5
+
6
+ # Base forms the most basic event type
7
+ class Base
8
+
9
+ attr_reader :schema, :attrs
10
+
11
+ # @param [String] schema the event schema name
12
+ # @param [Hash] attrs event attributes
13
+ def initialize(schema, attrs = {})
14
+ super()
15
+ @schema = schema
16
+ @attrs = attrs
17
+ end
18
+
19
+ # @return [Array<Appdash::CollectPacket::Annotation>] marshalable annotations
20
+ def to_a
21
+ annotate(attrs) + [annotation(['_schema', schema].join(':'))]
22
+ end
23
+
24
+ protected
25
+
26
+ def annotate(hash, prefix = nil)
27
+ hash.map do |key, value|
28
+ key = [prefix, normalize(key)].compact.join('.')
29
+
30
+ case value
31
+ when Hash
32
+ annotate(value, key)
33
+ else
34
+ annotation(key, value)
35
+ end
36
+ end.flatten
37
+ end
38
+
39
+ def annotation(key, value = nil)
40
+ case value
41
+ when DateTime, Time
42
+ value = value.strftime('%FT%T%:z')
43
+ when NilClass
44
+ # ignore
45
+ else
46
+ value = value.to_s
47
+ end
48
+ Appdash::CollectPacket::Annotation.new(key: key, value: value)
49
+ end
50
+
51
+ def normalize(key)
52
+ key = key.to_s
53
+ key = key.sub(/^[a-z\d]*/) { Appdash::Event.acronyms[$&] || $&.capitalize }
54
+ key.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{Appdash::Event.acronyms[$2] || $2.capitalize}" }
55
+
56
+ key[0] = key[0].upcase if key.size > 0
57
+ key
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,17 @@
1
+ require 'appdash/event/base'
2
+ require 'time'
3
+
4
+ module Appdash
5
+ module Event
6
+
7
+ # Log is an event whose timestamp is the current time and contains the given human-readable log message.
8
+ class Log < Base
9
+
10
+ # @param [String] msg the log message
11
+ def initialize(msg)
12
+ super("log", msg: msg, time: Time.now)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ require 'appdash/event/base'
2
+
3
+ module Appdash
4
+ module Event
5
+
6
+ # Message is an event that contains only a human-readable message.
7
+ class Message < Base
8
+
9
+ # @param [String] msg the message
10
+ def initialize(msg)
11
+ super("msg", msg: msg)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ require 'appdash/event/base'
2
+
3
+ module Appdash
4
+ module Event
5
+
6
+ # RackServer represents a HTTP event where a client's request was served via Rack.
7
+ class RackServer < Appdash::Event::Base
8
+
9
+ # @param [Rack::Request] req a Rack request object
10
+ # @param [Rack::Response] resp an optional Rack response object
11
+ # @param [Hash] attrs additional attributes, e.g. :user or :route
12
+ def initialize(req, resp = nil, attrs = {})
13
+ server = attrs.dup
14
+ server[:send] ||= Time.now
15
+ server[:request] ||= {}
16
+ server[:request].update parse_request(req)
17
+ if resp
18
+ server[:response] ||= {}
19
+ server[:response].update parse_response(resp)
20
+ end
21
+
22
+ super("HTTPServer", server: server)
23
+ end
24
+
25
+ protected
26
+
27
+ def parse_request(req)
28
+ data = {
29
+ method: req.request_method,
30
+ url: req.url,
31
+ scheme: req.scheme,
32
+ host: req.host,
33
+ remote_ip: req.ip,
34
+ content_length: req.content_length
35
+ }
36
+
37
+ [:content_type, :user_agent].each do |name|
38
+ value = req.send(name)
39
+ data[name] = value if value
40
+ end
41
+
42
+ data
43
+ end
44
+
45
+ def parse_response(resp)
46
+ {
47
+ content_length: resp.length,
48
+ status_code: resp.status
49
+ }
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,16 @@
1
+ require 'appdash/event/base'
2
+
3
+ module Appdash
4
+ module Event
5
+
6
+ # SpanName is an event which sets a span's name.
7
+ class SpanName < Base
8
+
9
+ # @param [String] name the event span name
10
+ def initialize(name)
11
+ super("name", name: name)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'appdash/event/base'
2
+ require 'appdash/event/span_name'
3
+ require 'appdash/event/message'
4
+ require 'appdash/event/log'
5
+ require 'appdash/event/rack_server'
6
+
7
+ module Appdash
8
+ module Event
9
+
10
+ # @return [Hash] known acronyms for attribute translations
11
+ def self.acronyms
12
+ @acronyms ||= {
13
+ "url" => "URL",
14
+ "uri" => "URI",
15
+ "id" => "ID",
16
+ "ip" => "IP",
17
+ }
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ require 'appdash/span/id'
2
+
3
+ module Appdash
4
+ class Span
5
+
6
+ # @attr_reader :root_id returns the root span ID
7
+ attr_reader :root_id
8
+
9
+ # @attr_reader :id returns the current span ID
10
+ attr_reader :id
11
+
12
+ def initialize(client)
13
+ @client = client
14
+ @packets = []
15
+ @root_id = Appdash::Span::ID.new
16
+ @id = root_id
17
+ end
18
+
19
+ # Appends a new Appdash::Event::SpanName event
20
+ def name(val)
21
+ event Appdash::Event::SpanName.new(val)
22
+ end
23
+
24
+ # Appends a new Appdash::Event::Message event
25
+ def message(msg)
26
+ event Appdash::Event::Message.new(msg)
27
+ end
28
+
29
+ # Appends a new Appdash::Event::Log event
30
+ def log(msg)
31
+ event Appdash::Event::Log.new(msg)
32
+ end
33
+
34
+ # Appends a generic Appdash::Event event
35
+ def event(evt)
36
+ @packets.push Appdash::CollectPacket.encode(evt, @id)
37
+ @id = @id.child
38
+ end
39
+
40
+ def flush
41
+ count = @packets.size
42
+ @client.send :write, @packets
43
+ @packets.clear
44
+ count
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,44 @@
1
+ require 'securerandom'
2
+
3
+ module Appdash
4
+ class Span
5
+
6
+ class ID
7
+ # @attr_reader [Integer] root ID of the tree that contains all of the spans related to this one.
8
+ attr_reader :trace
9
+
10
+ # @attr_reader [Integer] an ID that probabilistically uniquely identifies this span.
11
+ attr_reader :span
12
+
13
+ # @attr_reader [Integer] the ID of the parent span, if any.
14
+ attr_reader :parent
15
+
16
+ # Creates a new root span
17
+ # @param [Appdash::SpanID] parent, optional parent
18
+ def initialize(parent = nil)
19
+ @trace = parent ? parent.trace : random_uint64
20
+ @span = random_uint64
21
+ @parent = parent.span if parent
22
+ end
23
+
24
+ # @return [Appdash::SpanID] creates a child span
25
+ def child
26
+ self.class.new(self)
27
+ end
28
+
29
+ # @return [String] string ID
30
+ def to_s
31
+ [trace, span, parent].compact.map do |num|
32
+ num.to_s(16).rjust(16, '0')
33
+ end.join("/")
34
+ end
35
+
36
+ private
37
+
38
+ def random_uint64
39
+ SecureRandom.random_bytes(8).unpack("Q")[0]
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,13 @@
1
+ require 'protobuf'
2
+ require 'appdash/collector.pb.rb'
3
+
4
+ module Appdash
5
+ class CollectPacket
6
+
7
+ def self.encode(event, id)
8
+ wired = SpanID.new(trace: id.trace, span: id.span, parent: id.parent)
9
+ new(spanid: wired, annotation: event.to_a).encode
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Client do
4
+
5
+ let(:mock_socket) { double("TCPSocket", shutdown: nil) }
6
+ before { allow(TCPSocket).to receive(:new).and_return(mock_socket) }
7
+
8
+ it "should collect spans" do
9
+ span = subject.span
10
+ span.event(Appdash::Event::Message.new("Hello world!"))
11
+
12
+ expect(mock_socket).to receive(:write) do |raw|
13
+ expect(raw.bytesize).to eq(57)
14
+ expect(raw.bytes.first).to eq(56)
15
+ end.and_return(57)
16
+ span.flush
17
+ end
18
+
19
+ it "should support buffering" do
20
+ subject = described_class.new(max_buffer_size: 3)
21
+ subject.span do |s|
22
+ s.message("Message A")
23
+ s.message("Message B")
24
+ end
25
+
26
+ expect(mock_socket).to receive(:write) do |raw|
27
+ expect(raw.bytesize).to eq(118)
28
+ end
29
+ subject.shutdown
30
+ end
31
+
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Event::Base do
4
+
5
+ subject { described_class.new 'test', name: "Query", some_other: 2, sub: { req_url: "http://example.com/path", nest: { v: Time.utc(2015) }}}
6
+
7
+ it "should init" do
8
+ expect(subject.schema).to eq("test")
9
+ expect(subject.attrs.size).to eq(3)
10
+ end
11
+
12
+ it "should annotate" do
13
+ expect(atoh(subject.to_a)).to eq(
14
+ "Name" => "Query",
15
+ "SomeOther" => "2",
16
+ "Sub.ReqURL" => "http://example.com/path",
17
+ "Sub.Nest.V"=>"2015-01-01T00:00:00+00:00",
18
+ "_schema:test"=>"",
19
+ )
20
+ end
21
+
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Event::Log do
4
+
5
+ let(:time) { Time.utc(2001,2,3,4,5,6) }
6
+ before { allow(Time).to receive(:now).and_return(time) }
7
+ subject { described_class.new "Hi" }
8
+
9
+ it "should init" do
10
+ expect(subject.schema).to eq("log")
11
+ expect(subject.attrs).to eq(msg: "Hi", time: time)
12
+ end
13
+
14
+ it "should annotate" do
15
+ expect(atoh(subject.to_a)).to eq(
16
+ "Msg" => "Hi",
17
+ "Time" => "2001-02-03T04:05:06+00:00",
18
+ "_schema:log" => "",
19
+ )
20
+ end
21
+
22
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Event::Message do
4
+
5
+ subject { described_class.new "Hi" }
6
+
7
+ it "should init" do
8
+ expect(subject.schema).to eq("msg")
9
+ expect(subject.attrs).to eq(msg: "Hi")
10
+ end
11
+
12
+ it "should annotate" do
13
+ expect(atoh(subject.to_a)).to eq("Msg"=>"Hi", "_schema:msg"=>"")
14
+ end
15
+
16
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Event::RackServer do
4
+
5
+ let(:time) { Time.utc(2001,2,3,4,5,6) }
6
+ let(:response) { Rack::Response.new([], 201, 'Content-Length' => 33) }
7
+ let(:request) do
8
+ env = Rack::MockRequest.env_for("http://example.com:8080/", "REMOTE_ADDR" => "10.10.10.10", 'CONTENT_LENGTH' => 12, 'HTTP_USER_AGENT' => 'Test/1.0')
9
+ Rack::Request.new(env)
10
+ end
11
+
12
+ before { allow(Time).to receive(:now).and_return(time) }
13
+ subject { described_class.new request, response, route: 'createPost' }
14
+
15
+ it "should init" do
16
+ expect(subject.schema).to eq("HTTPServer")
17
+ expect(subject.attrs.size).to eq(1)
18
+ end
19
+
20
+ it "should annotate" do
21
+ expect(atoh(subject.to_a)).to eq(
22
+ "Server.Request.ContentLength" => "12",
23
+ "Server.Request.Host" => "example.com",
24
+ "Server.Request.Method" => "GET",
25
+ "Server.Request.Scheme" => "http",
26
+ "Server.Request.RemoteIP" => "10.10.10.10",
27
+ "Server.Request.URL" => "http://example.com:8080/",
28
+ "Server.Request.UserAgent" => "Test/1.0",
29
+ "Server.Response.ContentLength" => "0",
30
+ "Server.Response.StatusCode" => "201",
31
+ "Server.Route" => "createPost",
32
+ "Server.Send" => "2001-02-03T04:05:06+00:00",
33
+ "_schema:HTTPServer" => "",
34
+ )
35
+ end
36
+
37
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Event::SpanName do
4
+
5
+ subject { described_class.new "Query" }
6
+
7
+ it "should init" do
8
+ expect(subject.schema).to eq("name")
9
+ expect(subject.attrs).to eq(name: "Query")
10
+ end
11
+
12
+ it "should annotate" do
13
+ expect(atoh(subject.to_a)).to eq("Name" => "Query", "_schema:name" => "")
14
+ end
15
+
16
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Span::ID do
4
+
5
+ before do
6
+ allow(SecureRandom).to receive(:random_bytes).with(8).
7
+ and_return("A~CDEF~H", "xyz\x00\x00\x00\x00\x00", "^&<>^*%!", "2531afas", "*&^%$-[]")
8
+ end
9
+
10
+ it "should create instances" do
11
+ expect(subject.trace).to eq(5223689881108315713)
12
+ expect(subject.span).to eq(8026488)
13
+ expect(subject.parent).to be_nil
14
+ expect(subject.to_s).to eq("487e464544437e41/00000000007a7978")
15
+ end
16
+
17
+ it "should create children" do
18
+ child = subject.child
19
+ expect(child.trace).to eq(5223689881108315713)
20
+ expect(child.span).to eq(2388361761649337950)
21
+ expect(child.parent).to eq(8026488)
22
+ expect(child.to_s).to eq("487e464544437e41/21252a5e3e3c265e/00000000007a7978")
23
+ end
24
+
25
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::Span do
4
+
5
+ let(:mock_client) { double("Client", write: nil) }
6
+ subject { described_class.new mock_client }
7
+
8
+ it "should append events" do
9
+ expect(subject.id).to eq(subject.root_id)
10
+ subject.name("test")
11
+ expect(subject.id).not_to eq(subject.root_id)
12
+ expect(subject.id.to_s.size).to eq(50)
13
+
14
+ subject.message("test message")
15
+ subject.log("test log")
16
+ expect(subject.instance_variable_get(:@packets).size).to eq(3)
17
+ end
18
+
19
+ it "should flush" do
20
+ expect(subject.flush).to eq(0)
21
+
22
+ subject.name("test")
23
+ subject.message("test message")
24
+
25
+ expect(mock_client).to receive(:write) do |packets|
26
+ expect(packets.size).to eq(2)
27
+ expect(packets[0].bytesize).to eq(50)
28
+ expect(packets[1].bytesize).to eq(65)
29
+ end
30
+ expect(subject.flush).to eq(2)
31
+ end
32
+
33
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Appdash::CollectPacket do
4
+
5
+ it "should encode" do
6
+ packet = described_class.encode Appdash::Event::Message.new("Hello world!"), Appdash::Span::ID.new
7
+ expect(packet.bytesize).to eq(56)
8
+ end
9
+
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'rspec'
2
+ require 'rack'
3
+ require 'appdash'
4
+
5
+ helpers = Module.new do
6
+
7
+ def atoh(annotations)
8
+ annotations.inject({}) {|h, a| h[a.key] = a.value; h }
9
+ end
10
+
11
+ end
12
+
13
+ RSpec.configure do |c|
14
+ c.include helpers
15
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appdash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Black Square Media
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: protobuf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: rake
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
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Ruby client for Appdash, Sourcegraph's application tracing system, based
84
+ on Google's Dapper
85
+ email:
86
+ - dimitrij@blacksquaremedia.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".editorconfig"
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - MIT-LICENCE
95
+ - README.md
96
+ - Rakefile
97
+ - appdash.gemspec
98
+ - defs/appdash/collector.proto
99
+ - lib/appdash.rb
100
+ - lib/appdash/client.rb
101
+ - lib/appdash/collector.pb.rb
102
+ - lib/appdash/event/base.rb
103
+ - lib/appdash/event/log.rb
104
+ - lib/appdash/event/message.rb
105
+ - lib/appdash/event/rack_server.rb
106
+ - lib/appdash/event/span_name.rb
107
+ - lib/appdash/events.rb
108
+ - lib/appdash/span.rb
109
+ - lib/appdash/span/id.rb
110
+ - lib/appdash/wire.rb
111
+ - spec/appdash/client_spec.rb
112
+ - spec/appdash/event/base_spec.rb
113
+ - spec/appdash/event/log_spec.rb
114
+ - spec/appdash/event/message_spec.rb
115
+ - spec/appdash/event/rack_server_spec.rb
116
+ - spec/appdash/event/span_name_spec.rb
117
+ - spec/appdash/span/id_spec.rb
118
+ - spec/appdash/span_spec.rb
119
+ - spec/appdash/wire_spec.rb
120
+ - spec/spec_helper.rb
121
+ homepage: https://github.com/bsm/appdash-rb
122
+ licenses: []
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 1.9.0
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.4.8
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Appdash client for ruby
144
+ test_files:
145
+ - spec/appdash/client_spec.rb
146
+ - spec/appdash/event/base_spec.rb
147
+ - spec/appdash/event/log_spec.rb
148
+ - spec/appdash/event/message_spec.rb
149
+ - spec/appdash/event/rack_server_spec.rb
150
+ - spec/appdash/event/span_name_spec.rb
151
+ - spec/appdash/span/id_spec.rb
152
+ - spec/appdash/span_spec.rb
153
+ - spec/appdash/wire_spec.rb
154
+ - spec/spec_helper.rb