ntl-raygun_client 0.5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []