eltesla 0.0.1
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.
- checksums.yaml +7 -0
- data/lib/eltesla/client.rb +69 -0
- data/lib/eltesla/experiment.rb +49 -0
- data/lib/eltesla/observation.rb +35 -0
- data/lib/eltesla/result.rb +38 -0
- data/lib/eltesla/version.rb +3 -0
- data/lib/eltesla.rb +10 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6d5a5688dc14f783b38a944c3e29088ee53343beab09b3a7dd0a4d59a54eadcc
|
4
|
+
data.tar.gz: 39b89807a086e30b1b0d680975a29a3f657591e82e192b9709fc4c91388d3487
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b263b136234020ac7b6e88b7493131b2f815120409b36b1c6bd51d1d873adae29a4456e05a6e1613150fe4fbbb72d6c9f65e49be6a49e54963673749fe6a3036
|
7
|
+
data.tar.gz: 1b935e5420b4720c16be076184c13a32ba98f597043bc32b9dd4fbecaf74dcd99a9670ba7765354908e86864db976380c038beec17bb346e3ff4bed2f455b91a
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Eltesla
|
8
|
+
# Client for the Eltesla backend
|
9
|
+
class Client
|
10
|
+
if ENV.fetch('ELTESLA_DEBUG', false)
|
11
|
+
PROTOCOL = 'http'
|
12
|
+
DOMAIN = 'localhost:3000'
|
13
|
+
QUEUE_SIZE_THRESHOLD = 1
|
14
|
+
QUEUE_SIZE_LIMIT = 2
|
15
|
+
else
|
16
|
+
PROTOCOL = 'https'
|
17
|
+
DOMAIN = 'eltesla.dev'
|
18
|
+
QUEUE_SIZE_THRESHOLD = 10
|
19
|
+
QUEUE_SIZE_LIMIT = 20
|
20
|
+
end
|
21
|
+
ENDPOINT = URI.parse("#{PROTOCOL}://#{DOMAIN}/metrics")
|
22
|
+
|
23
|
+
class << self
|
24
|
+
attr_writer :queue
|
25
|
+
|
26
|
+
def queue
|
27
|
+
@queue ||= []
|
28
|
+
end
|
29
|
+
|
30
|
+
def send(result)
|
31
|
+
raise "Could not process #{result}" unless result.is_a?(Eltesla::Result)
|
32
|
+
|
33
|
+
queue << result
|
34
|
+
flush! if queue.size >= QUEUE_SIZE_THRESHOLD
|
35
|
+
end
|
36
|
+
|
37
|
+
def flush!
|
38
|
+
return if queue.empty?
|
39
|
+
|
40
|
+
http_post!
|
41
|
+
queue.clear
|
42
|
+
rescue StandardError => e
|
43
|
+
warn "[Eltesla] Could not send payload: #{e.message}"
|
44
|
+
if queue.size > QUEUE_SIZE_LIMIT
|
45
|
+
warn("[Eltesla] Dropping #{queue.size - QUEUE_SIZE_LIMIT} results from the queue")
|
46
|
+
self.queue = queue[-QUEUE_SIZE_LIMIT..]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def http_post!
|
53
|
+
http = Net::HTTP.new(ENDPOINT.host, ENDPOINT.port)
|
54
|
+
request = Net::HTTP::Post.new(
|
55
|
+
ENDPOINT.request_uri,
|
56
|
+
{ 'Content-Type': 'application/json' }
|
57
|
+
)
|
58
|
+
request.body = { results: queue }.to_json
|
59
|
+
|
60
|
+
http.request(request).value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# rubocop:disable Style/GlobalVars
|
67
|
+
$eltesla_exit_callback ||= at_exit { Eltesla::Client.flush! }
|
68
|
+
# rubocop:enable Style/GlobalVars
|
69
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'scientist/experiment'
|
4
|
+
require 'eltesla/result'
|
5
|
+
|
6
|
+
module Eltesla
|
7
|
+
# Github scientist experiment implementation for Eltesla
|
8
|
+
class Experiment
|
9
|
+
include Scientist::Experiment
|
10
|
+
|
11
|
+
attr_reader :name, :file, :line
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
location_parts = clean_trace(caller).first.split(/:/)
|
15
|
+
@file = location_parts.first
|
16
|
+
@line = location_parts[1].to_i
|
17
|
+
@name = name || location_parts.last[4..-2]
|
18
|
+
end
|
19
|
+
|
20
|
+
def enabled?
|
21
|
+
# FIXME : Add activation policies
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def raised(operation, error)
|
26
|
+
# see "In a Scientist callback" below
|
27
|
+
p "Operation '#{operation}' failed with error '#{error.inspect}'"
|
28
|
+
super # will re-raise
|
29
|
+
end
|
30
|
+
|
31
|
+
def publish(result)
|
32
|
+
Eltesla::Client.send(result.to_eltesla)
|
33
|
+
end
|
34
|
+
|
35
|
+
def clean_trace(backtrace)
|
36
|
+
return backtrace unless defined?(Rails.backtrace_cleaner)
|
37
|
+
|
38
|
+
Rails.backtrace_cleaner.clean(backtrace)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.run(name = nil)
|
42
|
+
raise 'Missing block' unless block_given?
|
43
|
+
|
44
|
+
experiment = Eltesla::Experiment.new(name)
|
45
|
+
yield(experiment)
|
46
|
+
experiment.run
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'scientist'
|
5
|
+
|
6
|
+
module Eltesla
|
7
|
+
# rubocop:disable Naming/ConstantName
|
8
|
+
OBSERVATION_ATTRIBUTES = %i[
|
9
|
+
name
|
10
|
+
value
|
11
|
+
duration
|
12
|
+
exception_class
|
13
|
+
exception_message
|
14
|
+
exception_backtrace
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
Observation =
|
18
|
+
if defined?(Data.define)
|
19
|
+
Data.define(*OBSERVATION_ATTRIBUTES)
|
20
|
+
else
|
21
|
+
Struct.new(*OBSERVATION_ATTRIBUTES, keyword_init: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
Scientist::Observation.define_method(:to_eltesla) do
|
25
|
+
Eltesla::Observation.new(
|
26
|
+
exception_class: exception&.class&.name,
|
27
|
+
exception_message: exception&.message,
|
28
|
+
exception_backtrace: exception&.backtrace,
|
29
|
+
name:,
|
30
|
+
value:,
|
31
|
+
duration:
|
32
|
+
)
|
33
|
+
end
|
34
|
+
# rubocop:enable Naming/ConstantName
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'scientist'
|
5
|
+
require_relative 'observation'
|
6
|
+
|
7
|
+
module Eltesla
|
8
|
+
# rubocop:disable Naming/ConstantName
|
9
|
+
RESULT_ATTRIBUTES = %i[
|
10
|
+
observations_attributes
|
11
|
+
context
|
12
|
+
matched
|
13
|
+
executed_at
|
14
|
+
experiment_name
|
15
|
+
experiment_file
|
16
|
+
experiment_line
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
Result =
|
20
|
+
if defined?(Data.define)
|
21
|
+
Data.define(*RESULT_ATTRIBUTES)
|
22
|
+
else
|
23
|
+
Struct.new(*RESULT_ATTRIBUTES, keyword_init: true)
|
24
|
+
end
|
25
|
+
|
26
|
+
Scientist::Result.define_method(:to_eltesla) do
|
27
|
+
Eltesla::Result.new(
|
28
|
+
experiment_name: experiment.name,
|
29
|
+
experiment_file: experiment.file,
|
30
|
+
experiment_line: experiment.line,
|
31
|
+
context: context.empty? ? nil : context,
|
32
|
+
matched: matched?,
|
33
|
+
executed_at: Time.now,
|
34
|
+
observations_attributes: observations.map(&:to_eltesla)
|
35
|
+
)
|
36
|
+
end
|
37
|
+
# rubocop:enable Naming/ConstantName
|
38
|
+
end
|
data/lib/eltesla.rb
ADDED
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eltesla
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexandre Ignjatovic
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-03-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: scientist
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
description: Client for the Eltesla service, for easier refactoring
|
28
|
+
email: alexandre.ignjatovic@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/eltesla.rb
|
34
|
+
- lib/eltesla/client.rb
|
35
|
+
- lib/eltesla/experiment.rb
|
36
|
+
- lib/eltesla/observation.rb
|
37
|
+
- lib/eltesla/result.rb
|
38
|
+
- lib/eltesla/version.rb
|
39
|
+
homepage: https://eltes.la
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '2.3'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubygems_version: 3.5.6
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: 'Eltesla: GitHub Scientist as a Service.'
|
62
|
+
test_files: []
|