Community:WebSkunk
From Splunk Wiki
The Web Skunk application is a simple project comprised of JavaScript and Python code. Web Skunk can be added to any website, and forwards loading time stats into Splunk for later analysis. It posts a payload called "splunkdata" to a custom Splunk receiver endpoint. Natively supported receiver endpoints will be available in Splunk 4.0. The project leverages Splunk's automatic extraction of field from any key value pairs with an equal sign.
jQuery Code
This is the jquery code to use within the page's HTML. The HTML and jquery code examples live in $SPLUNK_HOME/etc/apps/WebSkunk/rest/web/index.html.
<script type="text/javascript">
//<![CDATA[
var start_time = new Date();
function load() {
var end_time = new Date();
var time_delta = end_time.getTime() - start_time.getTime();
var timeStamp = end_time.toUTCString();
$.post("../receiver/", { splunkdata: timeStamp + " stats-source=jquery-hitstats stats-realtime=" + time_delta + " stats-uri=" + document.location } );
$("#rendertime").html("<br />stats-realtime: "+ time_delta+"ms");
}
//]]>
</script>
Receiver Endpoint Mapping
Below is a copy of restmap.conf, located in $SPLUNK_HOME/etc/apps/WebSkunk/default/restmap.conf. For more information about creating an endpoint, see this page.
# # REST endpoints map configuration # # Main endpoint [script:webskunk.main] match=/webskunk/main scripttype=python handler=webskunk_handlers.main requireAuthentication=false # Status endpoint [script:webskunk.status] match=/webskunk/status scripttype=python handler=webskunk_handlers.status requireAuthentication=false #Web endpoint [script:webskunk.web] match=/webskunk/web scripttype=python handler=webskunk_handlers.web requireAuthentication=false # Receiver endpoint [script:webskunk.receiver] match=/webskunk/receiver scripttype=python handler=webskunk_handlers.receiver requireAuthentication=false
Python Handlers
This is the python script that handles requests to the endpoints defined above. This file is located at $SPLUNK_HOME/etc/apps/WebSkunk/rest/webskunkhandlers.py.
#
# http request handlers
#
from splunk import auth, search
import splunk.rest
import utils
import logging as logger
import splunk.bundle as bundle
import httplib2, urllib, os, time
import telnetlib
# set our path to this particular application directory (which is suppose to be <appname>/bin)
app_dir = os.path.dirname(os.path.abspath(__file__))
# define the web content directory (needs to be <appname>/web directory)
web_dir = app_dir + "/web"
class main(splunk.rest.BaseRestHandler):
'''
Main endpoint
'''
def handle_GET(self):
# set output params
self.response.setStatus(200)
self.response.setHeader('content-type', 'text/html')
self.response.write('Main: this is webskunk')
# listen to all verbs
handle_POST = handle_DELETE = handle_PUT = handle_VIEW = handle_GET
class status(splunk.rest.BaseRestHandler):
'''
Status endpoint
'''
def handle_GET(self):
# set output params
self.response.setStatus(200)
self.response.setHeader('content-type', 'text/html')
self.response.write('<html><head><title>webskunk</title></head><body>')
self.response.write('<h1>Status: webskunk is online</h1><br><br>')
self.response.write('<b>Active endpoints:</b><br>')
self.response.write(utils.getHrefs(self.pathParts[1]))
self.response.write('</body></html>')
# listen to all verbs
handle_POST = handle_DELETE = handle_PUT = handle_VIEW = handle_GET
class web(splunk.rest.BaseRestHandler):
'''
Main endpoint
'''
def handle_GET(self):
files = []
logger.debug('scanning %s' % web_dir)
# do a scan of the application directory's web directory
for root, dirs, file_list in os.walk(web_dir):
cur_dir = root.replace(web_dir, '')
for file in file_list:
full_name = os.path.join(cur_dir, file)
files.append(full_name)
# extract the last segment of the URL passed to splunkd and use it to load a file
last_segment = self.pathParts[-1]
# check the requested file exists in the web directory - if not, we return a 404
if last_segment in files:
f = open(web_dir + '/' + last_segment, 'rb')
content = f.read()
f.close()
# basic checking of file extension to set a mime type
if ".html" in last_segment:
self.response.setHeader('content-type', 'text/html')
elif ".js" in last_segment:
self.response.setHeader('content-type', 'application/x-javascript')
elif ".css" in last_segment:
self.response.setHeader('content-type', 'text/css')
elif ".jpg" in last_segment:
# this won't work for now - leaving here for a reminder
self.response.setHeader('content-type', 'image/jpeg')
content_length = "%d" % len(content)
self.response.setHeader('Content-Length', content_length)
self.response.setStatus(200)
else:
self.response.setStatus(404)
content = "404 - not found!"
self.response.write(content)
class receiver(splunk.rest.BaseRestHandler):
def handle_POST(self):
host="localhost"
tn = telnetlib.Telnet(host, 9998)
try:
content = self.args['splunkdata']
tn.write(content)
self.response.write("AWESOME!")
except Exception, e:
logger.exception(e)
self.response.write(e)
# listen to all verbs
handle_GET = handle_DELETE = handle_PUT = handle_VIEW = handle_POST