ntl-raygun_client 0.5.0.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
+ SHA256:
3
+ metadata.gz: 143aaa9c05da3e2f365d2f179b79e475dd967e5bf34ed633c10044011a1647f6
4
+ data.tar.gz: 4339ee7260be75a35c6b73607820514e884db0247caecd7a93402b4804fe9fa6
5
+ SHA512:
6
+ metadata.gz: 30f1ac230de5b055707589084d6bdc4e9f3fb2e93844b7e711f9a7d7584103a91703e3da344ba11dba77036c8a69f6316f15f61cbb93d6c8fa8d4da9f8aa44f8
7
+ data.tar.gz: 1d42c2469948e2e64b2a19ec327f4a1908042e5c0805db856230e6b5c29f390d5d50aa07ab29ab00ec7a758e79499b90334041bde77ee54d43e34cff202ea255
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ require 'configure'
5
+ require 'error_data'
6
+ require 'telemetry'
7
+ require 'settings'
8
+
9
+ require 'raygun_client/client_info'
10
+ require 'raygun_client/data/client_info'
11
+ require 'raygun_client/data'
12
+ require 'raygun_client/settings'
13
+ require 'raygun_client/http/post'
@@ -0,0 +1,15 @@
1
+ module RaygunClient
2
+ module ClientInfo
3
+ def self.name
4
+ 'Raygun Client'
5
+ end
6
+
7
+ def self.version
8
+ '1'
9
+ end
10
+
11
+ def self.url
12
+ 'https://github.com/ntl/raygun-client'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'securerandom'
2
+ require 'clock/controls'
3
+
4
+ require 'error_data/controls'
5
+
6
+ require 'raygun_client/controls/random'
7
+ require 'raygun_client/controls/time'
8
+
9
+ require 'raygun_client/controls/error'
10
+ require 'raygun_client/controls/data'
11
+ require 'raygun_client/controls/error_data'
@@ -0,0 +1,127 @@
1
+ module RaygunClient
2
+ module Controls
3
+ module Data
4
+ def self.example(custom_data=nil, tags=nil, time: nil)
5
+ custom_data ||= self.custom_data
6
+ tags ||= self.tags
7
+ time ||= self.time
8
+
9
+ data = RaygunClient::Data.build
10
+
11
+ data.occurred_time = time
12
+ data.machine_name = machine_name
13
+ data.tags = tags
14
+ data.custom_data = custom_data
15
+
16
+ data.client = RaygunClient::Data::ClientInfo.build
17
+
18
+ data.error = Controls::ErrorData.example
19
+
20
+ data
21
+ end
22
+
23
+ def self.time
24
+ ::Controls::Time.example
25
+ end
26
+
27
+ def self.machine_name
28
+ 'some machine name'
29
+ end
30
+
31
+ def self.tags
32
+ ['some-tag']
33
+ end
34
+
35
+ def self.custom_data
36
+ { 'someKey' => 'some value' }
37
+ end
38
+
39
+ module JSON
40
+ def self.text
41
+ ::JSON.generate(data)
42
+ end
43
+
44
+ def self.data
45
+ reference_time = Controls::Data.time
46
+
47
+ {
48
+ 'occurredOn' => reference_time,
49
+ 'details' => {
50
+ 'machineName' => Controls::Data.machine_name,
51
+ 'client' => Client.data,
52
+ 'error' => Error.data,
53
+ 'tags' => Controls::Data.tags,
54
+ 'userCustomData' => Controls::Data.custom_data
55
+ }
56
+ }
57
+ end
58
+
59
+ module Client
60
+ def self.data
61
+ {
62
+ 'name' => ClientInfo.name,
63
+ 'version' => ClientInfo.version,
64
+ 'clientUrl' => ClientInfo.url
65
+ }
66
+ end
67
+ end
68
+
69
+ module Error
70
+ def self.data
71
+ error = {}
72
+ error['className'] = Controls::Error.class_name
73
+ error['message'] = Controls::Error.message
74
+
75
+ stack_trace = StackTrace.data
76
+
77
+ error['stackTrace'] = stack_trace
78
+
79
+ error
80
+ end
81
+
82
+ module StackTrace
83
+ def self.data
84
+ [
85
+ Frames::First.data,
86
+ Frames::Second.data,
87
+ Frames::Third.data
88
+ ]
89
+ end
90
+
91
+ module Frames
92
+ module First
93
+ def self.data
94
+ {
95
+ 'fileName' => Controls::Error::Backtrace::Frames::First.filename,
96
+ 'lineNumber' => Controls::Error::Backtrace::Frames::First.line_number,
97
+ 'methodName' => Controls::Error::Backtrace::Frames::First.method_name
98
+ }
99
+ end
100
+ end
101
+
102
+ module Second
103
+ def self.data
104
+ {
105
+ 'fileName' => Controls::Error::Backtrace::Frames::Second.filename,
106
+ 'lineNumber' => Controls::Error::Backtrace::Frames::Second.line_number,
107
+ 'methodName' => Controls::Error::Backtrace::Frames::Second.method_name
108
+ }
109
+ end
110
+ end
111
+
112
+ module Third
113
+ def self.data
114
+ {
115
+ 'fileName' => Controls::Error::Backtrace::Frames::Third.filename,
116
+ 'lineNumber' => Controls::Error::Backtrace::Frames::Third.line_number,
117
+ 'methodName' => Controls::Error::Backtrace::Frames::Third.method_name
118
+ }
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,5 @@
1
+ module RaygunClient
2
+ module Controls
3
+ Error = ErrorData::Controls::Error
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module RaygunClient
2
+ module Controls
3
+ ErrorData = ::ErrorData::Controls::ErrorData
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ module RaygunClient
2
+ module Controls
3
+ module Random
4
+ def self.example
5
+ SecureRandom.hex
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module RaygunClient
2
+ module Controls
3
+ Time = Clock::Controls::Time
4
+ end
5
+ end
@@ -0,0 +1,74 @@
1
+ module RaygunClient
2
+ class Data
3
+ include Schema::DataStructure
4
+
5
+ attribute :occurred_time, String
6
+ attribute :machine_name, String
7
+ attribute :client, ClientInfo
8
+ attribute :error, ErrorData
9
+ attribute :tags, Array
10
+ attribute :custom_data, Hash
11
+
12
+ def ==(other)
13
+ self.class == other.class &&
14
+ occurred_time == other.occurred_time &&
15
+ machine_name == other.machine_name &&
16
+ client == other.client &&
17
+ error == other.error
18
+ end
19
+
20
+ def transform_write(data)
21
+ data[:occurred_on] = data.delete(:occurred_time)
22
+
23
+ details = {}
24
+ details[:machine_name] = data.delete(:machine_name)
25
+
26
+ client = data.delete(:client)
27
+ details[:client] = client.to_h
28
+
29
+ error = data.delete(:error)
30
+
31
+ error_data = {}
32
+ error_data[:class_name] = error.class_name
33
+ error_data[:message] = error.message
34
+
35
+ stack_trace = []
36
+ error.backtrace.each do |frame|
37
+ frame_data = {}
38
+ frame_data[:file_name] = frame.filename
39
+ frame_data[:line_number] = frame.line_number
40
+ frame_data[:method_name] = frame.method_name
41
+ stack_trace << frame_data
42
+ end
43
+
44
+ error_data[:stack_trace] = stack_trace
45
+
46
+ details[:error] = error_data
47
+
48
+ tags = data.delete(:tags)
49
+ details[:tags] = tags unless tags.empty?
50
+
51
+ custom_data = data.delete(:custom_data)
52
+ details[:user_custom_data] = custom_data unless custom_data.empty?
53
+
54
+ data[:details] = details
55
+ end
56
+
57
+ module Transform
58
+ def self.json
59
+ JSON
60
+ end
61
+
62
+ def self.raw_data(instance)
63
+ instance.attributes
64
+ end
65
+
66
+ module JSON
67
+ def self.write(raw_data)
68
+ formatted_data = Casing::Camel.(raw_data)
69
+ ::JSON.generate(formatted_data)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,27 @@
1
+ module RaygunClient
2
+ class Data
3
+ class ClientInfo
4
+ include Schema::DataStructure
5
+
6
+ attribute :name, String
7
+ attribute :version, String
8
+ attribute :client_url, String
9
+
10
+ def ==(other)
11
+ name == other.name &&
12
+ version == other.version &&
13
+ client_url == other.client_url
14
+ end
15
+
16
+ def self.build
17
+ instance = new
18
+
19
+ instance.name = RaygunClient::ClientInfo.name
20
+ instance.version = RaygunClient::ClientInfo.version
21
+ instance.client_url = RaygunClient::ClientInfo.url
22
+
23
+ instance
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,138 @@
1
+ module RaygunClient
2
+ module HTTP
3
+ class Post
4
+ include Configure
5
+ include Dependency
6
+ include Settings::Setting
7
+
8
+ include ::Telemetry::Dependency
9
+ include Log::Dependency
10
+
11
+ setting :api_key
12
+
13
+ attr_reader :data
14
+
15
+ configure :raygun_post
16
+
17
+ def self.build(connection: nil)
18
+ instance = new
19
+ RaygunClient::Settings.set(instance)
20
+ instance
21
+ end
22
+
23
+ def self.call(data)
24
+ instance = build
25
+ instance.(data)
26
+ end
27
+
28
+ def call(data)
29
+ logger.trace { "Posting to Raygun" }
30
+ json_text = Transform::Write.(data, :json)
31
+
32
+ response = http_post(json_text)
33
+
34
+ telemetry.record(:posted, Telemetry::Data.new(data, response))
35
+
36
+ logger.info { "Posted to Raygun (#{LogText::Posted.(data, response)})" }
37
+
38
+ response
39
+ end
40
+
41
+ def self.host
42
+ 'api.raygun.io'
43
+ end
44
+
45
+ def self.path
46
+ '/entries'
47
+ end
48
+
49
+ def self.uri
50
+ @uri ||= URI::HTTPS.build(:host => host, :path => path)
51
+ end
52
+
53
+ def http_post(request_body)
54
+ uri = self.class.uri
55
+
56
+ response = Net::HTTP.post(uri, request_body, { 'X-ApiKey' => api_key })
57
+
58
+ response
59
+ end
60
+
61
+ def self.register_telemetry_sink(post)
62
+ sink = Telemetry.sink
63
+ post.telemetry.register(sink)
64
+ sink
65
+ end
66
+
67
+ module Telemetry
68
+ class Sink
69
+ include ::Telemetry::Sink
70
+
71
+ record :posted
72
+
73
+ def posts(&blk)
74
+ if blk.nil?
75
+ return posted_records
76
+ end
77
+
78
+ posted_records.select do |record|
79
+ blk.call(record.data.data, record.data.response)
80
+ end
81
+ end
82
+
83
+ def posted?(&blk)
84
+ if blk.nil?
85
+ return recorded_posted?
86
+ end
87
+
88
+ recorded_posted? do |record|
89
+ blk.call(record.data.data, record.data.response)
90
+ end
91
+ end
92
+ end
93
+
94
+ Data = Struct.new(:data, :response)
95
+
96
+ def self.sink
97
+ Sink.new
98
+ end
99
+ end
100
+
101
+ module Substitute
102
+ def self.build
103
+ substitute = Substitute::Post.new
104
+
105
+ sink = RaygunClient::HTTP::Post.register_telemetry_sink(substitute)
106
+ substitute.sink = sink
107
+
108
+ substitute
109
+ end
110
+
111
+ class Post < HTTP::Post
112
+ attr_accessor :sink
113
+
114
+ def http_post(_)
115
+ end
116
+
117
+ def posted?(data=nil, &block)
118
+ unless data.nil?
119
+ block ||= proc { |posted_data|
120
+ data == posted_data
121
+ }
122
+ end
123
+
124
+ sink.posted?(&block)
125
+ end
126
+ end
127
+ end
128
+
129
+ module LogText
130
+ module Posted
131
+ def self.call(data, response)
132
+ "Status Code: #{response&.code || '(none)'}, Reason Phrase: #{response&.message || '(none)'}, Error Message: #{data.error.message}, Custom Data: #{data.custom_data || '(none)'})"
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,15 @@
1
+ module RaygunClient
2
+ class Settings < ::Settings
3
+ def self.instance
4
+ @instance ||= build
5
+ end
6
+
7
+ def self.data_source
8
+ 'settings/raygun_client.json'
9
+ end
10
+
11
+ def self.set(receiver)
12
+ instance.set(receiver)
13
+ end
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ntl-raygun_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0.0
5
+ platform: ruby
6
+ authors:
7
+ - The Eventide Project
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: evt-configure
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: evt-settings
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: evt-telemetry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: ntl-error_data
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
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: test_bench
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: " "
84
+ email: opensource@eventide-project.org
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - lib/raygun_client.rb
90
+ - lib/raygun_client/client_info.rb
91
+ - lib/raygun_client/controls.rb
92
+ - lib/raygun_client/controls/data.rb
93
+ - lib/raygun_client/controls/error.rb
94
+ - lib/raygun_client/controls/error_data.rb
95
+ - lib/raygun_client/controls/random.rb
96
+ - lib/raygun_client/controls/time.rb
97
+ - lib/raygun_client/data.rb
98
+ - lib/raygun_client/data/client_info.rb
99
+ - lib/raygun_client/http/post.rb
100
+ - lib/raygun_client/settings.rb
101
+ homepage: https://github.com/ntl/raygun-client
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '2.4'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubygems_version: 3.1.3
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Client for the Raygun API
124
+ test_files: []