Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don't worry, you can still create the pull request.
  • 10 commits
  • 10 files changed
  • 0 commit comments
  • 2 contributors
Commits on Dec 28, 2011
@eric eric Reorganize classes 7b8c481
Commits on Feb 12, 2012
@eric eric Fix puts 9a44fdb
@eric eric Merge pull request #5 from papertrail/reorganization
Reorganize classes
a093b94
@eric eric Release 0.8.2 ed100da
@eric eric Release 0.8.3 75e7e4c
@eric eric Update README 116aa3e
@eric eric More small README fixes 1457f88
@eric eric Depend on faraday_middleware instead of faraday-stack 393638f
@eric eric Release 0.8.4 ec72a49
Commits on Feb 14, 2012
@kanevski Merge branch 'master' of https://github.com/papertrail/papertrail-cli
Made configuration parameters cascade in a more natural order:
defaults -> YAML -> CLI

Conflicts:
	bin/papertrail
	lib/papertrail/search_client.rb
26a3680
View
20 README.md
@@ -1,4 +1,4 @@
-# papertrail Command-line tail & search client for Papertrail log management service
+# papertrail command-line tail & search client for Papertrail log management service
Small standalone [binary] to retrieve, search, and tail recent app
server log and system syslog messages from [Papertrail].
@@ -6,19 +6,19 @@ server log and system syslog messages from [Papertrail].
Supports optional Boolean search queries and polling for new events
(like "tail -f"). Example:
- papertrail -f "(www OR db) (nginx OR pgsql) -accepted"
+ $ papertrail -f "(www OR db) (nginx OR pgsql) -accepted"
Output is line-buffered so it can be fed into a pipe, like for grep.
See below for colorization setup.
-The [SearchClient] class can be used by other apps to perform one-off
+The [Connection] class can be used by other apps to perform one-off
API searches or follow (tail) events matching a given query. Interface
may change.
## Quick Start
- $ [sudo] gem install papertrail-cli
+ $ [sudo] gem install papertrail
$ echo "token: 123456789012345678901234567890ab" > ~/.papertrail.yml
$ papertrail
@@ -27,10 +27,10 @@ Retrieve token from Papertrail [User Profile].
## Installation
-Install the gem (details on [RubyGems]), which includes a binary called
+Install the gem (details on [RubyGems]), which includes a binary called
"papertrail":
- $ [sudo] gem install papertrail-cli
+ $ [sudo] gem install papertrail
## Configuration
@@ -41,7 +41,7 @@ examples/papertrail.yml.example):
token: 123456789012345678901234567890ab
-Retrieve token from Papertrail [User Profile]. For compatibility with
+Retrieve token from Papertrail [User Profile]. For compatibility with
older config files, `username` and `password` keys are also supported.
You may want to alias "trail" to "papertrail", like:
@@ -82,7 +82,7 @@ Save [colortailrc] as `~/.colortailrc` and edit it to enable:
### Shorthand
-If you're using bash, create a function that accepts arguments, then
+If you're using bash, create a function that accepts arguments, then
invoke `pt` with optional search operators:
$ function pt() { papertrail -f -d 5 $_ | colortail -g papertrail }
@@ -116,13 +116,13 @@ Enhancement or fix:
1. Fork the project:
http://github.com/papertrail/papertrail-cli
2. Make your changes with tests.
-3. Commit the changes without changing the Rakefile or other files unrelated
+3. Commit the changes without changing the Rakefile or other files unrelated
to your enhancement.
4. Send a pull request.
[binary]: https://github.com/papertrail/papertrail-cli/blob/master/bin/papertrail
[Papertrail]: http://papertrailapp.com/
-[SearchClient]: https://github.com/papertrail/papertrail-cli/blob/master/lib/papertrail/search_client.rb
+[Connection]: https://github.com/papertrail/papertrail-cli/blob/master/lib/papertrail/connection.rb
[User Profile]: https://papertrailapp.com/user/edit
[RubyGems]: https://rubygems.org/gems/papertrail-cli
[colortail]: http://rubydoc.info/gems/colortail
View
100 bin/papertrail
@@ -1,104 +1,8 @@
#!/usr/bin/env ruby
-
-require 'optparse'
-require 'yaml'
-
-require 'papertrail-cli'
-
-class PapertrailSearch
- def run
- options = {
- :configfile => configfile_path,
- :delay => 10,
- :follow => false
- }
-
- OptionParser.new do |opts|
- opts.banner = "papertrail - command-line tail and search for Papertrail log management service"
-
- opts.on("-h", "--help", "Show usage") do |v|
- puts opts
- exit
- end
- opts.on("-f", "--follow", "Continue running and print new events (off)") do |v|
- options[:follow] = true
- end
- opts.on("-d", "--delay SECONDS", "Delay between refresh (3)") do |v|
- options[:delay] = v.to_i
- end
- opts.on("-c", "--configfile PATH", "Path to config (~/.papertrail.yml)") do |v|
- options[:configfile] = File.expand_path(v)
- end
-
- opts.separator usage
- end.parse!
-
- configfile_options = open(options[:configfile]) do |f|
- YAML.load(f)
- end
- configfile_options = symbolize_keys(configfile_options)
- options.merge!(configfile_options)
-
- client = Papertrail::SearchClient.new(options)
-
- search_and_print(client)
-
- if options[:follow]
- loop do
- sleep options[:delay]
- search_and_print(client)
- end
- end
- end
-
- def search_and_print(client)
- events = client.search(ARGV[0])
- return unless events
-
- Papertrail::SearchClient.format_events(events) do |e|
- puts e
- $stdout.flush
- end
- end
-
- def configfile_path
- if File.exists?(file_name = '.papertrail.yml')
- file_path = File.expand_path(file_name)
- else
- file_path = File.expand_path('~/.papertrail.yml')
- end
-
- file_path
- end
-
- def symbolize_keys(hash)
- new_hash = {}
- hash.each_key do |key|
- new_hash[(key.to_sym rescue key) || key] = hash[key]
- end
- new_hash
- end
-
- def usage
- <<EOF
-
-Usage: papertrail [-f] [-d seconds] [-c /path/to/papertrail.yml] [query]
-
-Examples:
- papertrail -f
- papertrail something
- papertrail 1.2.3 Failure
- papertrail -f "(www OR db) (nginx OR pgsql) -accepted"
- papertrail -f -d 10 "ns1 OR 'connection refused'"
-
-More: https://papertrailapp.com/
-
-EOF
- end
-end
+require 'papertrail/cli'
begin
- PapertrailSearch.new.run
+ Papertrail::Cli.new.run
rescue Interrupt
exit(0)
end
View
4 lib/papertrail-cli.rb → lib/papertrail.rb
@@ -1,5 +1,5 @@
-module PapertrailCli
- VERSION = "0.8.2"
+module Papertrail
+ VERSION = "0.8.4"
end
require 'papertrail/search_client'
View
122 lib/papertrail/cli.rb
@@ -0,0 +1,122 @@
+require 'optparse'
+require 'yaml'
+
+require 'papertrail/connection'
+
+module Papertrail
+ class Cli
+ def run
+ options = {
+ :configfile => nil,
+ :delay => 10,
+ :follow => false
+ }
+
+ if configfile = find_configfile
+ configfile_options = load_configfile(configfile)
+ options.merge!(configfile_options)
+ end
+
+ OptionParser.new do |opts|
+ opts.banner = "papertrail - command-line tail and search for Papertrail log management service"
+
+ opts.on("-h", "--help", "Show usage") do |v|
+ puts opts
+ exit
+ end
+ opts.on("-f", "--follow", "Continue running and print new events (off)") do |v|
+ options[:follow] = true
+ end
+ opts.on("-d", "--delay SECONDS", "Delay between refresh (2)") do |v|
+ options[:delay] = v.to_i
+ end
+ opts.on("-c", "--configfile PATH", "Path to config (~/.papertrail.yml)") do |v|
+ options[:configfile] = File.expand_path(v)
+ end
+ opts.on("-s", "--system SYSTEM", "System to search") do |v|
+ options[:system] = v
+ end
+ opts.on("-g", "--group GROUP", "Group to search") do |v|
+ options[:group] = v
+ end
+
+ opts.separator usage
+ end.parse!
+
+ if options[:configfile]
+ configfile_options = load_configfile(options[:configfile])
+ options.merge!(configfile_options)
+ end
+
+ connection = Papertrail::Connection.new(options)
+
+ query_options = {}
+
+ if options[:system]
+ query_options[:system_id] = connection.find_id_for_source(options[:system])
+ end
+
+ if options[:group]
+ query_options[:group_id] = connection.find_id_for_group(options[:group])
+ end
+
+ search_query = connection.query(ARGV[0], query_options)
+
+ if options[:follow]
+ loop do
+ search_query.search.events.each do |event|
+ $stdout.puts event
+ end
+ $stdout.flush
+ sleep options[:delay]
+ end
+ else
+ search_query.search.events.each do |event|
+ $stdout.puts event
+ end
+ end
+ end
+
+ def find_configfile
+ if File.exists?(path = File.expand_path('.papertrail.yml'))
+ return path
+ end
+ if File.exists?(path = File.expand_path('~/.papertrail.yml'))
+ return path
+ end
+
+ false
+ end
+
+ def load_configfile(file_path)
+ configfile_options = open(file_path) { |f| YAML.load(f) }
+ symbolize_keys(configfile_options)
+ end
+
+ def symbolize_keys(hash)
+ new_hash = {}
+ hash.each_key do |key|
+ new_hash[(key.to_sym rescue key) || key] = hash[key]
+ end
+
+ new_hash
+ end
+
+ def usage
+ <<-EOF
+
+ Usage: papertrail [-f] [-d seconds] [-c /path/to/papertrail.yml] [query]
+
+ Examples:
+ papertrail -f
+ papertrail something
+ papertrail 1.2.3 Failure
+ papertrail -f "(www OR db) (nginx OR pgsql) -accepted"
+ papertrail -f -d 10 "ns1 OR 'connection refused'"
+
+ More: https://papertrailapp.com/
+
+ EOF
+ end
+ end
+end
View
66 lib/papertrail/connection.rb
@@ -0,0 +1,66 @@
+require 'faraday'
+require 'openssl'
+require 'faraday_middleware'
+require 'yajl/json_gem'
+
+require 'papertrail/search_query'
+
+module Papertrail
+ class Connection
+ extend Forwardable
+
+ attr_reader :connection
+
+ def_delegators :@connection, :get, :put, :post
+
+ def initialize(options)
+ ssl_options = {
+ :verify => options.fetch(:verify_ssl) { OpenSSL::SSL::VERIFY_PEER }
+ }
+
+ # Make Ubuntu OpenSSL work
+ #
+ # From: https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/396818
+ # "[OpenSSL] does not presume to select a set of CAs by default."
+ if File.file?('/etc/ssl/certs/ca-certificates.crt')
+ ssl_options[:ca_file] = '/etc/ssl/certs/ca-certificates.crt'
+ end
+
+ @connection = Faraday::Connection.new(:url => 'https://papertrailapp.com', :ssl => ssl_options) do |builder|
+ builder.adapter Faraday.default_adapter
+ builder.use Faraday::Response::RaiseError
+ builder.use FaradayMiddleware::ParseJson, :content_type => /\bjson$/
+ end.tap do |conn|
+ if options[:username] && options[:password]
+ conn.basic_auth(options[:username], options[:password])
+ else
+ conn.headers['X-Papertrail-Token'] = options[:token]
+ end
+ end
+ end
+
+ def find_id_for_source(name)
+ response = @connection.get('/api/v1/systems.json')
+
+ response.body.each do |source|
+ return source['id'] if source['name'] =~ /#{Regexp.escape(name)}/i
+ end
+
+ return nil
+ end
+
+ def find_id_for_group(name)
+ response = @connection.get('/api/v1/groups.json')
+
+ response.body.each do |group|
+ return group['id'] if group['name'] =~ /#{Regexp.escape(name)}/i
+ end
+
+ return nil
+ end
+
+ def query(query = nil, options = {})
+ Papertrail::SearchQuery.new(self, query, options)
+ end
+ end
+end
View
15 lib/papertrail/event.rb
@@ -0,0 +1,15 @@
+require 'time'
+
+module Papertrail
+ class Event
+ attr_reader :data
+
+ def initialize(data)
+ @data = data
+ end
+
+ def to_s
+ "#{Time.parse(data['received_at']).strftime('%b %e %X')} #{data['hostname']} #{data['program']}: #{data['message']}"
+ end
+ end
+end
View
60 lib/papertrail/search_client.rb
@@ -1,60 +0,0 @@
-require 'faraday'
-require 'time'
-require 'openssl'
-require 'faraday_stack'
-
-module Papertrail
- class SearchClient
- def initialize(options)
- ssl_options = { :verify => options.fetch(:verify_ssl) { OpenSSL::SSL::VERIFY_PEER } }
-
- # Make Ubuntu OpenSSL work
- #
- # From: https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/396818
- # "[OpenSSL] does not presume to select a set of CAs by default."
- if File.file?('/etc/ssl/certs/ca-certificates.crt')
- ssl_options[:ca_file] = '/etc/ssl/certs/ca-certificates.crt'
- end
-
- @conn = Faraday::Connection.new(:url => 'https://papertrailapp.com', :ssl => ssl_options) do |builder|
- builder.adapter Faraday.default_adapter
- builder.use FaradayStack::ResponseJSON
- end.tap do |conn|
- if options[:username] && options[:password]
- conn.basic_auth(options[:username], options[:password])
- else
- conn.headers['X-Papertrail-Token'] = options[:token]
- end
- end
-
- @max_id_seen = {}
- end
-
- # search for all events or a specific query, defaulting to all events since
- # last result set (call with since=0 for all).
- def search(q = nil, since = nil)
- response = @conn.get('/api/v1/events/search.json') do |r|
- r.params = params_for_query(q, since)
- end
-
- if response.body
- @max_id_seen[q] = response.body['max_id']
- response.body['events']
- end
- end
-
- def params_for_query(q = nil, since = nil)
- params = {}
- params[:q] = q if q
- params[:min_id] = @max_id_seen[q] if @max_id_seen[q]
- params[:min_id] = since if since
- params
- end
-
- def self.format_events(events, &block)
- events.each do |event|
- yield "#{Time.parse(event['received_at']).strftime('%b %e %X')} #{event['hostname']} #{event['program']} #{event['message']}"
- end
- end
- end
-end
View
23 lib/papertrail/search_query.rb
@@ -0,0 +1,23 @@
+require 'papertrail/search_result'
+
+module Papertrail
+ class SearchQuery
+ def initialize(connection, query = nil, options = {})
+ @connection = connection
+ @query = query
+ @options = options
+ end
+
+ def search
+ response = @connection.get('/api/v1/events/search.json') do |r|
+ r.params = @options.dup
+
+ r.params[:q] = @query if @query
+ r.params[:min_id] = @max_id if @max_id
+ end
+
+ @max_id = response.body['max_id']
+ Papertrail::SearchResult.new(response.body)
+ end
+ end
+end
View
23 lib/papertrail/search_result.rb
@@ -0,0 +1,23 @@
+require 'papertrail/event'
+
+module Papertrail
+ class SearchResult
+ attr_reader :data, :events
+
+ def initialize(data)
+ @data = data
+
+ @events = @data['events'].collect do |event|
+ Papertrail::Event.new(event)
+ end
+ end
+
+ def max_id
+ @data['max_id']
+ end
+
+ def min_id
+ @data['min_id']
+ end
+ end
+end
View
22 papertrail-cli.gemspec → papertrail.gemspec
@@ -12,10 +12,10 @@ Gem::Specification.new do |s|
## Leave these as is they will be modified for you by the rake gemspec task.
## If your rubyforge_project name is different, then edit it and comment out
## the sub! line in the Rakefile
- s.name = 'papertrail-cli'
- s.version = '0.8.2'
- s.date = '2011-11-25'
- s.rubyforge_project = 'papertrail-cli'
+ s.name = 'papertrail'
+ s.version = '0.8.4'
+ s.date = '2012-02-11'
+ s.rubyforge_project = 'papertrail'
## Make sure your summary is short. The description may be as long
## as you like.
@@ -50,8 +50,8 @@ Gem::Specification.new do |s|
## List your runtime dependencies here. Runtime dependencies are those
## that are needed for an end user to actually USE your code.
s.add_dependency('yajl-ruby')
- s.add_dependency('faraday', [ '~> 0.6' ])
- s.add_dependency('faraday-stack', [ '~> 0.1' ])
+ s.add_dependency('faraday', [ '>= 0.6', '< 0.9' ])
+ s.add_dependency('faraday_middleware', [ '~> 0.8.4' ])
## List your development dependencies here. Development dependencies are
## those that are only needed during development
@@ -67,9 +67,13 @@ Gem::Specification.new do |s|
Rakefile
bin/papertrail
examples/papertrail.yml.example
- lib/papertrail-cli.rb
- lib/papertrail/search_client.rb
- papertrail-cli.gemspec
+ lib/papertrail.rb
+ lib/papertrail/cli.rb
+ lib/papertrail/connection.rb
+ lib/papertrail/event.rb
+ lib/papertrail/search_query.rb
+ lib/papertrail/search_result.rb
+ papertrail.gemspec
]
# = MANIFEST =

No commit comments for this range

Something went wrong with that request. Please try again.