logstream 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ data.tar.gz: 7733c436237beeea2f4209b81ea8881ca3ae9f54
4
+ metadata.gz: 0cbaedb3f433566f0acd608d0ff8f603ca3b04ed
5
+ SHA512:
6
+ data.tar.gz: 9105340c5ed3125164d618f3d5c1df4e3a156cd182ec1c57ef72f5315bc9bca98244a98a835abaca18f5e2c4fd509d073ffc8e2faa08c9c6f8b4d1d60ef20ce9
7
+ metadata.gz: a9b1e85f263b64e7a907a9efbe0ed8172d1a106a4410593ce01942592a85ad60c4f06b13e26beee40cb865fa7ff093ca3d02f336d8b6023bc04ebb759647e06c
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ logstream (0.0.1)
5
+ faye-websocket (~> 0.7.2)
6
+ json (~> 1.7.7)
7
+ thor (~> 0.19.1)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ eventmachine (1.0.3)
13
+ faye-websocket (0.7.2)
14
+ eventmachine (>= 0.12.0)
15
+ websocket-driver (>= 0.3.1)
16
+ json (1.7.7)
17
+ thor (0.19.1)
18
+ websocket-driver (0.3.2)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ logstream!
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Acquia, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # Logstream
2
+
3
+ Logstream is an Acquia service for streaming logs from Acquia Cloud. It
4
+ supports streaming a variety of log sources:
5
+
6
+ * Web (Apache) access and error logs
7
+ * PHP error log
8
+ * Acquia Cloud's Drupal Request log
9
+ * Drupal watchdog log (if the syslog.module is enabled)
10
+ * Varnish cache logs
11
+
12
+ This repository contains a client-side library and CLI. Acquia Cloud provides
13
+ <a href="https://docs.acquia.com/cloud/configure/logging">a browser-based
14
+ UI</a> as well.
15
+
16
+ ## Quick start
17
+
18
+ * Logstream works in conjunction with Acquia's <a
19
+ href="http://cloudapi.acquia.com/">Cloud API</a>. If you haven't already,
20
+ install your <a href="https://accounts.acquia.com/account/security">Acquia
21
+ Cloud Drush integration</a> files, which includes your Cloud API credentials.
22
+
23
+ * Install the Logstream CLI:
24
+ ```
25
+ $ gem install logstream
26
+ ```
27
+
28
+ * List all the sites you have access to:
29
+ ```
30
+ $ drush ac-site-list
31
+ devcloud:mysite
32
+ ```
33
+
34
+ * Stream logs from the production environment:
35
+ ```
36
+ $ logstream tail devcloud:mysite prod
37
+ 127.0.0.1 - - [11/Jun/2014:17:28:47 +0000] "GET / HTTP/1.1" 200 7708 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" http_host=mysite.com affinity="-" upstream_addr="10.218.29.150:80" hosting_site=mysite request_time=0.030 forwarded_for="64.80.128.4" upstream_status="200"
38
+ ... etc ...
39
+ ```
40
+
41
+ A variety of filtering and display options are available:
42
+
43
+ ```
44
+ $ logstream help tail
45
+ ```
46
+
47
+ ## API v1
48
+
49
+ Logstream communicates over TCP using the WebSocket protocol. Use the <a
50
+ href="http://cloudapi.acquia.com/#GET__sites__site_envs__env_logstream-instance_route">logstream
51
+ Cloud API call</a> to retrieve the URL to connect to and an authenticated
52
+ message to initial streaming for a particular Cloud environment.
53
+
54
+ Messages use text data frames, and contain JSON-encoded hashes. Each message
55
+ contains a key 'cmd' which specifies the action to perform, and defines the
56
+ other elements of the hash.
57
+
58
+ Available commands are defined in the following subsections. Inbound
59
+ commands can arrive from the upstream client (end-user client, or an
60
+ upstream logtailor). Outbound commands are sent to the upstream client.
61
+
62
+ ### success (outbound)
63
+
64
+ Sent by a variety of commands when a triggering command is completed
65
+ successfully (failures result in an error command). Since some commands execute
66
+ on multiple servers, a single command may generate multiple success
67
+ replies. Parameters:
68
+
69
+ * msg: the message that succeeded
70
+
71
+ ### error (outbound)
72
+
73
+ Sent when an error occurs, either because of a bad request or any kind of
74
+ system or network failure. Since some commands execute on multiple servers, a
75
+ single command may generate multiple error replies. Parameters:
76
+
77
+ * code: an HTTP-like status code; i.e.: 400 means your fault, 500 means our
78
+ fault.
79
+ * description: a human-readable description of the error condition
80
+ * during: the operation that triggered the error
81
+
82
+ ### connected (outbound)
83
+
84
+ Sent upon initial connection to a server. Parameters:
85
+
86
+ * server: the name of the connected server
87
+
88
+ ### available (outbound)
89
+
90
+ Sent to indicate an available log source. Parameters:
91
+
92
+ * type: the log type (e.g. apache-access)
93
+ * display: the suggested display name for the log type (e.g. "Apache access")
94
+ * server: the originating server for this stream
95
+
96
+ ### list-available (inbound) and list-availabe (outbound)
97
+
98
+ Requests a list of all available log sources from one specified server or all
99
+ servers. Parameters:
100
+
101
+ * server: the originating server to list; if not specified, all
102
+ connected servers will reply.
103
+
104
+ One or all servers will send available messages for each available log source.
105
+
106
+ ### enable (inbound)
107
+
108
+ Starts streaming a specific source previously offered via an
109
+ "available" command. Parameters:
110
+
111
+ * type: the log type to start streaming
112
+ * server: the originating server to stream from
113
+
114
+ Sends a success or error reply.
115
+
116
+ ### disable (inbound)
117
+
118
+ Stops streaming from an enabled source. Parameters:
119
+
120
+ * type: the log type to stop streaming
121
+ * server: the originating server to stream from
122
+
123
+ Sends a success or error reply.
124
+
125
+ ### list-enabled (inbound) and list-enabled (outbound)
126
+
127
+ Requests a list of all enabled log sources from one specified server or all
128
+ servers. Parameters:
129
+
130
+ * server: the originating server to list; if not specified, all
131
+ connected servers will reply.
132
+
133
+ One or all servers will send a list-enabled reply. Parameters:
134
+
135
+ * enabled: an array of enabled log sources
136
+ * server: the server these logs are enabled on
137
+
138
+ ### line (outbound)
139
+
140
+ Sent when a new, enabled line of log data is available. Parameters:
141
+
142
+ * type: the log type for this line (e.g. apache-access)
143
+ * server: this line's originating server name (e.g. web-1).
144
+ * unix_time: the Unix timestamp for this log line
145
+ * disp_time: the formatted display time for this log line
146
+ * text: the log text
147
+
148
+ Line messages may also contain other data depending on the log type:
149
+
150
+ * http_status: the HTTP status code, if the log line records an HTTP request
151
+ (e.g. from Apache, nginx, Varnish, etc)
152
+
data/bin/logstream ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'net/https'
5
+ require 'json'
6
+ require 'thor'
7
+ require 'logstream/client'
8
+
9
+ class QuickCloudAPI
10
+ class Error < StandardError; end
11
+
12
+ def self.get(path, opts = {})
13
+ confpath = "#{ENV['HOME']}/.acquia/cloudapi.conf"
14
+ begin
15
+ json = File.read(confpath)
16
+ config = JSON.load(json)
17
+ rescue Errno::ENOENT, JSON::ParserError => e
18
+ raise Error, "#{confpath} is missing or invalid. Download your Drush aliases from https://accounts.acquia.com/account/security to initialize it."
19
+ end
20
+ opts[:endpoint] ||= "https://cloudapi.acquia.com/v1"
21
+ uri = URI.parse("#{opts[:endpoint]}#{path}.json")
22
+ http = Net::HTTP.new(uri.host, uri.port)
23
+ http.use_ssl = true
24
+ http.ca_file = File.dirname(__FILE__) + "/../etc/ca.pem"
25
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
26
+ request = Net::HTTP::Get.new(uri.request_uri)
27
+ request.basic_auth(config['email'], config['key'])
28
+ response = http.request(request)
29
+ parsed = JSON.parse(response.body) rescue nil
30
+ case response.code.to_i
31
+ when 200
32
+ raise Error, "Unexpected reply #{response.body}" unless parsed
33
+ parsed
34
+ else
35
+ raise Error, "HTTP #{response.code}: #{response.body}"
36
+ end
37
+ end
38
+ end
39
+
40
+ class LogTailorCLI < Thor
41
+ desc "tail SITE ENV", "Stream log information for the specified site environment."
42
+ method_option(:types, :type => :array, :aliases => '-t',
43
+ :desc => "Only display listed log types",
44
+ :default => %w(apache-access php-error drupal-watchdog),
45
+ :banner => "apache-access apache-error php-error drupal-request drupal-watchdog bal-access"
46
+ )
47
+ method_option(:show, :type => :array, :aliases => '-s',
48
+ :desc => "Fow rows containing the column, only show them if the column matches the regexp.",
49
+ :banner => "column=regexp ..."
50
+ )
51
+ method_option(:hide, :type => :array, :aliases => '-h',
52
+ :desc => "For rows containing a column, do not show them if the column matches the regexp.",
53
+ :banner => "column=regexp ..."
54
+ )
55
+ method_option(:columns, :type => :array, :aliases => '-c',
56
+ :desc => "Display the specified columns.",
57
+ :default => %w(text),
58
+ :banner => "type disp_time unix_time text server http_status"
59
+ )
60
+ method_option(:color, :type => :boolean, :default => true, :desc => 'Turn on or off colorized lines.')
61
+ method_option(:endpoint, :type => :string, :desc => 'The Cloud API URL to connect to.')
62
+ def tail(site, env)
63
+ begin
64
+ shows = Hash[options[:show].map { |s| s.split('=') }.map { |k,v| [k, Regexp.new(v)] }] rescue {}
65
+ hides = Hash[options[:hide].map { |h| h.split('=') }.map { |k,v| [k, Regexp.new(v)] }] rescue {}
66
+
67
+ begin
68
+ info = QuickCloudAPI.get("/sites/#{site}/envs/#{env}/logstream", { :endpoint => options[:endpoint] })
69
+ logstream = Logstream::Client.new({
70
+ :columns => options[:columns],
71
+ :shows => shows,
72
+ :hides => hides,
73
+ :no_color => !options[:color],
74
+ })
75
+ logstream.run(info['url'], info['msg'])
76
+ rescue QuickCloudAPI::Error => e
77
+ puts "Cloud API error: #{e.message}"
78
+ exit(1)
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ LogTailorCLI.start
85
+
data/etc/ca.pem ADDED
@@ -0,0 +1,89 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIGVTCCBT2gAwIBAgIQCFH5WYFBRcq94CTiEsnCDjANBgkqhkiG9w0BAQUFADBs
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5
+ ZSBFViBSb290IENBMB4XDTA3MDQwMzAwMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
6
+ MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
7
+ LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
8
+ Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
9
+ CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
10
+ KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
11
+ BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
12
+ 1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
13
+ zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
14
+ 32duXvsCAwEAAaOCAvcwggLzMA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
15
+ ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
16
+ LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
17
+ AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
18
+ AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
19
+ AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
20
+ AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
21
+ AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
22
+ AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
23
+ AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
24
+ AHIAZQBuAGMAZQAuMA8GA1UdEwEB/wQFMAMBAf8wNAYIKwYBBQUHAQEEKDAmMCQG
25
+ CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSBhzCB
26
+ hDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFz
27
+ c3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu
28
+ Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSMEGDAW
29
+ gBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUBINTe
30
+ eZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAF1PhPGoiNOjsrycbeUpSXfh59bcqdg1
31
+ rslx3OXb3J0kIZCmz7cBHJvUV5eR13UWpRLXuT0uiT05aYrWNTf58SHEW0CtWakv
32
+ XzoAKUMncQPkvTAyVab+hA4LmzgZLEN8rEO/dTHlIxxFVbdpCJG1z9fVsV7un5Tk
33
+ 1nq5GMO41lJjHBC6iy9tXcwFOPRWBW3vnuzoYTYMFEuFFFoMg08iXFnLjIpx2vrF
34
+ EIRYzwfu45DC9fkpx1ojcflZtGQriLCnNseaIGHr+k61rmsb5OPs4tk8QUmoIKRU
35
+ 9ZKNu8BVIASm2LAXFszj0Mi0PeXZhMbT9m5teMl5Q+h6N/9cNUm/ocU=
36
+ -----END CERTIFICATE-----
37
+ -----BEGIN CERTIFICATE-----
38
+ MIIEQjCCA6ugAwIBAgIEQodApTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
39
+ VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
40
+ ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
41
+ KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
42
+ ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEw
43
+ MDEwNTAwMDBaFw0xNDA3MjYxODE1MTVaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
44
+ EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV
45
+ BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG
46
+ SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD
47
+ 1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt
48
+ cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46
49
+ OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd
50
+ HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm
51
+ t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET
52
+ MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr
53
+ BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo
54
+ dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v
55
+ Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU
56
+ mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7
57
+ UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF
58
+ BQADgYEASA4rbyBiTCiToyQ9WKshz4D4mpeQaiLtWnxHNpnneYR1qySPkgrVYQSu
59
+ w2pcsszZ5ESHb9uPOGL3RDadurxuB8TUjegf0Qtgo7WczmO+7Wfc+Lrebskly1u1
60
+ nXZwC99CcvhPQRFkpdLq/NWvEfQVOGecIKhLd1qRMkIy54Wz3zY=
61
+ -----END CERTIFICATE-----
62
+ -----BEGIN CERTIFICATE-----
63
+ MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
64
+ VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
65
+ ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
66
+ KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
67
+ ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
68
+ MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
69
+ ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
70
+ b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
71
+ bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
72
+ U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
73
+ A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
74
+ I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
75
+ wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
76
+ AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
77
+ oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
78
+ BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
79
+ dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
80
+ MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
81
+ b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
82
+ dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
83
+ MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
84
+ E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
85
+ MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
86
+ hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
87
+ 95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
88
+ 2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
89
+ -----END CERTIFICATE-----
data/lib/logstream.rb ADDED
@@ -0,0 +1 @@
1
+ require 'logstream/client'
@@ -0,0 +1,126 @@
1
+ require 'faye/websocket'
2
+ require 'logger'
3
+ require 'json'
4
+
5
+ module Logstream
6
+ class Client
7
+ def initialize(opts = {})
8
+ opts = {
9
+ :logger => Logger.new(STDOUT),
10
+ :log_prefix => '',
11
+ :shows => {},
12
+ :hides => {},
13
+ :columns => [ 'text' ],
14
+ :no_color => false,
15
+ :debug => false,
16
+ }.merge(opts)
17
+ @opts = opts
18
+ @columns = {
19
+ :type => "%-15s",
20
+ :disp_time => "%s",
21
+ :server => "%-8s",
22
+ :text => "%s",
23
+ }
24
+ end
25
+
26
+ def debug(msg)
27
+ if @opts[:debug]
28
+ color('logtailor-debug', nil) do
29
+ puts msg
30
+ end
31
+ end
32
+ end
33
+
34
+ def run(url, connect_message)
35
+ EM.run do
36
+ debug(url)
37
+ ws = Faye::WebSocket::Client.new(url)
38
+ ws.on :open do
39
+ debug(connect_message.inspect)
40
+ ws.send(connect_message)
41
+ end
42
+ ws.on :message do |body,type|
43
+ debug(body.data)
44
+ msg = JSON.parse(body.data)
45
+ case msg['cmd']
46
+ when 'success'
47
+ color('logtailor-error', msg['code']) do
48
+ # puts "#{msg.inspect}"
49
+ end
50
+ when 'error'
51
+ color('logtailor-error', msg['code']) do
52
+ puts "#{msg.inspect}"
53
+ end
54
+ ws.close
55
+ EM.stop
56
+ when 'available'
57
+ send_msg(ws, { 'cmd' => 'enable', 'type' => msg['type'], 'server' => msg['server'] })
58
+ when 'line'
59
+ next unless msg.all? { |k,v| @opts[:shows][k].nil? || v =~ shows[k] }
60
+ next if msg.any? { |k,v| @opts[:hides][k] && v =~ hides[k] }
61
+ p = ''
62
+ color(msg['log_type'], msg['http_status']) do
63
+ @opts[:columns].each do |column|
64
+ print("#{p}#{@columns[column.to_sym] || '%s'}" % [ msg[column.to_s] ])
65
+ p = ' '
66
+ end
67
+ end
68
+ puts
69
+ end
70
+ end
71
+ ws.on :close do
72
+ @opts[:logger].info "#{@opts[:log_prefix]}: connection closed"
73
+ ws.close
74
+ EM.stop
75
+ end
76
+ ws.on :error do |error|
77
+ @opts[:logger].info "#{@opts[:log_prefix]}: error: #{error.message}"
78
+ ws.close
79
+ EM.stop
80
+ end
81
+ end
82
+ rescue Interrupt
83
+ # exit cleanly
84
+ end
85
+
86
+ def send_msg(ws, msg)
87
+ ws.send(msg.to_json)
88
+ end
89
+
90
+ GREEN = '32;1'
91
+ RED = '31;1'
92
+ YELLOW = '33;1'
93
+ BLUE = '34;1'
94
+ LOG_TYPE_COLORS = {
95
+ 'apache-request' => {
96
+ /^5/ => RED,
97
+ /^4/ => YELLOW,
98
+ /^[123]/ => GREEN,
99
+ },
100
+ 'bal-access' => {
101
+ /^5/ => RED,
102
+ /^4/ => YELLOW,
103
+ /^[123]/ => GREEN,
104
+ },
105
+ 'apache-error' => RED,
106
+ 'php-error' => RED,
107
+ 'drupal-watchdog' => BLUE,
108
+ 'logtailor-error' => RED,
109
+ 'logtailor-debug' => BLUE,
110
+ }
111
+
112
+ def color(type, status)
113
+ color = LOG_TYPE_COLORS[type]
114
+ if color.is_a? Hash
115
+ color = color.find { |k,v| status.to_s =~ k }[1] rescue nil
116
+ end
117
+ color = nil if @opts[:no_color]
118
+ begin
119
+ print "\e[#{color}m" if color
120
+ yield
121
+ ensure
122
+ print "\e[0m" if color
123
+ end
124
+ end
125
+ end
126
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstream
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Barry Jaspan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2014-06-11 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faye-websocket
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.7.2
22
+ type: :runtime
23
+ version_requirements: *id001
24
+ - !ruby/object:Gem::Dependency
25
+ name: json
26
+ prerelease: false
27
+ requirement: &id002 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ version: 1.7.7
32
+ type: :runtime
33
+ version_requirements: *id002
34
+ - !ruby/object:Gem::Dependency
35
+ name: thor
36
+ prerelease: false
37
+ requirement: &id003 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 0.19.1
42
+ type: :runtime
43
+ version_requirements: *id003
44
+ description: Logstream is an Acquia service for streaming logs from Acquia Cloud.
45
+ email: barry.jaspan@acquia.com
46
+ executables:
47
+ - logstream
48
+ extensions: []
49
+
50
+ extra_rdoc_files: []
51
+
52
+ files:
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - LICENSE
56
+ - README.md
57
+ - bin/logstream
58
+ - etc/ca.pem
59
+ - lib/logstream/client.rb
60
+ - lib/logstream.rb
61
+ homepage: https://github.com/acquia/logstream
62
+ licenses: []
63
+
64
+ metadata: {}
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - &id004
74
+ - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - *id004
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 2.0.14
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Acquia Logstream tools and library
87
+ test_files: []
88
+
89
+ has_rdoc: false