Skip to content

Commit

Permalink
Merge pull request github-linguist#2173 from github/moar-instrumentation
Browse files Browse the repository at this point in the history
Instrument all calls and pass the blob, strategy and language candidates in the payload.
  • Loading branch information
arfon committed Mar 5, 2015
2 parents fd76335 + a1010b8 commit 9ceea4a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 14 deletions.
2 changes: 1 addition & 1 deletion lib/linguist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def instrument(*args, &bk)
if instrumenter
instrumenter.instrument(*args, &bk)
else
yield
yield if block_given?
end
end
end
8 changes: 3 additions & 5 deletions lib/linguist/classifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ class Classifier
#
# Returns an Array of Language objects, most probable first.
def self.call(blob, possible_languages)
Linguist.instrument("linguist.bayesian_classification") do
language_names = possible_languages.map(&:name)
classify(Samples.cache, blob.data, language_names).map do |name, _|
Language[name] # Return the actual Language objects
end
language_names = possible_languages.map(&:name)
classify(Samples.cache, blob.data, language_names).map do |name, _|
Language[name] # Return the actual Language objects
end
end

Expand Down
26 changes: 18 additions & 8 deletions lib/linguist/language.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,30 @@ def self.detect(blob)
# Bail early if the blob is binary or empty.
return nil if blob.likely_binary? || blob.binary? || blob.empty?

Linguist.instrument("linguist.detection") do
Linguist.instrument("linguist.detection", :blob => blob) do
# Call each strategy until one candidate is returned.
STRATEGIES.reduce([]) do |languages, strategy|
candidates = strategy.call(blob, languages)
languages = []
returning_strategy = nil

STRATEGIES.each do |strategy|
returning_strategy = strategy
candidates = Linguist.instrument("linguist.strategy", :blob => blob, :strategy => strategy, :candidates => languages) do
strategy.call(blob, languages)
end
if candidates.size == 1
return candidates.first
languages = candidates
break
elsif candidates.size > 1
# More than one candidate was found, pass them to the next strategy.
candidates
languages = candidates
else
# No candiates were found, pass on languages from the previous strategy.
languages
# No candidates, try the next strategy
end
end.first
end

Linguist.instrument("linguist.detected", :blob => blob, :strategy => returning_strategy, :language => languages.first)

languages.first
end
end

Expand Down
50 changes: 50 additions & 0 deletions test/test_instrumentation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require_relative "./helper"

class TestInstrumentation < Minitest::Test
include Linguist

class LocalInstrumenter
Event = Struct.new(:name, :args)

attr_reader :events

def initialize
@events = []
end

def instrument(name, *args)
@events << Event.new(name, args)
yield if block_given?
end
end

def setup
Linguist.instrumenter = LocalInstrumenter.new
end

def teardown
Linguist.instrumenter = nil
end

def test_detection_instrumentation_with_binary_blob
binary_blob = fixture_blob("Binary/octocat.ai")
Language.detect(binary_blob)

# Shouldn't instrument this (as it's binary)
assert_equal 0, Linguist.instrumenter.events.size
end

def test_modeline_instrumentation
blob = fixture_blob("Data/Modelines/ruby")
Language.detect(blob)

detect_event = Linguist.instrumenter.events.last
detect_event_payload = detect_event[:args].first

assert_equal 3, Linguist.instrumenter.events.size
assert_equal "linguist.detected", detect_event.name
assert_equal Language['Ruby'], detect_event_payload[:language]
assert_equal blob, detect_event_payload[:blob]
assert_equal Linguist::Strategy::Modeline, detect_event_payload[:strategy]
end
end

0 comments on commit 9ceea4a

Please sign in to comment.