vayacondios-server 0.2.11 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -1
- data/.travis.yml +2 -0
- data/Gemfile +15 -9
- data/LICENSE.md +2 -6
- data/Procfile +1 -1
- data/README.md +656 -111
- data/Rakefile +89 -6
- data/bin/vcd +10 -0
- data/bin/vcd-server +8 -0
- data/config/database.yml +6 -0
- data/config/spec.example.yml +18 -0
- data/config/vayacondios.example.yml +15 -0
- data/config/vcd-server.rb +37 -0
- data/examples/configuration.rb +56 -0
- data/examples/event_stream.rb +19 -0
- data/examples/simple.rb +61 -0
- data/features/event.feature +319 -0
- data/features/events.feature +208 -0
- data/features/stash.feature +840 -0
- data/features/stashes.feature +492 -0
- data/features/step_definitions/stash_steps.rb +113 -0
- data/features/stream.feature +30 -0
- data/features/support/em.rb +14 -0
- data/features/support/env.rb +13 -0
- data/lib/vayacondios/configuration.rb +63 -0
- data/lib/vayacondios/server/api.rb +126 -0
- data/lib/vayacondios/server/api_options.rb +56 -0
- data/lib/vayacondios/server/configuration.rb +23 -0
- data/lib/vayacondios/server/driver.rb +71 -0
- data/lib/vayacondios/server/drivers/mongo.rb +126 -0
- data/lib/vayacondios/server/handlers/document_handler.rb +81 -0
- data/lib/vayacondios/server/handlers/event_handler.rb +31 -26
- data/lib/vayacondios/server/handlers/events_handler.rb +31 -0
- data/lib/vayacondios/server/handlers/stash_handler.rb +69 -0
- data/lib/vayacondios/server/handlers/stashes_handler.rb +49 -0
- data/lib/vayacondios/server/handlers/stream_handler.rb +39 -0
- data/lib/vayacondios/server/models/document.rb +87 -0
- data/lib/vayacondios/server/models/event.rb +198 -0
- data/lib/vayacondios/server/models/stash.rb +100 -0
- data/lib/vayacondios/server.rb +35 -0
- data/lib/vayacondios-server.rb +19 -13
- data/lib/vayacondios.rb +22 -0
- data/pom.xml +124 -4
- data/spec/configuration_spec.rb +41 -0
- data/spec/server/api_options_spec.rb +32 -0
- data/spec/server/api_spec.rb +279 -0
- data/spec/server/configuration_spec.rb +27 -0
- data/spec/server/drivers/mongo_spec.rb +107 -0
- data/spec/server/handlers/event_handler_spec.rb +62 -0
- data/spec/server/handlers/events_handler_spec.rb +51 -0
- data/spec/server/handlers/stash_handler_spec.rb +68 -0
- data/spec/server/handlers/stashes_handler_spec.rb +50 -0
- data/spec/server/handlers/stream_handler_spec.rb +5 -0
- data/spec/server/models/document_spec.rb +9 -0
- data/spec/server/models/event_spec.rb +185 -0
- data/spec/server/models/stash_spec.rb +95 -0
- data/spec/spec_helper.rb +23 -3
- data/spec/support/database_helper.rb +42 -0
- data/spec/support/log_helper.rb +19 -0
- data/spec/support/shared_context_for_events.rb +22 -0
- data/spec/support/shared_context_for_stashes.rb +24 -0
- data/spec/support/shared_examples_for_handlers.rb +32 -0
- data/src/main/java/com/infochimps/vayacondios/BaseClient.java +342 -0
- data/src/main/java/com/infochimps/vayacondios/HTTPClient.java +426 -0
- data/src/main/java/com/infochimps/vayacondios/VayacondiosClient.java +487 -65
- data/src/main/java/com/infochimps/vayacondios/test/IntegrationTest.java +3 -0
- data/src/test/java/com/infochimps/vayacondios/BaseClientTest.java +50 -0
- data/src/test/java/com/infochimps/vayacondios/HTTPClientIT.java +267 -0
- data/vayacondios-server.gemspec +9 -9
- metadata +127 -122
- checksums.yaml +0 -15
- data/.rspec +0 -2
- data/.yardopts +0 -10
- data/Guardfile +0 -41
- data/app/http_shim.rb +0 -71
- data/bin/vcd.sh +0 -27
- data/config/http_shim.rb +0 -43
- data/config/vayacondios.example.yaml +0 -7
- data/config/vayacondios.yaml +0 -7
- data/examples/java/ItemSetTest.java +0 -76
- data/lib/tasks/publish.rake +0 -23
- data/lib/tasks/spec.rake +0 -11
- data/lib/tasks/yard.rake +0 -2
- data/lib/vayacondios/client/config.rb +0 -7
- data/lib/vayacondios/client/configliere.rb +0 -38
- data/lib/vayacondios/client/cube_client.rb +0 -39
- data/lib/vayacondios/client/http_client.rb +0 -49
- data/lib/vayacondios/client/itemset.rb +0 -130
- data/lib/vayacondios/client/legacy_switch.rb +0 -43
- data/lib/vayacondios/client/notifier.rb +0 -123
- data/lib/vayacondios/client/zabbix_client.rb +0 -148
- data/lib/vayacondios/legacy_switch.rb +0 -43
- data/lib/vayacondios/server/errors/bad_request.rb +0 -6
- data/lib/vayacondios/server/errors/not_found.rb +0 -6
- data/lib/vayacondios/server/handlers/config_handler.rb +0 -32
- data/lib/vayacondios/server/handlers/itemset_handler.rb +0 -60
- data/lib/vayacondios/server/legacy_switch.rb +0 -43
- data/lib/vayacondios/server/model/config_document.rb +0 -89
- data/lib/vayacondios/server/model/document.rb +0 -25
- data/lib/vayacondios/server/model/event_document.rb +0 -94
- data/lib/vayacondios/server/model/itemset_document.rb +0 -126
- data/lib/vayacondios/server/rack/extract_methods.rb +0 -35
- data/lib/vayacondios/server/rack/jsonize.rb +0 -43
- data/lib/vayacondios/server/rack/params.rb +0 -50
- data/lib/vayacondios/server/rack/path.rb +0 -23
- data/lib/vayacondios/server/rack/path_validation.rb +0 -22
- data/lib/vayacondios/version.rb +0 -3
- data/lib/vayacondios-client.rb +0 -22
- data/scripts/hadoop_monitor/configurable.rb +0 -66
- data/scripts/hadoop_monitor/hadoop_attempt_scraper.rb +0 -45
- data/scripts/hadoop_monitor/hadoop_client.rb +0 -273
- data/scripts/hadoop_monitor/hadoop_monitor.rb +0 -101
- data/scripts/hadoop_monitor/hadoopable.rb +0 -65
- data/scripts/hadoop_monitor/machine_monitor.rb +0 -115
- data/scripts/s3_cataloger/buckets +0 -33
- data/scripts/s3_cataloger/foreach_bucket +0 -88
- data/scripts/s3_cataloger/parse_ls.py +0 -391
- data/spec/client/itemset_legacy_spec.rb +0 -55
- data/spec/client/itemset_spec.rb +0 -60
- data/spec/client/notifier_spec.rb +0 -120
- data/spec/server/config_spec.rb +0 -113
- data/spec/server/event_spec.rb +0 -103
- data/spec/server/itemset_legacy_spec.rb +0 -320
- data/spec/server/itemset_spec.rb +0 -317
- data/spec/server/rack/extract_methods_spec.rb +0 -60
- data/spec/server/rack/path_spec.rb +0 -36
- data/spec/server/rack/path_validation_spec.rb +0 -22
- data/spec/server/server_spec.rb +0 -20
- data/spec/support/mongo_cleaner.rb +0 -32
- data/src/main/java/ItemSetTest.java +0 -76
- data/src/main/java/com/infochimps/util/CurrentClass.java +0 -26
- data/src/main/java/com/infochimps/util/DebugUtil.java +0 -38
- data/src/main/java/com/infochimps/util/HttpHelper.java +0 -181
- data/src/main/java/com/infochimps/vayacondios/ItemSets.java +0 -373
- data/src/main/java/com/infochimps/vayacondios/LinkToVCD.java +0 -18
- data/src/main/java/com/infochimps/vayacondios/MemoryVCDShim.java +0 -84
- data/src/main/java/com/infochimps/vayacondios/Organization.java +0 -62
- data/src/main/java/com/infochimps/vayacondios/PathBuilder.java +0 -13
- data/src/main/java/com/infochimps/vayacondios/StandardVCDLink.java +0 -218
- data/src/main/java/com/infochimps/vayacondios/VCDIntegrationTest.java +0 -108
- data/src/test/java/com/infochimps/vayacondios/TestVayacondiosInMemory.java +0 -78
- data/vayacondios-client.gemspec +0 -25
@@ -1,22 +0,0 @@
|
|
1
|
-
class Vayacondios
|
2
|
-
module Rack
|
3
|
-
class PathValidation
|
4
|
-
include Goliath::Rack::AsyncMiddleware
|
5
|
-
|
6
|
-
def initialize(app, opts = {})
|
7
|
-
@app = app ; @opts = opts
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
return [400, {}, MultiJson.dump({ error: "Bad Request. Format path is <host>/v1/<org>/event/<topic>" })] unless valid_paths? env[:vayacondios_path]
|
12
|
-
@app.call(env)
|
13
|
-
end
|
14
|
-
|
15
|
-
def valid_paths?(path)
|
16
|
-
# use @opts for validation later
|
17
|
-
path.nil? ? false : true
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/vayacondios/version.rb
DELETED
data/lib/vayacondios-client.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'configliere'
|
2
|
-
require 'multi_json'
|
3
|
-
require 'net/http'
|
4
|
-
|
5
|
-
require 'gorillib/builder'
|
6
|
-
require 'gorillib/configurable'
|
7
|
-
require 'gorillib/enumerable/sum'
|
8
|
-
require 'gorillib/exception/raisers'
|
9
|
-
require 'gorillib/hash/deep_compact'
|
10
|
-
require 'gorillib/hash/deep_merge'
|
11
|
-
require 'gorillib/hash/keys'
|
12
|
-
require 'gorillib/logger/log'
|
13
|
-
require 'gorillib/metaprogramming/class_attribute'
|
14
|
-
require 'gorillib/object/blank'
|
15
|
-
require 'gorillib/string/constantize'
|
16
|
-
require 'gorillib/string/inflections'
|
17
|
-
|
18
|
-
require 'vayacondios/client/http_client'
|
19
|
-
require 'vayacondios/client/cube_client'
|
20
|
-
require 'vayacondios/client/zabbix_client'
|
21
|
-
require 'vayacondios/client/notifier'
|
22
|
-
require 'vayacondios/client/configliere'
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'configliere'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
class Vayacondios
|
5
|
-
|
6
|
-
module Configurable
|
7
|
-
|
8
|
-
#
|
9
|
-
# Declare a name CONST_NAME = :const_name
|
10
|
-
#
|
11
|
-
def self.declare_name symbol
|
12
|
-
const_set symbol.to_s.upcase.to_sym, symbol
|
13
|
-
end
|
14
|
-
|
15
|
-
declare_name :cluster_busy
|
16
|
-
declare_name :cluster_quiet
|
17
|
-
declare_name :event
|
18
|
-
declare_name :time
|
19
|
-
|
20
|
-
attr_reader :logger
|
21
|
-
|
22
|
-
def settings
|
23
|
-
init_settings
|
24
|
-
return @settings
|
25
|
-
end
|
26
|
-
|
27
|
-
def init_settings
|
28
|
-
return if defined? @settings
|
29
|
-
|
30
|
-
@settings = Configliere::Param.new
|
31
|
-
@settings.use :env_var, :config_file, :commandline
|
32
|
-
|
33
|
-
@settings.define(:config_file,
|
34
|
-
description: "Config file location")
|
35
|
-
@settings.define(:sleep_seconds,
|
36
|
-
default: 5,
|
37
|
-
description: "Time to sleep in main loops")
|
38
|
-
@settings.define(:log_level,
|
39
|
-
default: "info",
|
40
|
-
description: "Log level. See standard Logger class")
|
41
|
-
@settings.define(:mongo_db,
|
42
|
-
default: 'job_info',
|
43
|
-
description: "Mongo database to dump hadoop job information into")
|
44
|
-
@settings.define(:mongo_ip,
|
45
|
-
default: nil,
|
46
|
-
description: "IP address of Hadoop monitor node")
|
47
|
-
@settings.define(:mongo_collection_size,
|
48
|
-
default: 10 * (1 << 20),
|
49
|
-
description: ("Size (in bytes) of Mongo job events collection"))
|
50
|
-
|
51
|
-
@settings.resolve!
|
52
|
-
|
53
|
-
if @settings.config_file
|
54
|
-
@settings.read(@settings.config_file)
|
55
|
-
@settings.resolve!
|
56
|
-
end
|
57
|
-
|
58
|
-
@logger = Logger.new(STDERR)
|
59
|
-
@logger.level = Logger.const_get(@settings.log_level.upcase.to_sym)
|
60
|
-
|
61
|
-
@logger.info "Settings: #{@settings}"
|
62
|
-
|
63
|
-
@settings
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'nibbler'
|
3
|
-
require 'socket'
|
4
|
-
|
5
|
-
class HadoopAttemptScraper < Nibbler
|
6
|
-
attr_accessor :task_id
|
7
|
-
|
8
|
-
def self.scrape_task(task_id)
|
9
|
-
task_id = task_id.to_s
|
10
|
-
|
11
|
-
url = "http://#{Socket.gethostname}:50030/taskdetails.jsp?tipid=#{task_id}"
|
12
|
-
scrape = parse(open(url))
|
13
|
-
scrape.task_id = task_id
|
14
|
-
|
15
|
-
scrape
|
16
|
-
end
|
17
|
-
|
18
|
-
elements 'table.jobtasks tbody > tr' => :attempts do
|
19
|
-
element 'td:nth-child(1)' => 'attempt_id'
|
20
|
-
element 'td:nth-child(2) a/@href' => 'machine'
|
21
|
-
element 'td:nth-child(3)' => 'status'
|
22
|
-
element 'td:nth-child(4)' => 'progress'
|
23
|
-
element 'td:nth-child(5)' => 'start_time'
|
24
|
-
element 'td:nth-child(6)' => 'finish_time'
|
25
|
-
element 'td:nth-child(7)' => 'errors'
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_attempts
|
29
|
-
attempts.map do |attempt|
|
30
|
-
start_time = Time.parse(attempt.start_time) rescue nil
|
31
|
-
finish_time = attempt.finish_time.length > 0 ? Time.parse(attempt.finish_time) : nil
|
32
|
-
{
|
33
|
-
_id: attempt.attempt_id.to_s,
|
34
|
-
task_id: task_id,
|
35
|
-
host: attempt.machine.to_s.gsub(/^http:\/\//, '').gsub(/:[0-9]+$/, ''),
|
36
|
-
status: attempt.status,
|
37
|
-
progress: attempt.progress.to_f / 100.0,
|
38
|
-
start_time: start_time,
|
39
|
-
finish_time: finish_time,
|
40
|
-
duration: start_time ? (finish_time || Time.now) - start_time : nil,
|
41
|
-
errors: attempt.errors
|
42
|
-
}
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,273 +0,0 @@
|
|
1
|
-
require_relative 'configurable'
|
2
|
-
require_relative 'hadoopable'
|
3
|
-
require_relative 'hadoop_attempt_scraper'
|
4
|
-
|
5
|
-
require 'json'
|
6
|
-
require 'optparse'
|
7
|
-
require 'ostruct'
|
8
|
-
require 'logger'
|
9
|
-
require 'pp'
|
10
|
-
require 'gorillib/string/inflections'
|
11
|
-
require 'swineherd-fs'
|
12
|
-
|
13
|
-
class Vayacondios
|
14
|
-
|
15
|
-
class HadoopClient
|
16
|
-
|
17
|
-
include Configurable
|
18
|
-
include Hadoopable
|
19
|
-
|
20
|
-
RUNNING = JobStatus::RUNNING
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
init_settings
|
24
|
-
logger.info "Connecting to job tracker."
|
25
|
-
@job_client = JobClient.new JobConf.new(get_hadoop_conf)
|
26
|
-
end
|
27
|
-
|
28
|
-
#
|
29
|
-
# (Equality doesn't work for jobs, so - will not work as intended
|
30
|
-
# on arrays of jobs.)
|
31
|
-
#
|
32
|
-
def subtract jobs_array1, jobs_array2
|
33
|
-
jobs_array1.reject{|j| jobs_array2.map(&:job_id).map(&:to_s).index j.job_id.to_s}
|
34
|
-
end
|
35
|
-
|
36
|
-
#
|
37
|
-
# Returns the jobs with the specified state. States are specified
|
38
|
-
# by constants in this class.
|
39
|
-
#
|
40
|
-
def jobs_with_state state
|
41
|
-
jobs_by_state[state] || []
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# Returns the properties of the specified job as a hash.
|
46
|
-
#
|
47
|
-
def job_properties job
|
48
|
-
host_port = job.get_tracking_url[/^(http:\/\/)?[^\/]*/]
|
49
|
-
job_id = job.get_id.to_s
|
50
|
-
conf_uri = "#{host_port}/logs/#{job_id}_conf.xml"
|
51
|
-
|
52
|
-
parse_properties(open conf_uri)
|
53
|
-
end
|
54
|
-
|
55
|
-
#
|
56
|
-
# Returns the stats for the current job as a hash.
|
57
|
-
#
|
58
|
-
def job_stats job, finish_time
|
59
|
-
parse_job job.get_id, finish_time
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
#
|
65
|
-
# Returns a hash JobStatus::<SOME_STATE> => <array of jobs>
|
66
|
-
#
|
67
|
-
def jobs_by_state
|
68
|
-
job_statuses_by_state = @job_client.get_all_jobs.group_by(&:get_run_state)
|
69
|
-
Hash[job_statuses_by_state.map{|state, job_statuses| [state, jobs_from_statuses(job_statuses)]}]
|
70
|
-
end
|
71
|
-
|
72
|
-
#
|
73
|
-
# Some hadoop stuff returns JobStatus objects. This converts them
|
74
|
-
# to RunningJob objects.
|
75
|
-
#
|
76
|
-
def jobs_from_statuses job_statuses
|
77
|
-
job_statuses.map{|job_status| @job_client.get_job job_status.get_job_id}
|
78
|
-
end
|
79
|
-
|
80
|
-
#
|
81
|
-
# Takes an org.apache.hadoop.mapred.RunningJob and returns a hash
|
82
|
-
# object that represents it.
|
83
|
-
#
|
84
|
-
def parse_job job_id, finish_time
|
85
|
-
job = @job_client.get_job job_id
|
86
|
-
job_status = @job_client.get_all_jobs.select{|j| j.get_job_id.to_s == job_id.to_s}.first
|
87
|
-
finished_status = [:FAILED, :KILLED, :COMPLETE]
|
88
|
-
failed_status = [:FAILED]
|
89
|
-
|
90
|
-
|
91
|
-
# not sure what is what. I'm guessing
|
92
|
-
# JobStatus.getStartTime corresponds to the
|
93
|
-
# launch time in the logs
|
94
|
-
|
95
|
-
start_time = Time.at(job_status.get_start_time / 1000)
|
96
|
-
reduce_progress = job.reduce_progress
|
97
|
-
map_progress = job.map_progress
|
98
|
-
run_duration = (finish_time || Time.now) - start_time
|
99
|
-
|
100
|
-
map_eta = map_progress && map_progress > 0.0 ? (start_time + (run_duration / map_progress)) : nil
|
101
|
-
reduce_eta = reduce_progress && reduce_progress > 0.0 ? (start_time + (run_duration / reduce_progress)) : nil
|
102
|
-
|
103
|
-
job_data = {
|
104
|
-
|
105
|
-
_id: job_id.to_s,
|
106
|
-
name: job.get_job_name.to_s,
|
107
|
-
|
108
|
-
start_time: start_time,
|
109
|
-
finish_time: finish_time,
|
110
|
-
|
111
|
-
duration: run_duration,
|
112
|
-
|
113
|
-
map_eta: map_eta,
|
114
|
-
reduce_eta: reduce_eta,
|
115
|
-
eta: reduce_eta,
|
116
|
-
|
117
|
-
status: case job_status.get_run_state
|
118
|
-
when JobStatus::FAILED then :FAILED
|
119
|
-
when JobStatus::KILLED then :KILLED
|
120
|
-
when JobStatus::PREP then :PREP
|
121
|
-
when JobStatus::RUNNING then :RUNNING
|
122
|
-
when JobStatus::SUCCEEDED then :SUCCEEDED
|
123
|
-
end,
|
124
|
-
|
125
|
-
finished_maps: num_tasks(job_id, :map, finished_status),
|
126
|
-
finished_reduces: num_tasks(job_id, :reduce, finished_status),
|
127
|
-
failed_maps: num_tasks(job_id, :map, failed_status),
|
128
|
-
failed_reduces: num_tasks(job_id, :reduce, failed_status),
|
129
|
-
|
130
|
-
counters: parse_counters(job.get_counters)
|
131
|
-
}
|
132
|
-
|
133
|
-
job_event = {
|
134
|
-
t: Time.now,
|
135
|
-
d: {
|
136
|
-
job_id: job.job_id,
|
137
|
-
cleanup_progress: job.cleanup_progress,
|
138
|
-
map_progress: job.map_progress,
|
139
|
-
reduce_progress: job.reduce_progress,
|
140
|
-
setup_progress: job.setup_progress,
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
|
-
setup_task_data = @job_client.get_setup_task_reports job_id
|
145
|
-
map_task_data = @job_client.get_map_task_reports job_id
|
146
|
-
reduce_task_data = @job_client.get_reduce_task_reports job_id
|
147
|
-
cleanup_task_data = @job_client.get_cleanup_task_reports job_id
|
148
|
-
|
149
|
-
setup_reports = setup_task_data.map{|task| parse_task task, "SETUP", job_id }
|
150
|
-
setup_event_reports = setup_task_data.map{|task| parse_task_progress task, "SETUP" }
|
151
|
-
|
152
|
-
map_reports = map_task_data.map{|task| parse_task task, "MAP", job_id }
|
153
|
-
map_event_reports = map_task_data.map{|task| parse_task_progress task, "MAP" }
|
154
|
-
|
155
|
-
reduce_reports = reduce_task_data.map{|task| parse_task task, "REDUCE", job_id }
|
156
|
-
reduce_event_reports = reduce_task_data.map{|task| parse_task_progress task, "REDUCE" }
|
157
|
-
|
158
|
-
cleanup_reports = cleanup_task_data.map{|task| parse_task task, "CLEANUP", job_id }
|
159
|
-
cleanup_event_reports = cleanup_task_data.map{|task| parse_task_progress task, "CLEANUP" }
|
160
|
-
|
161
|
-
tasks = setup_reports + map_reports + reduce_reports + cleanup_reports
|
162
|
-
task_events = setup_event_reports + map_event_reports + reduce_event_reports + cleanup_event_reports
|
163
|
-
|
164
|
-
attempt_reports = tasks.map{|task| HadoopAttemptScraper.scrape_task(task[:_id]).to_attempts }.flatten
|
165
|
-
|
166
|
-
{
|
167
|
-
job: job_data,
|
168
|
-
job_event: job_event,
|
169
|
-
tasks: tasks,
|
170
|
-
task_events: task_events,
|
171
|
-
attempts: attempt_reports
|
172
|
-
}
|
173
|
-
end
|
174
|
-
|
175
|
-
#
|
176
|
-
# Return a hash containing a name => value hash representing the
|
177
|
-
# config for a hadoop job.
|
178
|
-
#
|
179
|
-
def parse_properties conf
|
180
|
-
properties = {}
|
181
|
-
conf.read.scan /[^\n]*\n/ do |line,|
|
182
|
-
m = /<name>([^<]+)<\/name><value>([^<]+)<\/value>/.match line
|
183
|
-
if m and m[1] !~ /fs\.s3n?\.awsSecretAccessKey/ then
|
184
|
-
properties[parse_key m[1]] = parse_atom m[2]
|
185
|
-
end
|
186
|
-
end
|
187
|
-
properties
|
188
|
-
end
|
189
|
-
|
190
|
-
#
|
191
|
-
# Takes an org.apache.hadoop.mapred.TaskReport and returns a Hash
|
192
|
-
# object that represents it.
|
193
|
-
#
|
194
|
-
def parse_task task_report, task_type, parent_job_id
|
195
|
-
start_time = task_report.get_start_time > 0 ? Time.at(task_report.get_start_time / 1000) : nil
|
196
|
-
finish_time = task_report.get_finish_time > 0 ? Time.at(task_report.get_finish_time / 1000) : nil
|
197
|
-
|
198
|
-
{
|
199
|
-
_id: task_report.get_task_id.to_s,
|
200
|
-
job_id: parent_job_id.to_s,
|
201
|
-
type: task_type,
|
202
|
-
status: task_report.get_current_status.to_s,
|
203
|
-
start_time: start_time,
|
204
|
-
finish_time: finish_time,
|
205
|
-
duration: start_time ? (finish_time || Time.now) - start_time : nil,
|
206
|
-
counters: parse_counters(task_report.get_counters),
|
207
|
-
diagnostics: task_report.get_diagnostics.map(&:to_s),
|
208
|
-
successful_attempt_id: task_report.get_successful_task_attempt.to_s
|
209
|
-
}
|
210
|
-
end
|
211
|
-
|
212
|
-
def parse_task_progress task_report, task_type
|
213
|
-
{
|
214
|
-
t: Time.now,
|
215
|
-
d: {
|
216
|
-
task_id: task_report.get_task_id.to_s,
|
217
|
-
progress: task_report.get_progress,
|
218
|
-
running_attempt_ids: task_report.get_running_task_attempts.map(&:to_s)
|
219
|
-
}
|
220
|
-
}
|
221
|
-
end
|
222
|
-
|
223
|
-
#
|
224
|
-
# Takes a class of type org.apache.hadoop.mapred.Counters and
|
225
|
-
# returns a Hash object that represents this counter.
|
226
|
-
#
|
227
|
-
def parse_counters counters
|
228
|
-
Hash[counters.map do |group|
|
229
|
-
[parse_key(group.get_name), Hash[group.map do |counter|
|
230
|
-
[parse_key(counter.get_name), counter.get_counter]
|
231
|
-
end]]
|
232
|
-
end]
|
233
|
-
end
|
234
|
-
|
235
|
-
#
|
236
|
-
# Parse a key in a log entry. Log entries consist of a type, which I
|
237
|
-
# consider a key, and a list of key=value pairs.
|
238
|
-
#
|
239
|
-
def parse_key key
|
240
|
-
return (parse_atom key).underscore.gsub ".", "_"
|
241
|
-
end
|
242
|
-
|
243
|
-
#
|
244
|
-
# Parse a value in a Hadoop log.
|
245
|
-
#
|
246
|
-
def parse_atom a
|
247
|
-
if /[0-9][ \r\t\n]*\/[ \r\t\n]*[0-9]+/.match a
|
248
|
-
# "0/6" -> [0,6]
|
249
|
-
return a.split("/").collect{|s| s.to_i}
|
250
|
-
elsif /^[0-9,]*$/.match a
|
251
|
-
# "224" -> 224
|
252
|
-
return a.gsub(',', '').to_i
|
253
|
-
else
|
254
|
-
# \. -> .
|
255
|
-
return a.gsub(/([^\\])\\(.)/, '\1\2')
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
#
|
260
|
-
# Returns the number of tasks of the specified TIPStatus from the
|
261
|
-
# specified job_client of the specified type (map or reduce)
|
262
|
-
#
|
263
|
-
def num_tasks job_id, map_or_reduce, statuses
|
264
|
-
method_name = "get_#{map_or_reduce}_task_reports".to_sym
|
265
|
-
@job_client.send(method_name, job_id).select do |report|
|
266
|
-
tip_statuses = statuses.map do |status|
|
267
|
-
TIPStatus.const_get status
|
268
|
-
end
|
269
|
-
tip_statuses.index report.get_current_status
|
270
|
-
end.size
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
@@ -1,101 +0,0 @@
|
|
1
|
-
#!/usr/bin/env jruby19
|
2
|
-
|
3
|
-
require_relative 'hadoop_client'
|
4
|
-
require_relative 'configurable'
|
5
|
-
require 'java'
|
6
|
-
require 'mongo'
|
7
|
-
require 'scanf'
|
8
|
-
require 'gorillib/hash/slice'
|
9
|
-
require 'thread'
|
10
|
-
require 'open-uri'
|
11
|
-
require 'json'
|
12
|
-
|
13
|
-
class Vayacondios
|
14
|
-
|
15
|
-
class HadoopMonitor
|
16
|
-
def initialize
|
17
|
-
init_settings
|
18
|
-
|
19
|
-
@hadoop = HadoopClient.new
|
20
|
-
|
21
|
-
@monitored_jobs = []
|
22
|
-
|
23
|
-
logger.debug "Creating mongo collections."
|
24
|
-
@conn = Mongo::Connection.new settings.mongo_ip
|
25
|
-
@db = @conn[settings.mongo_db]
|
26
|
-
|
27
|
-
capped_collection_opts = {
|
28
|
-
:capped => true,
|
29
|
-
:size => settings.mongo_collection_size
|
30
|
-
}
|
31
|
-
|
32
|
-
@collections = {
|
33
|
-
jobs: @db.create_collection('jobs'),
|
34
|
-
tasks: @db.create_collection('job_tasks'),
|
35
|
-
attempts: @db.create_collection('job_task_attempts'),
|
36
|
-
|
37
|
-
job_events: @db.create_collection('job_events', capped_collection_opts),
|
38
|
-
task_events: @db.create_collection('job_task_events', capped_collection_opts),
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
def run
|
43
|
-
loop do
|
44
|
-
|
45
|
-
logger.debug "In main event loop."
|
46
|
-
|
47
|
-
running_jobs = @hadoop.jobs_with_state HadoopClient::RUNNING
|
48
|
-
started_jobs = @hadoop.subtract(running_jobs, @monitored_jobs)
|
49
|
-
finished_jobs = @hadoop.subtract(@monitored_jobs, running_jobs)
|
50
|
-
|
51
|
-
finished_jobs.each do |job|
|
52
|
-
logger.debug "#{job.get_id.to_s} is complete."
|
53
|
-
update_job_stats job, Time.now
|
54
|
-
end
|
55
|
-
|
56
|
-
running_jobs.each{|job| update_job_stats job, nil, @hadoop.subtract([job], started_jobs).empty? }
|
57
|
-
|
58
|
-
@monitored_jobs = running_jobs
|
59
|
-
|
60
|
-
sleep settings.sleep_seconds
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
|
67
|
-
include Configurable
|
68
|
-
|
69
|
-
def update_job_stats job, finish_time = nil, include_properties = false
|
70
|
-
stats = @hadoop.job_stats(job, finish_time)
|
71
|
-
|
72
|
-
if include_properties
|
73
|
-
stats[:job][:properties] = @hadoop.job_properties job
|
74
|
-
end
|
75
|
-
|
76
|
-
logger.debug "upserting job #{JSON.generate stats[:job]}"
|
77
|
-
@collections[:jobs].update({_id: stats[:job][:_id]}, stats[:job], upsert: true)
|
78
|
-
|
79
|
-
logger.debug "upserting job_event #{JSON.generate stats[:job_event]}"
|
80
|
-
@collections[:job_events].insert(stats[:job_event])
|
81
|
-
|
82
|
-
logger.debug "upserting tasks #{JSON.generate stats[:tasks]}"
|
83
|
-
stats[:tasks].each do |task|
|
84
|
-
@collections[:tasks].update({_id: task[:_id]}, task, upsert: true)
|
85
|
-
end
|
86
|
-
|
87
|
-
logger.debug "upserting task_events #{JSON.generate stats[:task_events]}"
|
88
|
-
stats[:task_events].each do |task_event|
|
89
|
-
@collections[:task_events].insert(task_event)
|
90
|
-
end
|
91
|
-
|
92
|
-
logger.debug "upserting attempts #{JSON.generate stats[:attempts]}"
|
93
|
-
stats[:attempts].each do |attempt|
|
94
|
-
@collections[:attempts].update({_id: attempt[:_id]}, attempt, upsert: true)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
Vayacondios::HadoopMonitor.new.run
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
|
3
|
-
class Vayacondios
|
4
|
-
|
5
|
-
module Hadoopable
|
6
|
-
|
7
|
-
include Configurable
|
8
|
-
|
9
|
-
#--------------------------------------------------------------------------------
|
10
|
-
# Initialize jruby and tell it about hadoop.
|
11
|
-
#--------------------------------------------------------------------------------
|
12
|
-
|
13
|
-
begin
|
14
|
-
require 'java'
|
15
|
-
rescue LoadError => e
|
16
|
-
raise "\nJava not found. Are you sure you're running with JRuby?\n#{e.message}"
|
17
|
-
end
|
18
|
-
|
19
|
-
hadoop_home = ENV['HADOOP_HOME'] || '/usr/lib/hadoop'
|
20
|
-
|
21
|
-
raise "\nHadoop installation not found. Try setting $HADOOP_HOME\n" unless (hadoop_home and (File.exist? hadoop_home))
|
22
|
-
|
23
|
-
$CLASSPATH << File.join(File.join(hadoop_home, 'conf') || ENV['HADOOP_CONF_DIR'],
|
24
|
-
'') # add trailing slash
|
25
|
-
|
26
|
-
Dir["#{hadoop_home}/{hadoop*.jar,lib/*.jar}"].each{|jar| require jar}
|
27
|
-
|
28
|
-
include_class org.apache.hadoop.mapred.JobConf
|
29
|
-
include_class org.apache.hadoop.mapred.JobClient
|
30
|
-
include_class org.apache.hadoop.mapred.JobStatus
|
31
|
-
include_class org.apache.hadoop.mapred.TIPStatus
|
32
|
-
include_class org.apache.hadoop.conf.Configuration
|
33
|
-
#--------------------------------------------------------------------------------
|
34
|
-
|
35
|
-
def get_hadoop_conf
|
36
|
-
logger.debug "Getting hadoop configuration"
|
37
|
-
|
38
|
-
stderr, $stderr = $stderr, StringIO.new
|
39
|
-
|
40
|
-
conf = Configuration.new
|
41
|
-
|
42
|
-
# per-site defaults
|
43
|
-
%w[capacity-scheduler.xml core-site.xml hadoop-policy.xml hadoop-site.xml hdfs-site.xml mapred-site.xml].each do |conf_file|
|
44
|
-
conf.addResource conf_file
|
45
|
-
end
|
46
|
-
|
47
|
-
conf.reload_configuration
|
48
|
-
|
49
|
-
# per-user overrides
|
50
|
-
if Swineherd.config[:aws]
|
51
|
-
conf.set("fs.s3.awsAccessKeyId",Swineherd.config[:aws][:access_key])
|
52
|
-
conf.set("fs.s3.awsSecretAccessKey",Swineherd.config[:aws][:secret_key])
|
53
|
-
|
54
|
-
conf.set("fs.s3n.awsAccessKeyId",Swineherd.config[:aws][:access_key])
|
55
|
-
conf.set("fs.s3n.awsSecretAccessKey",Swineherd.config[:aws][:secret_key])
|
56
|
-
end
|
57
|
-
|
58
|
-
return conf
|
59
|
-
ensure
|
60
|
-
stderr_lines = $stderr.string.split("\n")
|
61
|
-
$stderr = stderr
|
62
|
-
stderr_lines.each{|line| logger.debug line}
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|