skylight 0.0.7 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/bin/skylight +5 -0
  3. data/lib/skylight.rb +2 -0
  4. data/lib/skylight/cli.rb +84 -0
  5. data/lib/skylight/config.rb +53 -6
  6. data/lib/skylight/instrumenter.rb +4 -1
  7. data/lib/skylight/json_proto.rb +0 -3
  8. data/lib/skylight/middleware.rb +1 -0
  9. data/lib/skylight/normalize.rb +30 -5
  10. data/lib/skylight/normalize/process_action.rb +1 -1
  11. data/lib/skylight/normalize/render_collection.rb +2 -6
  12. data/lib/skylight/normalize/render_partial.rb +2 -5
  13. data/lib/skylight/normalize/render_template.rb +2 -5
  14. data/lib/skylight/normalize/sql.rb +2 -4
  15. data/lib/skylight/railtie.rb +30 -33
  16. data/lib/skylight/sanity_checker.rb +73 -0
  17. data/lib/skylight/subscriber.rb +1 -15
  18. data/lib/skylight/trace.rb +30 -5
  19. data/lib/skylight/util/http.rb +97 -0
  20. data/lib/skylight/vendor/highline.rb +1012 -0
  21. data/lib/skylight/vendor/highline/color_scheme.rb +134 -0
  22. data/lib/skylight/vendor/highline/compatibility.rb +16 -0
  23. data/lib/skylight/vendor/highline/import.rb +41 -0
  24. data/lib/skylight/vendor/highline/menu.rb +398 -0
  25. data/lib/skylight/vendor/highline/question.rb +475 -0
  26. data/lib/skylight/vendor/highline/simulate.rb +48 -0
  27. data/lib/skylight/vendor/highline/string_extensions.rb +131 -0
  28. data/lib/skylight/vendor/highline/style.rb +181 -0
  29. data/lib/skylight/vendor/highline/system_extensions.rb +218 -0
  30. data/lib/skylight/vendor/thor.rb +473 -0
  31. data/lib/skylight/vendor/thor/actions.rb +318 -0
  32. data/lib/skylight/vendor/thor/actions/create_file.rb +105 -0
  33. data/lib/skylight/vendor/thor/actions/create_link.rb +60 -0
  34. data/lib/skylight/vendor/thor/actions/directory.rb +119 -0
  35. data/lib/skylight/vendor/thor/actions/empty_directory.rb +137 -0
  36. data/lib/skylight/vendor/thor/actions/file_manipulation.rb +314 -0
  37. data/lib/skylight/vendor/thor/actions/inject_into_file.rb +109 -0
  38. data/lib/skylight/vendor/thor/base.rb +652 -0
  39. data/lib/skylight/vendor/thor/command.rb +136 -0
  40. data/lib/skylight/vendor/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  41. data/lib/skylight/vendor/thor/core_ext/io_binary_read.rb +12 -0
  42. data/lib/skylight/vendor/thor/core_ext/ordered_hash.rb +100 -0
  43. data/lib/skylight/vendor/thor/error.rb +28 -0
  44. data/lib/skylight/vendor/thor/group.rb +282 -0
  45. data/lib/skylight/vendor/thor/invocation.rb +172 -0
  46. data/lib/skylight/vendor/thor/parser.rb +4 -0
  47. data/lib/skylight/vendor/thor/parser/argument.rb +74 -0
  48. data/lib/skylight/vendor/thor/parser/arguments.rb +171 -0
  49. data/lib/skylight/vendor/thor/parser/option.rb +121 -0
  50. data/lib/skylight/vendor/thor/parser/options.rb +218 -0
  51. data/lib/skylight/vendor/thor/rake_compat.rb +72 -0
  52. data/lib/skylight/vendor/thor/runner.rb +322 -0
  53. data/lib/skylight/vendor/thor/shell.rb +88 -0
  54. data/lib/skylight/vendor/thor/shell/basic.rb +393 -0
  55. data/lib/skylight/vendor/thor/shell/color.rb +148 -0
  56. data/lib/skylight/vendor/thor/shell/html.rb +127 -0
  57. data/lib/skylight/vendor/thor/util.rb +270 -0
  58. data/lib/skylight/vendor/thor/version.rb +3 -0
  59. data/lib/skylight/version.rb +1 -1
  60. data/lib/skylight/worker.rb +3 -58
  61. metadata +56 -18
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: addb4eed3d6a9b0f22eb5163115018211c5da90c
4
+ data.tar.gz: 513eb7a8391b46447744f602127b2e0e4fe84edc
5
+ SHA512:
6
+ metadata.gz: cd3900fdbb47bc3adf7a81dda75a69277b72484d056a1f86c66b83b36335d0a2e01568830c0bb412bdcd76c82eb7ceec11fc2a5b8f73c1c129d725ab342e27b4
7
+ data.tar.gz: e94a2b3bf08c8151b1a23e666402a4530eaa3310087de8f6b43f109f57792c7556e17314711babfeff7cfaca3a3f8d1df41f18b36587bf356c5c12d2533f668a
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "skylight/cli"
4
+
5
+ Skylight::CLI.start(ARGV)
@@ -19,11 +19,13 @@ module Skylight
19
19
  require 'skylight/util/clock'
20
20
  require 'skylight/util/ewma'
21
21
  require 'skylight/util/gzip'
22
+ require 'skylight/util/http'
22
23
  require 'skylight/util/queue'
23
24
  require 'skylight/util/uniform_sample'
24
25
  require 'skylight/util/uuid'
25
26
 
26
27
  # Then require the rest
28
+ require 'skylight/sanity_checker'
27
29
  require 'skylight/compat'
28
30
  require 'skylight/config'
29
31
  require 'skylight/instrumenter'
@@ -0,0 +1,84 @@
1
+ # Use vendored thor / highline
2
+ $:.unshift File.expand_path('../vendor', __FILE__)
3
+
4
+ require "skylight"
5
+ require "thor"
6
+ require "highline"
7
+
8
+ module Skylight
9
+ class CLI < Thor
10
+ desc "create", "Create a new app"
11
+ def create
12
+ if !SanityChecker.new.smoke_test(File.expand_path("config/skylight.yml"))
13
+ say "Your app is already on Skylight. http://www.skylight.io", :green
14
+ return
15
+ end
16
+
17
+ token = load_credentials
18
+ config = http_config
19
+
20
+ response = Util::HTTP.new(config).create_app(token, app_name)["app"]
21
+
22
+ config.app_id = response["id"]
23
+ config.authentication_token = response["token"]
24
+
25
+ config.yaml_file = File.expand_path("config/skylight.yml")
26
+
27
+ config.save
28
+
29
+ say "Congratulations. Your application is on Skylight! http://www.skylight.io", :green
30
+ end
31
+
32
+ private
33
+ def user_settings
34
+ File.expand_path("~/.skylight")
35
+ end
36
+
37
+ def http_config
38
+ @http_config ||= Config.new do |c|
39
+ c.host = "www.skylight.io"
40
+ c.port = 443
41
+ c.ssl = true
42
+ c.deflate = false
43
+ end
44
+ end
45
+
46
+ def load_credentials
47
+ if credentials?
48
+ return YAML.load_file(user_settings)["token"]
49
+ end
50
+
51
+ token = nil
52
+
53
+ loop do
54
+ h = HighLine.new
55
+ username = h.ask("Username: ")
56
+ password = h.ask("Password: ") { |q| q.echo = "*" }
57
+
58
+ response = Util::HTTP.new(http_config).auth(username, password)
59
+ if response["authenticated"] == false
60
+ say "Sorry. That username and password was invalid. Please try again", :red
61
+ puts
62
+ else
63
+ token = response["token"]
64
+ break
65
+ end
66
+ end
67
+
68
+ File.open(user_settings, "w") do |file|
69
+ file.puts YAML.dump("token" => token)
70
+ end
71
+
72
+ token
73
+ end
74
+
75
+ def credentials?
76
+ !SanityChecker.new.user_credentials(user_settings)
77
+ end
78
+
79
+ def app_name
80
+ require "./config/application"
81
+ Rails.application.class.name.split("::").first.underscore
82
+ end
83
+ end
84
+ end
@@ -1,17 +1,42 @@
1
1
  require 'yaml'
2
+ require 'logger'
2
3
 
3
4
  module Skylight
4
5
  class Config
6
+ class Normalizer < Struct.new(:view_paths)
7
+ end
8
+
9
+ class << self
10
+ def load_from_yaml(path, env=ENV)
11
+ new do |config|
12
+ data = YAML.load_file(path)
5
13
 
6
- def self.load_from_yaml(path)
7
- new do |config|
8
- data = YAML.load_file(path)
9
- data.each do |key, value|
10
- if config.respond_to?("#{key}=")
11
- config.send("#{key}=", value)
14
+ data.each do |key, value|
15
+ apply_config(config, key, value)
12
16
  end
17
+
18
+ config.yaml_file = path
19
+
20
+ apply_env(config, env)
21
+ end
22
+ end
23
+
24
+ private
25
+ def apply_env(config, env)
26
+ env.each do |key, value|
27
+ name = normalize_env(key)
28
+ apply_config(config, name, value) if name
13
29
  end
14
30
  end
31
+
32
+ def normalize_env(key)
33
+ match = key.match(/^SKYLIGHT_(\w+)$/)
34
+ match && match[1].downcase
35
+ end
36
+
37
+ def apply_config(config, key, value)
38
+ config.send("#{key}=", value) if config.respond_to?("#{key}=")
39
+ end
15
40
  end
16
41
 
17
42
  def initialize(attrs = {})
@@ -27,6 +52,8 @@ module Skylight
27
52
  @logger = Logger.new(STDOUT)
28
53
  @logger.level = Logger::INFO
29
54
 
55
+ @normalizer = Normalizer.new
56
+
30
57
  attrs.each do |k, v|
31
58
  if respond_to?("#{k}=")
32
59
  send("#{k}=", v)
@@ -36,7 +63,9 @@ module Skylight
36
63
  yield self if block_given?
37
64
  end
38
65
 
66
+ attr_accessor :yaml_file
39
67
  attr_accessor :authentication_token
68
+ attr_accessor :app_id
40
69
 
41
70
  attr_accessor :ssl
42
71
  alias_method :ssl?, :ssl
@@ -48,12 +77,16 @@ module Skylight
48
77
 
49
78
  attr_accessor :port
50
79
 
80
+ attr_accessor :http
81
+
51
82
  attr_accessor :samples_per_interval
52
83
 
53
84
  attr_accessor :interval
54
85
 
55
86
  attr_accessor :max_pending_traces
56
87
 
88
+ attr_reader :normalizer
89
+
57
90
  attr_reader :protocol
58
91
  def protocol=(val)
59
92
  if val.is_a?(String) || val.is_a?(Symbol)
@@ -78,5 +111,19 @@ module Skylight
78
111
  end
79
112
  end
80
113
 
114
+ attr_writer :gc_profiler
115
+
116
+ def gc_profiler
117
+ @gc_profiler ||= Struct.new(:enable, :disable, :clear, :total_time).new(nil, nil, nil, 0)
118
+ end
119
+
120
+ def save(filename=yaml_file)
121
+ File.open(filename, "w") do |file|
122
+ config = {}
123
+ config["authentication_token"] = authentication_token if authentication_token
124
+ config["app_id"] = app_id if app_id
125
+ file.puts YAML.dump(config)
126
+ end
127
+ end
81
128
  end
82
129
  end
@@ -20,6 +20,7 @@ module Skylight
20
20
 
21
21
  def initialize(config)
22
22
  @config = config
23
+
23
24
  @worker = Worker.new(self)
24
25
  end
25
26
 
@@ -39,6 +40,8 @@ module Skylight
39
40
  return
40
41
  end
41
42
 
43
+ config.gc_profiler.enable
44
+
42
45
  self
43
46
  end
44
47
 
@@ -72,7 +75,7 @@ module Skylight
72
75
  private
73
76
 
74
77
  def create_trace(endpoint)
75
- Trace.new(endpoint)
78
+ Trace.new(config, endpoint)
76
79
  # Paranoia
77
80
  rescue => e
78
81
  error e
@@ -82,9 +82,6 @@ module Skylight
82
82
  ehash
83
83
  end
84
84
 
85
- require "pp"
86
- @config.logger.debug PP.pp(hash, "")
87
-
88
85
  out << hash.to_json
89
86
  end
90
87
  end
@@ -8,6 +8,7 @@ module Skylight
8
8
  def initialize(app, config, instrumenter_class=Instrumenter)
9
9
  @app = app
10
10
  @config = config
11
+ @config.gc_profiler = GC::Profiler
11
12
  @instrumenter_class = instrumenter_class
12
13
  end
13
14
 
@@ -2,13 +2,13 @@ module Skylight
2
2
  module Normalize
3
3
  @registry = {}
4
4
 
5
- def self.normalize(trace, name, payload)
5
+ def self.normalize(trace, name, payload, config={})
6
6
  klass = @registry[name]
7
7
 
8
8
  if klass
9
- klass.new(trace, name, payload).normalize
9
+ klass.new(trace, name, payload, config).normalize
10
10
  else
11
- Default.new(trace, name, payload).normalize
11
+ Default.new(trace, name, payload, config).normalize
12
12
  end
13
13
  end
14
14
 
@@ -22,8 +22,33 @@ module Skylight
22
22
  Normalize.register(name, self)
23
23
  end
24
24
 
25
- def initialize(trace, name, payload)
26
- @trace, @name, @payload = trace, name, payload
25
+ def initialize(trace, name, payload, config={})
26
+ @trace, @name, @payload, @config = trace, name, payload, config
27
+ end
28
+ end
29
+
30
+ class RenderNormalizer < Normalizer
31
+ private
32
+ def normalize_render(category, payload)
33
+ path = @payload[:identifier]
34
+
35
+ title = relative_path(path)
36
+ path = nil if path == title
37
+ [ category, title, path, payload ]
38
+ end
39
+
40
+ def relative_path(path)
41
+ root_path = @config.view_paths.find do |p|
42
+ path.start_with?(p)
43
+ end
44
+
45
+ if root_path
46
+ relative = path[root_path.size..-1]
47
+ relative = relative[1..-1] if relative.start_with?("/")
48
+ relative
49
+ else
50
+ path
51
+ end
27
52
  end
28
53
  end
29
54
  end
@@ -5,7 +5,7 @@ module Skylight
5
5
 
6
6
  def normalize
7
7
  @trace.endpoint = controller_action
8
- [ "app.controller.request", controller_action, controller_action, @payload ]
8
+ [ "app.controller.request", controller_action, nil, @payload ]
9
9
  end
10
10
 
11
11
  private
@@ -1,15 +1,11 @@
1
1
  module Skylight
2
2
  module Normalize
3
- class RenderCollection < Normalizer
3
+ class RenderCollection < RenderNormalizer
4
4
  register "render_collection.action_view"
5
5
 
6
6
  def normalize
7
- path = @payload[:identifier]
8
- annotations = { count: @payload[:count] }
9
-
10
- [ "view.render.collection", path, path, annotations ]
7
+ normalize_render "view.render.collection", count: @payload[:count]
11
8
  end
12
9
  end
13
10
  end
14
11
  end
15
-
@@ -1,13 +1,10 @@
1
1
  module Skylight
2
2
  module Normalize
3
- class RenderPartial < Normalizer
3
+ class RenderPartial < RenderNormalizer
4
4
  register "render_partial.action_view"
5
5
 
6
6
  def normalize
7
- path = @payload[:identifier]
8
- annotations = { partial: true }
9
-
10
- [ "view.render.template", path, path, annotations ]
7
+ normalize_render "view.render.template", partial: true
11
8
  end
12
9
  end
13
10
  end
@@ -1,13 +1,10 @@
1
1
  module Skylight
2
2
  module Normalize
3
- class RenderTemplate < Normalizer
3
+ class RenderTemplate < RenderNormalizer
4
4
  register "render_template.action_view"
5
5
 
6
6
  def normalize
7
- path = @payload[:identifier]
8
- annotations = { partial: false }
9
-
10
- [ "view.render.template", path, path, annotations ]
7
+ normalize_render "view.render.template", partial: false
11
8
  end
12
9
  end
13
10
  end
@@ -4,11 +4,9 @@ module Skylight
4
4
  register "sql.active_record"
5
5
 
6
6
  def normalize
7
- if @payload[:name] == "SCHEMA"
7
+ case @payload[:name]
8
+ when "SCHEMA", "CACHE"
8
9
  return :skip
9
- elsif @payload[:name] == "CACHE"
10
- name = "db.sql.cache"
11
- title = "Cached Load"
12
10
  else
13
11
  name = "db.sql.query"
14
12
  title = @payload[:name]
@@ -13,9 +13,25 @@ module Skylight
13
13
 
14
14
  attr_accessor :instrumenter
15
15
 
16
+ initializer "skylight.sanity_check" do |app|
17
+ checker = SanityChecker.new
18
+ @problems = checker.smoke_test(config_path(app)) || checker.sanity_check(load_config(app))
19
+ next unless @problems
20
+
21
+ @problems.each do |group, problem_list|
22
+ problem_list.each do |problem|
23
+ puts "[SKYLIGHT] PROBLEM: #{group} #{problem}"
24
+ end
25
+ end
26
+ end
27
+
16
28
  initializer "skylight.configure" do |app|
17
- Rails.logger.debug "[SKYLIGHT] Installing middleware"
18
- app.middleware.insert 0, Middleware, load_config
29
+ if @problems
30
+ puts "[SKYLIGHT] Skipping Skylight boot"
31
+ else
32
+ Rails.logger.debug "[SKYLIGHT] Installing middleware"
33
+ app.middleware.insert 0, Middleware, load_config(app)
34
+ end
19
35
  end
20
36
 
21
37
  private
@@ -24,42 +40,23 @@ module Skylight
24
40
  Array(config.skylight.environments).map { |e| e && e.to_s }.compact
25
41
  end
26
42
 
27
- def load_instrumenter
28
- if environments.include?(Rails.env.to_s)
29
- if c = load_config
30
- Rails.logger.debug "[SKYLIGHT] Starting instrumenter"
31
- Instrumenter.start!(c)
32
- end
33
- end
34
- # Paranoia
35
- rescue
36
- nil
43
+ def config_path(app)
44
+ path = config.skylight.config_path
45
+ File.expand_path(path, app.root)
37
46
  end
38
47
 
39
- def load_config
40
- unless path = config.skylight.config_path
41
- Rails.logger.warn "[SKYLIGHT] Path to config YAML file unset"
42
- return
43
- end
44
-
45
- path = File.expand_path(path, Rails.root)
46
-
47
- unless File.exist?(path)
48
- Rails.logger.warn "[SKYLIGHT] Config does not exist at `#{path}`"
49
- return
50
- end
51
-
52
- ret = Config.load_from_yaml(path)
48
+ def load_config(app)
49
+ @skylight_config ||= begin
50
+ config = Config.load_from_yaml(config_path(app), ENV).tap do |c|
51
+ c.logger = Rails.logger
52
+ end
53
53
 
54
- unless ret.authentication_token
55
- Rails.logger.warn "[SKYLIGHT] Config does not include an authentication token"
56
- return
54
+ config.normalizer.view_paths = app.config.paths["app/views"].existent
55
+ config.http = Util::HTTP.new(config)
56
+ config
57
57
  end
58
-
59
- ret.logger = Rails.logger
60
-
61
- ret
62
58
  rescue => e
59
+ raise
63
60
  Rails.logger.error "[SKYLIGHT] #{e.message} (#{e.class}) - #{e.backtrace.first}"
64
61
  end
65
62