logstream 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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