logs-cf-plugin 0.0.23.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +49 -0
- data/lib/logs-cf-plugin/log_target.rb +46 -0
- data/lib/logs-cf-plugin/loggregator_client.rb +116 -0
- data/lib/logs-cf-plugin/message_writer.rb +5 -0
- data/lib/logs-cf-plugin/plugin.rb +54 -0
- data/vendor/log_message/log_message.pb.rb +32 -0
- data/vendor/log_message/log_message.proto +25 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OTI0ZDYyMGIwNjE4YTMwZjhmYWFlMDNmOTg5NmFmZGMyM2E0MjhkYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NGI4NDQxYTUxYmM3Njc3MTBkZDVmNGI2YzM2NGY3NDYwZjY2ZTMzNw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NmYwNjE5NWE0MjRhMzBjZDBlYmVkM2FiZjg5OGMwYzZiNDE4ZjUxODQ1YTU0
|
10
|
+
NDBlZTNhM2RmNWMxYWRkZTBkZjU0YTllMTI5NTkzODc4YTY2ZjYyMTUzOGFm
|
11
|
+
YWQ0MTFjMmQyZjhhOGE4ZGRlMjE2OWQ0NWViMGY4MjYzNGZlMzE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MmUyMWRkNDc5ZTFhMGRiMDM5NmI1M2EzMDE4ZWMzZDc3NGYyZjc5MTJkMDkw
|
14
|
+
NzdiNDgzNjU5NmYxYzI2OTk0MmQ4N2M3NTEyMDIyZTgyNWExMjUyMmFkZDQx
|
15
|
+
ZWM5NGI2MTZjY2E1NmY2Mjg4ZjVhZDJiZWFkOGVmZDZmNGYxYmY=
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Logs-Cf-Plugin [![Build Status](https://travis-ci.org/cloudfoundry/logs-cf-plugin.png?branch=master)](https://travis-ci.org/cloudfoundry/logs-cf-plugin)
|
2
|
+
|
3
|
+
Plugin to cf command to add streaming application logs.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'logs-cf-plugin'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install logs-cf-plugin
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
After installing you can run cf logs and see your application's logs stream to the console.
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
The Cloud Foundry team uses GitHub and accepts contributions via [pull request](https://help.github.com/articles/using-pull-requests)
|
26
|
+
|
27
|
+
Follow these steps to make a contribution to any of our open source repositories:
|
28
|
+
|
29
|
+
1. Complete our CLA Agreement for [individuals](http://www.cloudfoundry.org/individualcontribution.pdf) or [corporations](http://www.cloudfoundry.org/corpcontribution.pdf)
|
30
|
+
1. Set your name and email
|
31
|
+
|
32
|
+
git config --global user.name "Firstname Lastname"
|
33
|
+
git config --global user.email "your_email@youremail.com"
|
34
|
+
|
35
|
+
1. Fork the repo
|
36
|
+
1. Make your changes on a topic branch, commit, and push to github and open a pull request.
|
37
|
+
|
38
|
+
Once your commits are approved by Travis CI and reviewed by the core team, they will be merged.
|
39
|
+
|
40
|
+
#### Checkout
|
41
|
+
|
42
|
+
git clone git@github.com:cloudfoundry/logs-cf-plugin.git
|
43
|
+
cd logs-cf-plugin/
|
44
|
+
bundle
|
45
|
+
|
46
|
+
#### Running tests
|
47
|
+
|
48
|
+
rake
|
49
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module LogsCfPlugin
|
2
|
+
class LogTarget
|
3
|
+
def initialize(target_organization, target_space, ids)
|
4
|
+
raise ArgumentError, "Requires 3 ids" unless ids.size == 3
|
5
|
+
@target_organization = target_organization
|
6
|
+
@target_space = target_space
|
7
|
+
|
8
|
+
@org_id = ids[0]
|
9
|
+
@space_id = ids[1]
|
10
|
+
@app_id = ids[2]
|
11
|
+
end
|
12
|
+
|
13
|
+
def ambiguous?
|
14
|
+
@target_organization && @target_space
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid?
|
18
|
+
!!target
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_params
|
22
|
+
case target
|
23
|
+
when :org
|
24
|
+
{org: @org_id}
|
25
|
+
when :space
|
26
|
+
{org: @org_id, space: @space_id}
|
27
|
+
when :app
|
28
|
+
{org: @org_id, space: @space_id, app: @app_id}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def target
|
35
|
+
return nil if ambiguous?
|
36
|
+
case
|
37
|
+
when @target_organization
|
38
|
+
:org
|
39
|
+
when @target_space
|
40
|
+
:space
|
41
|
+
when @app_id
|
42
|
+
:app
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'log_message/log_message.pb'
|
2
|
+
require 'faye/websocket'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module LogsCfPlugin
|
7
|
+
class LoggregatorClient
|
8
|
+
include CFoundry::TraceHelpers
|
9
|
+
|
10
|
+
def initialize(loggregator_host, user_token, output, trace)
|
11
|
+
@output = output
|
12
|
+
@loggregator_host = loggregator_host
|
13
|
+
@user_token = user_token
|
14
|
+
@trace = trace
|
15
|
+
end
|
16
|
+
|
17
|
+
def listen(query_params)
|
18
|
+
websocket_address = "wss://#{loggregator_host}:4443/tail/?#{hash_to_query(query_params)}"
|
19
|
+
output.puts "websocket_address: #{websocket_address}" if trace
|
20
|
+
|
21
|
+
EM.run {
|
22
|
+
ws = Faye::WebSocket::Client.new(websocket_address, nil, :headers => {"Origin" => "http://localhost", "Authorization" => user_token})
|
23
|
+
|
24
|
+
ws.on :open do |event|
|
25
|
+
output.puts("Connected to server.")
|
26
|
+
EventMachine.add_periodic_timer(keep_alive_interval) do
|
27
|
+
ws.send([42])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ws.on :message do |event|
|
32
|
+
received_message = LogMessage.decode(event.data.pack("C*"))
|
33
|
+
MessageWriter.write(output, received_message)
|
34
|
+
end
|
35
|
+
|
36
|
+
ws.on :error do |event|
|
37
|
+
output.puts("Server error")
|
38
|
+
output.puts(event.data.inspect) if trace
|
39
|
+
end
|
40
|
+
|
41
|
+
ws.on :close do |event|
|
42
|
+
ws.close
|
43
|
+
output.puts("Server dropped connection...goodbye.")
|
44
|
+
EM.stop
|
45
|
+
ws = nil
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def dump_messages(query_params)
|
51
|
+
uri = URI.parse("https://#{loggregator_host}/dump/?#{hash_to_query(query_params)}")
|
52
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
53
|
+
http.use_ssl = true
|
54
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
55
|
+
|
56
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
57
|
+
request['Authorization'] = user_token
|
58
|
+
|
59
|
+
if trace
|
60
|
+
request_hash = {
|
61
|
+
:url => uri.request_uri,
|
62
|
+
:method => "GET",
|
63
|
+
:headers => sane_headers(request),
|
64
|
+
:body => ""
|
65
|
+
}
|
66
|
+
output.puts(request_trace(request_hash))
|
67
|
+
end
|
68
|
+
|
69
|
+
response = http.request(request)
|
70
|
+
|
71
|
+
return [] unless response.code == "200"
|
72
|
+
|
73
|
+
response_bytes = StringIO.new(response.body)
|
74
|
+
messages = []
|
75
|
+
while len = response_bytes.read(4)
|
76
|
+
len = len.unpack("N")[0] # 32-bit length, BigEndian stylie
|
77
|
+
record = response_bytes.read(len) # This returns a string even if len is 0.
|
78
|
+
msg = LogMessage.decode(record)
|
79
|
+
messages << msg
|
80
|
+
end
|
81
|
+
|
82
|
+
if trace
|
83
|
+
response_hash = {
|
84
|
+
:headers => sane_headers(response),
|
85
|
+
:status => response.code,
|
86
|
+
:body => messages
|
87
|
+
}
|
88
|
+
output.puts(response_trace(response_hash))
|
89
|
+
end
|
90
|
+
|
91
|
+
messages
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def sane_headers(obj)
|
97
|
+
hds = {}
|
98
|
+
|
99
|
+
obj.each_header do |k, v|
|
100
|
+
hds[k] = v
|
101
|
+
end
|
102
|
+
|
103
|
+
hds
|
104
|
+
end
|
105
|
+
|
106
|
+
def keep_alive_interval
|
107
|
+
25
|
108
|
+
end
|
109
|
+
|
110
|
+
def hash_to_query(hash)
|
111
|
+
return URI.encode(hash.map { |k, v| "#{k}=#{v}" }.join("&"))
|
112
|
+
end
|
113
|
+
|
114
|
+
attr_reader :output, :loggregator_host, :user_token, :trace
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'cf'
|
2
|
+
|
3
|
+
module LogsCfPlugin
|
4
|
+
require 'logs-cf-plugin/loggregator_client'
|
5
|
+
require 'logs-cf-plugin/log_target'
|
6
|
+
require 'logs-cf-plugin/message_writer'
|
7
|
+
|
8
|
+
class Plugin < CF::CLI
|
9
|
+
include LoginRequirements
|
10
|
+
|
11
|
+
desc "Tail or dump logs for CF applications or spaces"
|
12
|
+
group :apps
|
13
|
+
input :app, :desc => "App to tail logs from", :argument => :optional, :from_given => by_name(:app)
|
14
|
+
input :space, :type => :boolean, :desc => "Logs of all apps in the current space", :default => false
|
15
|
+
input :org, :type => :boolean, :desc => "Logs of all apps and spaces in the current organization", :default => false
|
16
|
+
input :recent, :type => :boolean, :desc => "Dump recent logs instead of tailing", :default => false
|
17
|
+
|
18
|
+
def logs
|
19
|
+
guids = [client.current_organization.guid, client.current_space.guid, input[:app].try(:guid)]
|
20
|
+
|
21
|
+
log_target = LogTarget.new(input[:org], input[:space], guids)
|
22
|
+
|
23
|
+
if log_target.ambiguous?
|
24
|
+
Mothership::Help.command_help(@@commands[:logs])
|
25
|
+
fail "Please provide either --space or --org, but not both."
|
26
|
+
end
|
27
|
+
|
28
|
+
unless log_target.valid?
|
29
|
+
Mothership::Help.command_help(@@commands[:logs])
|
30
|
+
fail "Please provide an application to log."
|
31
|
+
end
|
32
|
+
|
33
|
+
loggregator_client = LoggregatorClient.new(loggregator_host, client.token.auth_header, STDOUT, input[:trace])
|
34
|
+
|
35
|
+
if input[:recent]
|
36
|
+
loggregator_client.dump_messages(log_target.query_params).each do |m|
|
37
|
+
MessageWriter.write(STDOUT, m)
|
38
|
+
end
|
39
|
+
|
40
|
+
else
|
41
|
+
loggregator_client.listen(log_target.query_params)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
::ManifestsPlugin.default_to_app_from_manifest(:logs, false)
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def loggregator_host
|
50
|
+
target_base = client.target.sub(/^https?:\/\/([^\.]+\.)?(.+)\/?/, '\2')
|
51
|
+
"loggregator.#{target_base}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
## Generated from log_message.proto for logMessage
|
2
|
+
require "beefcake"
|
3
|
+
|
4
|
+
|
5
|
+
class LogMessage
|
6
|
+
include Beefcake::Message
|
7
|
+
|
8
|
+
module MessageType
|
9
|
+
OUT = 1
|
10
|
+
ERR = 2
|
11
|
+
end
|
12
|
+
module SourceType
|
13
|
+
CLOUD_CONTROLLER = 1
|
14
|
+
ROUTER = 2
|
15
|
+
UAA = 3
|
16
|
+
DEA = 4
|
17
|
+
WARDEN_CONTAINER = 5
|
18
|
+
end
|
19
|
+
|
20
|
+
required :message, :bytes, 1
|
21
|
+
required :message_type, LogMessage::MessageType, 2
|
22
|
+
required :timestamp, :sint64, 3
|
23
|
+
required :app_id, :string, 4
|
24
|
+
required :source_type, LogMessage::SourceType, 5
|
25
|
+
optional :source_id, :string, 6
|
26
|
+
optional :space_id, :string, 7
|
27
|
+
required :organization_id, :string, 8
|
28
|
+
|
29
|
+
def message_type_name
|
30
|
+
{MessageType::OUT => 'STDOUT', MessageType::ERR => 'STDERR'}[message_type]
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
package logMessage;
|
2
|
+
|
3
|
+
message LogMessage {
|
4
|
+
enum MessageType {
|
5
|
+
OUT = 1;
|
6
|
+
ERR = 2;
|
7
|
+
}
|
8
|
+
|
9
|
+
enum SourceType {
|
10
|
+
CLOUD_CONTROLLER = 1;
|
11
|
+
ROUTER = 2;
|
12
|
+
UAA = 3;
|
13
|
+
DEA = 4;
|
14
|
+
WARDEN_CONTAINER = 5;
|
15
|
+
}
|
16
|
+
|
17
|
+
required bytes message = 1;
|
18
|
+
required MessageType message_type = 2;
|
19
|
+
required sint64 timestamp = 3;
|
20
|
+
required string app_id = 4;
|
21
|
+
required SourceType source_type = 5;
|
22
|
+
optional string source_id = 6;
|
23
|
+
optional string space_id = 7;
|
24
|
+
required string organization_id = 8;
|
25
|
+
}
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logs-cf-plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.23.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pivotal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cf
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.5
|
20
|
+
- - <
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.2.5
|
30
|
+
- - <
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: faye-websocket
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ~>
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.6.1
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.6.1
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: beefcake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.3.7
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.3.7
|
61
|
+
description: CF command line tool to retrieve recent and tail CF Application Logs
|
62
|
+
email:
|
63
|
+
- vcap-dev@googlegroups.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- lib/logs-cf-plugin/log_target.rb
|
69
|
+
- lib/logs-cf-plugin/loggregator_client.rb
|
70
|
+
- lib/logs-cf-plugin/message_writer.rb
|
71
|
+
- lib/logs-cf-plugin/plugin.rb
|
72
|
+
- vendor/log_message/log_message.pb.rb
|
73
|
+
- vendor/log_message/log_message.proto
|
74
|
+
- README.md
|
75
|
+
homepage: http://github.com/cloudfoundry/logs-cf-plugin
|
76
|
+
licenses:
|
77
|
+
- Apache 2.0
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
- vendor
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.9.3
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ! '>'
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.3.1
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.0.6
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: CF Logs
|
100
|
+
test_files: []
|