Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos-caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Guillaume Hervier
slapos-caddy
Commits
100153ea
Commit
100153ea
authored
Jan 22, 2015
by
Alain Takoudjou
Committed by
Tristan Cavelier
Mar 31, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
monitor: tail -f the logs on monitoring stack (one file or many files)
parent
f2cfdbb8
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
279 additions
and
1 deletion
+279
-1
stack/monitor/buildout.cfg
stack/monitor/buildout.cfg
+9
-1
stack/monitor/cgi-httpd.conf.in
stack/monitor/cgi-httpd.conf.in
+4
-0
stack/monitor/logTools.py
stack/monitor/logTools.py
+69
-0
stack/monitor/monitor.cfg.in
stack/monitor/monitor.cfg.in
+20
-0
stack/monitor/webfile-directory/logfile.cgi.in
stack/monitor/webfile-directory/logfile.cgi.in
+177
-0
No files found.
stack/monitor/buildout.cfg
View file @
100153ea
...
@@ -60,7 +60,7 @@ mode = 0644
...
@@ -60,7 +60,7 @@ mode = 0644
recipe = hexagonit.recipe.download
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename}
url = ${:_profile_base_location_}/${:filename}
download-only = true
download-only = true
md5sum = 2d48f8b8e01fa0fdde964ed1c1547f05
#md5sum =
filename = cgi-httpd.conf.in
filename = cgi-httpd.conf.in
mode = 0644
mode = 0644
...
@@ -90,6 +90,14 @@ download-only = true
...
@@ -90,6 +90,14 @@ download-only = true
filename = information.html.in
filename = information.html.in
mode = 0644
mode = 0644
[logfile-cgi]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/webfile-directory/${:filename}
download-only = true
#md5sum =
filename = logfile.cgi.in
mode = 0644
[status-cgi]
[status-cgi]
recipe = hexagonit.recipe.download
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/webfile-directory/${:filename}
url = ${:_profile_base_location_}/webfile-directory/${:filename}
...
...
stack/monitor/cgi-httpd.conf.in
View file @
100153ea
...
@@ -24,6 +24,7 @@ LoadModule authn_file_module modules/mod_authn_file.so
...
@@ -24,6 +24,7 @@ LoadModule authn_file_module modules/mod_authn_file.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule env_module modules/mod_env.so
# SSL Configuration
# SSL Configuration
<IfDefine !SSLConfigured>
<IfDefine !SSLConfigured>
...
@@ -38,6 +39,9 @@ SSLProtocol -ALL +SSLv3 +TLSv1
...
@@ -38,6 +39,9 @@ SSLProtocol -ALL +SSLv3 +TLSv1
SSLHonorCipherOrder On
SSLHonorCipherOrder On
SSLCipherSuite RC4-SHA:HIGH:!ADH
SSLCipherSuite RC4-SHA:HIGH:!ADH
</IfDefine>
</IfDefine>
{% for key, value in environment_dict.items() -%}
SetEnv {{ key }} "{{ value }}"
{% endfor -%}
SSLEngine On
SSLEngine On
ScriptSock {{ httpd_configuration.get('cgid-pid-file') }}
ScriptSock {{ httpd_configuration.get('cgid-pid-file') }}
<Directory {{ directory.get('www') }}>
<Directory {{ directory.get('www') }}>
...
...
stack/monitor/logTools.py
View file @
100153ea
...
@@ -167,3 +167,72 @@ def generateRSS(db_path, name, rss_path, url_link, limit=10):
...
@@ -167,3 +167,72 @@ def generateRSS(db_path, name, rss_path, url_link, limit=10):
with open(rss_path, 'w') as rss_ouput:
with open(rss_path, 'w') as rss_ouput:
rss_ouput.write(rss_feed.to_xml())
rss_ouput.write(rss_feed.to_xml())
def tail(f, lines=20):
"""
Returns the last `lines` lines of file `f`. It is an implementation of tail -f n.
"""
BUFSIZ = 1024
f.seek(0, 2)
bytes = f.tell()
size = lines + 1
block = -1
data = []
while size > 0 and bytes > 0:
if bytes - BUFSIZ > 0:
# Seek back one whole BUFSIZ
f.seek(block * BUFSIZ, 2)
# read BUFFER
data.insert(0, f.read(BUFSIZ))
else:
# file too small, start from begining
f.seek(0, 0)
# only read what was not read
data.insert(0, f.read(bytes))
linesFound = data[0].count('
\
n
')
size -= linesFound
bytes -= BUFSIZ
block -= 1
return '
\
n
'.join(''.join(data).splitlines()[-lines:])
def readFileFrom(f, lastPosition, limit=20000):
"""
Returns the last lines of file `f`, from position lastPosition.
and the last position
limit = max number of characters to read
"""
BUFSIZ = 1024
f.seek(0, 2)
# XXX-Marco do now shadow 'bytes'
bytes = f.tell()
block = -1
data = ""
length = bytes
truncated = False # True if a part of log data has been truncated
if (lastPosition <= 0 and length > limit) or (length - lastPosition > limit):
lastPosition = length - limit
truncated = True
size = bytes - lastPosition
while bytes > lastPosition:
if abs(block * BUFSIZ) <= size:
# Seek back one whole BUFSIZ
f.seek(block * BUFSIZ, 2)
data = f.read(BUFSIZ) + data
else:
margin = abs(block * BUFSIZ) - size
if length < BUFSIZ:
f.seek(0, 0)
else:
seek = block * BUFSIZ + margin
f.seek(seek, 2)
data = f.read(BUFSIZ - margin) + data
bytes -= BUFSIZ
block -= 1
f.close()
return {
'content': data,
'position': length,
'truncated': truncated
}
stack/monitor/monitor.cfg.in
View file @
100153ea
...
@@ -179,6 +179,22 @@ context =
...
@@ -179,6 +179,22 @@ context =
key monitoring_file_json monitor-parameters:json-path
key monitoring_file_json monitor-parameters:json-path
raw python_executable ${buildout:executable}
raw python_executable ${buildout:executable}
[deploy-logfile-cgi]
recipe = slapos.recipe.template:jinja2
template = ${logfile-cgi:location}/${logfile-cgi:filename}
rendered = $${monitor-directory:monitoring-cgi}/$${:filename}
filename = Files.cgi
script-path= monitoring/Files.cgi
mode = 0744
context =
key monitor_bin monitor-parameters:executable
key script_path :script-path
section base_folder_list log-folder-cgi
raw python_executable ${buildout:directory}/bin/${extra-eggs:interpreter}
[log-folder-cgi]
log-folder = $${monitor-directory:log}
[make-rss]
[make-rss]
recipe = slapos.recipe.template:jinja2
recipe = slapos.recipe.template:jinja2
template = ${make-rss-script:output}
template = ${make-rss-script:output}
...
@@ -353,6 +369,9 @@ listening-ip = $${slap-parameters:ipv6-random}
...
@@ -353,6 +369,9 @@ listening-ip = $${slap-parameters:ipv6-random}
certificate = $${ca-httpd:cert-file}
certificate = $${ca-httpd:cert-file}
key = $${ca-httpd:key-file}
key = $${ca-httpd:key-file}
[httpd-environment]
PYTHONPATH = ${log-tools:location}
[monitor-httpd-configuration-file]
[monitor-httpd-configuration-file]
recipe = slapos.recipe.template:jinja2
recipe = slapos.recipe.template:jinja2
template = ${monitor-httpd-template:destination}/${monitor-httpd-template:filename}
template = ${monitor-httpd-template:destination}/${monitor-httpd-template:filename}
...
@@ -363,6 +382,7 @@ context =
...
@@ -363,6 +382,7 @@ context =
section monitor_parameters monitor-parameters
section monitor_parameters monitor-parameters
section httpd_configuration monitor-httpd-configuration
section httpd_configuration monitor-httpd-configuration
section monitor_rewrite_rule monitor-rewrite-rule
section monitor_rewrite_rule monitor-rewrite-rule
section environment_dict httpd-environment
[cgi-httpd-wrapper]
[cgi-httpd-wrapper]
recipe = slapos.cookbook:wrapper
recipe = slapos.cookbook:wrapper
...
...
stack/monitor/webfile-directory/logfile.cgi.in
0 → 100644
View file @
100153ea
#!{{ python_executable }}
import cgi
import cgitb
import json
import os
import subprocess
import logTools
import codecs
cgitb.enable(display=0, logdir="/tmp/cgi.log")
form = cgi.FieldStorage()
base_folder_list = {{ base_folder_list }}
script_path = "{{ script_path }}"
logpath = form.getvalue("path", "")
size = int(form.getvalue("size", "200"))
print """
<html><head>
<link
rel=
"stylesheet"
href=
"static/pure-min.css"
>
<link
rel=
"stylesheet"
href=
"static/style.css"
>
<script
src=
"static/jquery-1.10.2.min.js"
></script>
<style>
.head
{
background-color
:
#0078e7
;
border
:
0px
solid
#ffffff
;
text-align
:
left
;
border-width
:
0px
0px
1px
1px
;
font-size
:
18px
;
font-family
:
Helvetica
;
font-weight
:
normal
;
color
:
#ffffff
;
display
:
block
;
padding
:
10px
;
margin
:
0
;
}
.box
{
border
:
1px
solid
#e8eaed
;
padding
:
5px
;
}
textarea
{
width
:
100%
;
height
:
470px
;
margin-top
:
10px
;}
ul
{
margin
:
0px
;
padding
:
0px
;
list-style
:
none
;}
.button
{
margin-top
:
5px
;}
.button
div
{
margin
:
0
;
margin-right
:
10px
;
float
:
left
;
}
</style>
<script
language=
"javascript"
type=
"text/javascript"
>
$
(
document
).
ready
(
function
()
{
$
(
"
.file
"
).
click
(
function
()
{
var
child
=
$
(
this
).
children
(
'
input[type=checkbox]
'
);
if
(
!
$
(
child
).
is
(
'
:checked
'
)
)
{
$
(
child
).
prop
(
"
checked
"
,
true
);
}
else
{
$
(
child
).
prop
(
"
checked
"
,
false
);}
});
$
(
"
#open
"
).
click
(
function
()
{
var
file_list
=
""
;
$
(
"
.file
"
).
each
(
function
()
{
if
(
$
(
this
).
children
(
'
input[type=checkbox]
'
).
is
(
'
:checked
'
)
)
{
file_list
+=
$
(
this
).
attr
(
"
rel
"
)
+
"
#
"
;
}
});
if
(
file_list
==
""
)
{
return
false
;}
$
(
"
#path
"
).
val
(
file_list
);
$
(
"
#log_form
"
).
submit
();
return
false
;
});
$
(
"
#check
"
).
click
(
function
()
{
$
(
"
.file
"
).
each
(
function
()
{
var
child
=
$
(
this
).
children
(
'
input[type=checkbox]
'
);
if
(
!
$
(
child
).
is
(
'
:checked
'
)
)
{
$
(
child
).
prop
(
"
checked
"
,
true
);
}
});
return
false
;
});
$
(
"
#uncheck
"
).
click
(
function
()
{
$
(
"
.file
"
).
each
(
function
()
{
var
child
=
$
(
this
).
children
(
'
input[type=checkbox]
'
);
if
(
$
(
child
).
is
(
'
:checked
'
)
)
{
$
(
child
).
prop
(
"
checked
"
,
false
);
}
});
return
false
;
});
$
(
"
#reload
"
).
click
(
function
()
{
$
(
"
#log_form
"
).
submit
();
return
false
;
});
$
(
"
#return
"
).
click
(
function
()
{
$
(
"
#path
"
).
val
(
""
);
$
(
"
#log_form
"
).
submit
();
return
false
;
});
var
textarea
=
$
(
"
#logcontent
"
)
if
(
textarea
!=
undefined
)
{
$
(
textarea
).
animate
({
scrollTop
:
$
(
textarea
)[
0
].
scrollHeight
-
$
(
textarea
).
height
()
},
"
slow
"
);
}
});
</script>
</head><body>
"""
if not logpath:
print """
<form
action=
"/index.cgi"
method=
"post"
class=
"pure-form-aligned"
id=
"log_form"
>
<input
type=
"hidden"
name=
"posting-script"
value=
"%s"
/>
<div
class=
"box pure-menu pure-menu-open"
>
<h2
class=
"head"
>
Select file(s) in the list bellow
</h2>
<ul>
""" % script_path
for base_folder in base_folder_list.values():
if os.path.exists(base_folder):
for filename in os.listdir(base_folder):
path = os.path.join(base_folder, filename)
if not os.path.isdir(path):
print """
<li>
<a
href=
"#"
class=
"script file"
rel=
"%s"
title=
"%s"
>
<input
type=
"checkbox"
/>
%s
</a></li>
""" % (
path, path, filename)
else:
# accept a folder containing log files
for sub_filename in os.listdir(path):
sub_path = os.path.join(path, sub_filename)
if os.path.isdir(sub_path):
continue
print """
<li><a
href=
"#"
class=
"script file"
rel=
"%s"
title=
"%s"
>
%s
</a></li>
""" % (
sub_path, sub_path, sub_filename)
print """
</ul>
</div>
<div
class=
"button"
>
<div><label
for=
"size"
>
Lines:
</label><select
name=
"size"
id=
"size"
>
<option
value=
"50"
selected
>
50
</option>
<option
value=
"100"
>
100
</option>
<option
value=
"200"
>
200
</option>
<option
value=
"500"
>
500
</option>
<option
value=
"1500"
>
1500
</option>
</select></div>
<button
type=
"button"
class=
"pure-button pure-button-primary"
id=
"uncheck"
>
Uncheck All
</button>
<button
type=
"button"
class=
"pure-button pure-button-primary"
id=
"check"
>
Check All
</button>
<button
type=
"button"
class=
"pure-button pure-button-primary"
id=
"open"
>
Open File(s)
</button>
</div>
<div
style=
'clear:both'
></div>
<input
type=
"hidden"
name=
"path"
id=
"path"
value=
""
/>
</form>
"""
else:
path_list = [x for x in logpath.split('#') if x]
log_content = ""
title = ""
for filepath in path_list:
if os.path.exists(filepath) and os.path.isfile(filepath):
title += " " + filepath.split('/')[-1:][0]
try:
content = logTools.tail(codecs.open(filepath, "r", "utf_8"), size)
except Exception, e:
content = str(e)
if content:
log_content += "TAIL FILE %s >>>>\n\n" % filepath
log_content += content + "\n\n\n"
print """
<form
action=
"/index.cgi"
method=
"post"
class=
"pure-form-aligned"
id=
"log_form"
>
<input
type=
"hidden"
name=
"posting-script"
value=
"%s"
/>
<input
type=
"hidden"
name=
"path"
id=
"path"
value=
"%s"
/>
</form>
<div
class=
"box"
>
<h2
class=
"head"
>
Tail: %s
</h2>
<div
class=
"button"
>
<button
type=
"submit"
class=
"pure-button pure-button-primary"
id=
"return"
>
Return
</button>
<button
type=
"submit"
class=
"pure-button pure-button-primary"
id=
"reload"
>
Refresh
</button>
</div>
<div
style=
'clear:both'
></div>
<textarea
id=
"logcontent"
>
%s
</textarea>
</div>
""" % (script_path, logpath, title, log_content)
print """
</body></html>
"""
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment