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 +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +24 -0
- data/LICENSE +22 -0
- data/README.md +152 -0
- data/bin/logstream +85 -0
- data/etc/ca.pem +89 -0
- data/lib/logstream.rb +1 -0
- data/lib/logstream/client.rb +126 -0
- metadata +89 -0
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
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
|