observability 0.2.0 → 0.3.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: eb2bcfb9c815937bbc46798e8645ccc77e0a7e87dfa5024d327c9e9d4db5a1ff
4
- data.tar.gz: c561389042c72073f21a5e18c06252a36177cd19022e6330c2633f8368953a8f
3
+ metadata.gz: ca1dcfc173024a7ef76eb412bc386cae1e45ccc1844cd79bae98cea45377b110
4
+ data.tar.gz: b3c53287536774ec9d33c3acc63fe10856921cdccdb2485850191924e2ed707c
5
5
  SHA512:
6
- metadata.gz: 4295af2f27a6d6eed728608896ae92fd79736d159c9b2f4c0595b5918708e6b6f63cde95d9824450daa741db481b0ecc7331c842fd43006eb03e704a35b9e603
7
- data.tar.gz: e98b10c101567afa169e55d4b75dffa400d06491ff0320e3c9f01c72d73349ca413655697bb4e69b6493bfa676b2682ff1a48a035f3474de9552e349f9734fbf
6
+ metadata.gz: 81a5b9df54dd9cc7d350a61f186741e0dd74f7651d8c21a527592dcfe10d1463a4c86b332de3351e5bfab44030a431169e2b4c587a1a86de764073f9e517468c
7
+ data.tar.gz: 52002d309d9ee18d8ca6a26d7f02023bfdbd10e5b9ebf6a1959b678a7f4f17878a2f3567ec046a34bd47b0d02221a0cb77e0232ab62b394e7dbd171541dc2629
Binary file
data.tar.gz.sig CHANGED
Binary file
data/History.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ---
4
4
 
5
+ ## v0.3.0 [2020-02-21] Michael Granger <ged@faeriemud.org>
6
+
7
+ Improvements:
8
+
9
+ - Add `requires` to instrumentation, add a PG instrument
10
+ - Add an event ID for cross-application context
11
+ - Update for Ruby 2.7.
12
+
13
+ Bugfixes:
14
+
15
+ - Add a provisional fix for observing arity-0 methods
16
+ - Guard against blockless observe calls
17
+
18
+
5
19
  ## v0.2.0 [2019-10-16] Michael Granger <ged@faeriemud.org>
6
20
 
7
21
  Improvements:
data/README.md CHANGED
@@ -19,7 +19,7 @@ Observability is a toolkit for instrumenting code to make it more observable.
19
19
  It follows the principle of Observability-Oriented Design as expressed by Charity
20
20
  Majors (@mipsytipsy).
21
21
 
22
- Its goals are [stolen from https://charity.wtf/2019/02/05/logs-vs-structured-events/]:
22
+ Its goals are stolen from https://charity.wtf/2019/02/05/logs-vs-structured-events/:
23
23
 
24
24
  * Emit a rich record from the perspective of a single action as the code is
25
25
  executing.
@@ -35,6 +35,8 @@ Its goals are [stolen from https://charity.wtf/2019/02/05/logs-vs-structured-eve
35
35
  system quality, system behavior, outliers, error conditions, etc. You will be
36
36
  absolutely amazed how useful it is … and appalled by what you turn up. 🙂
37
37
 
38
+ [![builds.sr.ht status](https://builds.sr.ht/~ged/Observability.svg)](https://builds.sr.ht/~ged/Observability?)
39
+
38
40
 
39
41
  ## Prerequisites
40
42
 
@@ -52,13 +54,6 @@ You can check out the current development source with Mercurial via its
52
54
  [project page][sourcehut]. Or if you prefer Git, via
53
55
  [its Github mirror][github].
54
56
 
55
- After checking out the source, run:
56
-
57
- $ rake newb
58
-
59
- This task will install any missing dependencies, run the tests/specs,
60
- and generate the API documentation.
61
-
62
57
 
63
58
  ## Author
64
59
 
@@ -67,7 +62,7 @@ and generate the API documentation.
67
62
 
68
63
  ## License
69
64
 
70
- Copyright (c) 2019, Michael Granger
65
+ Copyright (c) 2019-2020, Michael Granger
71
66
  All rights reserved.
72
67
 
73
68
  Redistribution and use in source and binary forms, with or without
@@ -13,11 +13,14 @@ module Observability
13
13
 
14
14
 
15
15
  # Package version
16
- VERSION = '0.2.0'
16
+ VERSION = '0.3.0'
17
17
 
18
18
  # Version control revision
19
19
  REVISION = %q$Revision$
20
20
 
21
+ # The default port to use for network communications
22
+ DEFAULT_PORT = 15775
23
+
21
24
 
22
25
  # Loggability -- Create a logger
23
26
  log_as :observability
@@ -93,13 +96,27 @@ module Observability
93
96
  ### Make a body for a wrapping method for the method with the given +name+ and
94
97
  ### +context+, passing the given +options+.
95
98
  def self::make_wrapped_method( name, context, options, &callback )
96
- return Proc.new do |*m_args, **m_options, &block|
97
- Loggability[ Observability ].debug "Wrapped method %p: %p" %
98
- [ name, context ]
99
- Observability.observer.event( context, **options ) do
100
- # :TODO: Freeze or dup the arguments to prevent accidental modification?
101
- callback.call( *m_args, **m_options, &block ) if callback
102
- super( *m_args, **m_options, &block )
99
+
100
+ # Supering into arity-zero methods with (empty) *args and **options raises an
101
+ # ArgumentError for some reason.
102
+ if context.first.arity.zero?
103
+ return Proc.new do |*m_args, **m_options, &block|
104
+ Loggability[ Observability ].debug "Wrapped zero-arity method %p: %p" %
105
+ [ name, context ]
106
+ Observability.observer.event( context, **options ) do
107
+ callback.call( *m_args, **m_options, &block ) if callback
108
+ super( *m_args, &block )
109
+ end
110
+ end
111
+ else
112
+ return Proc.new do |*m_args, **m_options, &block|
113
+ Loggability[ Observability ].debug "Wrapped method %p: %p" %
114
+ [ name, context ]
115
+ Observability.observer.event( context, **options ) do
116
+ # :TODO: Freeze or dup the arguments to prevent accidental modification?
117
+ callback.call( *m_args, **m_options, &block ) if callback
118
+ super( *m_args, **m_options, &block )
119
+ end
103
120
  end
104
121
  end
105
122
  end
@@ -36,7 +36,7 @@ class Observability::Collector::RabbitMQ < Observability::Collector
36
36
 
37
37
  ##
38
38
  # The port to bind to
39
- setting :port, default: 15775
39
+ setting :port, default: Observability::DEFAULT_PORT
40
40
 
41
41
  ##
42
42
  # The broker_uri to use when connecting to RabbitMQ
@@ -37,7 +37,7 @@ class Observability::Collector::Timescale < Observability::Collector
37
37
 
38
38
  ##
39
39
  # The port to bind to
40
- setting :port, default: 15775
40
+ setting :port, default: Observability::DEFAULT_PORT
41
41
 
42
42
  ##
43
43
  # The URL of the timescale DB to store events in
@@ -106,7 +106,6 @@ class Observability::Collector::Timescale < Observability::Collector
106
106
 
107
107
  ### Read the next event from the socket
108
108
  def read_next_event
109
- self.log.debug "Reading next event."
110
109
  data = @socket.recv_nonblock( MAX_EVENT_BYTES, exception: false )
111
110
 
112
111
  if data == :wait_readable
@@ -123,6 +122,8 @@ class Observability::Collector::Timescale < Observability::Collector
123
122
 
124
123
  ### Store the specified +event+.
125
124
  def store_event( event )
125
+ self.log.debug "Storing event: %p" % [ event ]
126
+
126
127
  time = event.delete('@timestamp')
127
128
  type = event.delete('@type')
128
129
  version = event.delete('@version')
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'time'
5
5
  require 'forwardable'
6
+ require 'uuid'
6
7
  require 'loggability'
7
8
  require 'concurrent'
8
9
 
@@ -22,8 +23,23 @@ class Observability::Event
22
23
  log_to :observability
23
24
 
24
25
 
26
+ ### Return a generator that can return a unique ID string for identifying Events
27
+ ### across application boundaries.
28
+ def self::id_generator
29
+ return @id_generator ||= UUID.new
30
+ end
31
+
32
+
33
+ ### Generate a new Event ID.
34
+ def self::generate_id
35
+ return self.id_generator.generate
36
+ end
37
+
38
+
25
39
  ### Create a new event
26
- def initialize( type, **fields )
40
+ def initialize( type, parent=nil, **fields )
41
+ @id = self.class.generate_id
42
+ @parent_id = parent&.id
27
43
  @type = type.freeze
28
44
  @timestamp = Time.now
29
45
  @start = Concurrent.monotonic_time
@@ -35,6 +51,14 @@ class Observability::Event
35
51
  public
36
52
  ######
37
53
 
54
+ ##
55
+ # The ID of the event, used to pass context through application boundaries
56
+ attr_reader :id
57
+
58
+ ##
59
+ # The ID of the containing context event, if there is one
60
+ attr_reader :parent_id
61
+
38
62
  ##
39
63
  # The type of the event, which should be a string of the form: 'foo.bar.baz'
40
64
  attr_reader :type
@@ -71,6 +95,8 @@ class Observability::Event
71
95
  unless @fields.frozen?
72
96
  self.log.debug "Resolving event %#x" % [ self.object_id ]
73
97
  data = self.fields.merge(
98
+ :@id => self.id,
99
+ :@parent_id => self.parent_id,
74
100
  :@type => self.type,
75
101
  :@timestamp => self.timestamp,
76
102
  :@version => FORMAT_VERSION
@@ -45,6 +45,7 @@ module Observability::Instrumentation
45
45
  mod.extend( Loggability )
46
46
  mod.log_to( :observability )
47
47
  mod.instance_variable_set( :@depends_on, Set.new )
48
+ mod.instance_variable_set( :@requires, Set.new )
48
49
  mod.instance_variable_set( :@installation_callbacks, Set.new )
49
50
  mod.singleton_class.attr_reader( :installation_callbacks )
50
51
  else
@@ -81,11 +82,18 @@ module Observability::Instrumentation
81
82
  ### If they are not present when the instrumentation loads, it will be skipped
82
83
  ### entirely.
83
84
  def depends_on( *modules )
84
- @depends_on.merge( modules.flatten(1) )
85
+ @depends_on.merge( modules.flatten )
85
86
  return @depends_on
86
87
  end
87
88
 
88
89
 
90
+ ### Specified +files+ to require if this instrumentation is loaded.
91
+ def requires( *files )
92
+ @requires.merge( files.flatten )
93
+ return @requires
94
+ end
95
+
96
+
89
97
  ### Register a +callback+ that will be called when instrumentation is installed,
90
98
  ### if and only if all of the given +modules+ are present (may be empty).
91
99
  def when_installed( *modules, &callback )
@@ -101,6 +109,9 @@ module Observability::Instrumentation
101
109
 
102
110
  ### Call installation callbacks which meet their prerequistes.
103
111
  def install
112
+ self.requires.each do |file|
113
+ require( file )
114
+ end
104
115
  self.installation_callbacks.each do |callback, dependencies|
105
116
  missing = dependencies.
106
117
  reject {|mod| Observability::Instrumentation.check_for_module(mod) }
@@ -112,6 +123,8 @@ module Observability::Instrumentation
112
123
  self.log.info "Skipping %p: missing %s" % [ callback, missing.join(', ') ]
113
124
  end
114
125
  end
126
+ rescue LoadError => err
127
+ raise "%p while loading instrumentation"
115
128
  end
116
129
 
117
130
  end # module Observability::Instrumentation
@@ -0,0 +1,39 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'observability/instrumentation' unless defined?( Observability::Instrumentation )
5
+
6
+
7
+ # Instrumentation for the CZTop library
8
+ # Refs:
9
+ # - https://gitlab.com/paddor/cztop
10
+ module Observability::Instrumentation::CZTop
11
+ extend Observability::Instrumentation
12
+
13
+ depends_on 'CZTop'
14
+
15
+
16
+ when_installed( 'CZTop::Socket' ) do
17
+ CZTop::Socket.extend( Observability )
18
+ CZTop::Socket.observe_method( :CURVE_server! )
19
+ CZTop::Socket.observe_method( :CURVE_client! )
20
+ CZTop::Socket.observe_method( :connect )
21
+ CZTop::Socket.observe_method( :disconnect )
22
+ CZTop::Socket.observe_method( :close )
23
+ CZTop::Socket.observe_method( :bind )
24
+ CZTop::Socket.observe_method( :unbind )
25
+ CZTop::Socket.observe_method( :signal )
26
+ CZTop::Socket.observe_method( :wait )
27
+ end
28
+
29
+
30
+ when_installed( 'CZTop::Message' ) do
31
+ CZTop::Message.extend( Observability )
32
+ CZTop::Message.observe_class_method( :receive_from )
33
+ CZTop::Message.observe_method( :send_to )
34
+ CZTop::Message.observe_method( :<< )
35
+ CZTop::Message.observe_method( :routing_id= )
36
+ end
37
+
38
+ end # module Observability::Instrumentation::CZTop
39
+
@@ -0,0 +1,70 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'observability/instrumentation' unless defined?( Observability::Instrumentation )
5
+
6
+
7
+ # Instrumentation for the 'pg' PostgreSQL driver
8
+ # Refs:
9
+ # - https://github.com/ged/ruby-pg
10
+ module Observability::Instrumentation::PG
11
+ extend Observability::Instrumentation
12
+
13
+ depends_on 'PG'
14
+
15
+ requires 'pg_query'
16
+
17
+ when_installed( 'PG::Connection' ) do
18
+ PG::Connection.extend( Observability )
19
+ PG::Connection.observe_class_method( :connect_start )
20
+ PG::Connection.observe_class_method( :ping, timed: true )
21
+ PG::Connection.observe_method( :connect_poll )
22
+ PG::Connection.observe_method( :reset )
23
+ PG::Connection.observe_method( :reset_start )
24
+ PG::Connection.observe_method( :reset_poll )
25
+ PG::Connection.observe_method( :sync_exec )
26
+ PG::Connection.observe_method( :finish )
27
+
28
+ PG::Connection.observe_method( :exec, timed: true, &self.method(:observe_exec) )
29
+ PG::Connection.observe_method( :exec_params, timed: true, &self.method(:observe_exec) )
30
+
31
+ PG::Connection.observe_method( :sync_exec, timed: true, &self.method(:observe_exec) )
32
+ PG::Connection.observe_method( :sync_exec_params, timed: true, &self.method(:observe_exec) )
33
+
34
+ PG::Connection.observe_method( :prepare, timed: true, &self.method(:observe_prepare) )
35
+ PG::Connection.observe_method( :exec_prepared, timed: true, &self.method(:observe_exec_prepared) )
36
+
37
+ PG::Connection.observe_method( :sync_prepare, timed: true, &self.method(:observe_prepare) )
38
+ PG::Connection.observe_method( :sync_exec_prepared, timed: true, &self.method(:observe_exec_prepared) )
39
+ end
40
+
41
+
42
+ ###############
43
+ module_function
44
+ ###############
45
+
46
+ ### Observer callback for the *exec methods.
47
+ def observe_exec( sql, * )
48
+ nsql = PgQuery.normalize( sql )
49
+ Observability.observer.add( query: nsql )
50
+ rescue => err
51
+ Loggability[ Observability ].warn "Couldn't normalize query: %p" % [ sql ]
52
+ end
53
+
54
+
55
+ ### Observer callback for *prepare methods.
56
+ def observe_prepare( name, query, * )
57
+ nsql = PgQuery.normalize( query )
58
+ Observability.observer.add( statement_name: name, query: nsql )
59
+ rescue => err
60
+ Loggability[ Observability ].warn "Couldn't normalize query: %p" % [ sql ]
61
+ end
62
+
63
+
64
+ ### Observer callback for *exec_prepared methods.
65
+ def observe_exec_prepared( name, query, * )
66
+ Observability.observer.add( statement_name: name )
67
+ end
68
+
69
+ end # module Observability::Instrumentation::PG
70
+
@@ -32,6 +32,5 @@ module Observability::Instrumentation::Sequel
32
32
  end
33
33
  end
34
34
 
35
-
36
35
  end # module Observability::Instrumentation::Sequel
37
36
 
@@ -54,7 +54,8 @@ class Observability::Observer
54
54
  type = self.type_from_object( type )
55
55
  fields = self.fields_from_options( options )
56
56
 
57
- event = Observability::Event.new( type, **fields )
57
+ parent = @event_stack.value.last
58
+ event = Observability::Event.new( type, parent, **fields )
58
59
  @event_stack.value.push( event )
59
60
 
60
61
  new_context = @context_stack.value.last&.dup || {}
@@ -11,10 +11,13 @@ module Observability::ObserverHooks
11
11
  ### context, then yield to the method's block. Finish the event when the yield
12
12
  ### returns, handling exceptions that are being raised automatically.
13
13
  def observe( detail, **options, &block )
14
- raise LocalJumpError, "no block given" unless block
15
-
16
- marker = Observability.observer.event( [block, detail], **options )
17
- Observability.observer.finish_after_block( marker, &block )
14
+ if block
15
+ marker = Observability.observer.event( [block, detail], **options )
16
+ Observability.observer.finish_after_block( marker, &block )
17
+ else
18
+ Loggability[ Observability ].warn "No block given for %p -> %p with options: %p" %
19
+ [ self, detail, options ]
20
+ end
18
21
  end
19
22
 
20
23
 
@@ -28,7 +28,7 @@ class Observability::Sender::UDP < Observability::Sender
28
28
 
29
29
  ##
30
30
  # The port to send events to
31
- setting :port, default: 15775
31
+ setting :port, default: Observability::DEFAULT_PORT
32
32
 
33
33
  end
34
34
 
@@ -35,7 +35,7 @@ class Observability::Sender::UdpMulticast < Observability::Sender
35
35
 
36
36
  ##
37
37
  # The port to bind to
38
- setting :port, default: 15775
38
+ setting :port, default: Observability::DEFAULT_PORT
39
39
 
40
40
  end
41
41
 
@@ -35,6 +35,26 @@ describe Observability::Event do
35
35
  end
36
36
 
37
37
 
38
+ it "can be created with a parent event" do
39
+ parent_event = described_class.new( 'acme.server.request', score: 100, time: 48 )
40
+ child_event = described_class.new( 'acme.user.created', parent_event )
41
+
42
+ expect( child_event.parent_id ).to eq( parent_event.id )
43
+ end
44
+
45
+
46
+ it "is created with a unique ID" do
47
+ event1 = described_class.new( 'acme.server.request' )
48
+ event2 = described_class.new( 'acme.server.request' )
49
+
50
+ expect( event1.id ).to be_a( String )
51
+ expect( event1.id.length ).to be > 16
52
+ expect( event2.id ).to be_a( String )
53
+ expect( event2.id.length ).to be == event1.id.length
54
+ expect( event2.id ).to_not eq( event1.id )
55
+ end
56
+
57
+
38
58
  it "returns a structured log entry when resolved" do
39
59
  event = described_class.new( 'acme.user.review', score: 100, time: 48 )
40
60
  expect( event.resolve ).to be_a( Hash ).and( include(score: 100, time: 48) )
@@ -99,7 +119,7 @@ describe Observability::Event do
99
119
 
100
120
  sleep 0.25
101
121
 
102
- expect( event.resolve[:duration] ).to be_within( 0.01 ).of( 0.25 )
122
+ expect( event.resolve[:duration] ).to be_a( Float ).and( be > 0.25 )
103
123
  end
104
124
 
105
125
  end
@@ -34,7 +34,7 @@ describe Observability::Sender::UDP do
34
34
  block.call( *args )
35
35
  end
36
36
  expect( udp_socket ).to receive( :connect ).with( 'localhost', 8787 )
37
- expect( udp_socket ).to receive( :sendmsg_nonblock ) do |msg, flags, **opts|
37
+ expect( udp_socket ).to receive( :sendmsg_nonblock ) do |msg, flags, opts={}|
38
38
  expect( msg ).to match( /\{.*"@type":"acme\.engine\.startup".*\}/ )
39
39
  expect( flags ).to eq( 0 )
40
40
  expect( opts ).to include( exception: false )
@@ -55,7 +55,7 @@ describe Observability::Sender::UDP do
55
55
  block.call( *args )
56
56
  end
57
57
  expect( udp_socket ).to receive( :connect ).with( 'localhost', 8787 )
58
- expect( udp_socket ).to receive( :sendmsg_nonblock ) do |msg, flags, **opts|
58
+ expect( udp_socket ).to receive( :sendmsg_nonblock ) do |msg, flags, opts={}|
59
59
  if !blocked_once
60
60
  blocked_once = true
61
61
  :wait_writable
@@ -147,6 +147,8 @@ RSpec.configure do |config|
147
147
  config.mock_with( :rspec ) do |mock|
148
148
  mock.syntax = :expect
149
149
  end
150
+ config.warnings = true
151
+ config.profile_examples = 5
150
152
 
151
153
  config.include( Loggability::SpecHelpers )
152
154
  config.include( Observability::SpecHelpers )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: observability
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -34,7 +34,7 @@ cert_chain:
34
34
  jBZSA+N+xUTgUWpXjjwsLZjzJkhWATJWq+krNXcqpwXo6HsjmdUxoFMt63RBb+sI
35
35
  XrxOxp8o0uOkU7FdLSGsyqJ2LzsR4obN
36
36
  -----END CERTIFICATE-----
37
- date: 2019-10-17 00:00:00.000000000 Z
37
+ date: 2020-02-21 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: concurrent-ruby
@@ -70,42 +70,42 @@ dependencies:
70
70
  requirements:
71
71
  - - "~>"
72
72
  - !ruby/object:Gem::Version
73
- version: '0.11'
73
+ version: '0.15'
74
74
  type: :runtime
75
75
  prerelease: false
76
76
  version_requirements: !ruby/object:Gem::Requirement
77
77
  requirements:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
- version: '0.11'
80
+ version: '0.15'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: configurability
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: '3.3'
87
+ version: '4.0'
88
88
  type: :runtime
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: '3.3'
94
+ version: '4.0'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: pluggability
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
99
  - - "~>"
100
100
  - !ruby/object:Gem::Version
101
- version: '0.6'
101
+ version: '0.7'
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
- version: '0.6'
108
+ version: '0.7'
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: msgpack
111
111
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +120,48 @@ dependencies:
120
120
  - - "~>"
121
121
  - !ruby/object:Gem::Version
122
122
  version: '1.3'
123
+ - !ruby/object:Gem::Dependency
124
+ name: uuid
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '2.3'
130
+ type: :runtime
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '2.3'
137
+ - !ruby/object:Gem::Dependency
138
+ name: pg
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '1.1'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '1.1'
151
+ - !ruby/object:Gem::Dependency
152
+ name: sequel
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '5.26'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '5.26'
123
165
  - !ruby/object:Gem::Dependency
124
166
  name: timecop
125
167
  requirement: !ruby/object:Gem::Requirement
@@ -140,14 +182,14 @@ dependencies:
140
182
  requirements:
141
183
  - - "~>"
142
184
  - !ruby/object:Gem::Version
143
- version: '0.4'
185
+ version: '0.10'
144
186
  type: :development
145
187
  prerelease: false
146
188
  version_requirements: !ruby/object:Gem::Requirement
147
189
  requirements:
148
190
  - - "~>"
149
191
  - !ruby/object:Gem::Version
150
- version: '0.4'
192
+ version: '0.10'
151
193
  - !ruby/object:Gem::Dependency
152
194
  name: simplecov
153
195
  requirement: !ruby/object:Gem::Requirement
@@ -182,7 +224,8 @@ description: |-
182
224
  Majors (@mipsytipsy).
183
225
  email:
184
226
  - ged@faeriemud.org
185
- executables: []
227
+ executables:
228
+ - observability-collector
186
229
  extensions: []
187
230
  extra_rdoc_files: []
188
231
  files:
@@ -198,7 +241,9 @@ files:
198
241
  - lib/observability/event.rb
199
242
  - lib/observability/instrumentation.rb
200
243
  - lib/observability/instrumentation/bunny.rb
244
+ - lib/observability/instrumentation/cztop.rb
201
245
  - lib/observability/instrumentation/grape.rb
246
+ - lib/observability/instrumentation/pg.rb
202
247
  - lib/observability/instrumentation/rack.rb
203
248
  - lib/observability/instrumentation/sequel.rb
204
249
  - lib/observability/observer.rb
@@ -237,7 +282,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
282
  - !ruby/object:Gem::Version
238
283
  version: '0'
239
284
  requirements: []
240
- rubygems_version: 3.0.3
285
+ rubygems_version: 3.1.2
241
286
  signing_key:
242
287
  specification_version: 4
243
288
  summary: Observability is a toolkit for instrumenting code to make it more observable.
metadata.gz.sig CHANGED
Binary file