Posts Categorized: Free Tools

pastedImage_15

Node.js dashboard for SAP HANA

This is what we will be developing in this blog …

Over the past few years Node.js has really caught my attention. The simplicity of Javascript with server side processing, Non-blocking-IO, Event Driven, and simple integration always intrigued me as a great combination for enterprise applications. (Somehow it sounds similar to HANA XS Engine)
A couple months ago I ran into a similar problem to Jon-Paul Boyd (HANA Forum Post) in which I wanted to use XS Engine for websocket/persistant connections to my HANA Instance, but due to the support not being included in SPS6, I decided to look elsewhere, and ended up using Node.js to fulfill this requirement.In the past, while developing HANA/Node apps, I resorted to creating a XSJS App which really just acted as a middleware layer to push and pull data from my HANA DB, until recently I noticed a great blog post from Ingo Sauerzapf which piqued my interest. The blog mentioned that Holger Koser had created a HANA DB Client for Node making life extremely easy to connect to HANA directly from Node. I thought it would be good share the small project I developed using Node.js and this new client with the community in the hopes that others will share their experiences with the technology.This blog is not necessarily an introduction to Node.js development as there are some nice tutorials and examples out there from Tobias Hoffman and Alessandro Spadoni. The blog is intended to cover a small app developed in Node.js and shows the development process behind it, taking it from conception through to reality. I encourage you to download a few of these components, and also the example out. This app, similar to another app I developed called Metric² (which you can read about here), it is a web based widget showing some friendly KPI’s on the performance of your HANA Instance. The app gets streaming data from our HANA backend displaying this in a friendly, simple dashboard. The dashboard is designed to be shown on a large format monitor in a Ops or IT center and can also very easily be modified to show any KPI’s relevant to your business or needs.

Requirements:

SAP HANA Instance (e.g. AWS Developer Image)

Node.js installed (this does not need to be on the HANA box but same network with access to the HANA port – normally 30015).

Node Dependencies

We will also use a couple of helpful dependencies from the node community including Socket.io, Express and obviously hdb. Installing these packages is as simple as running “npm install hdb”. Once you have the dependencies installed we can start creating our app.

https://nodei.co/npm/hdb.png?compact=true

App Design

For me, I always start mocking up in my favorite Image IDE (Photoshop), I used this image as inspiration for my app. I liked the simplicity, clean layout with focus on the numbers at the bottom. In our case, we will add a small chart in the center, giving us a basic visual representation of the numbers being displayed:

 

Photoshop HTML Mockup
Download the PSD

App Development

Index.html

In this case I decided to use Twitter Bootstrap to help with some of the layout/formatting of the page as well as some mundane tasks like Modal popups. From a coding perspective I started out developing the Single paged “index.html” file, doing my best to stick with my mockup which I previously created. I was sure to “id” all of my elements on this page as we will be updating these values from our node.js backend. This aspect of node development is strictly “traditional” web based development. No need to work with Node or any server for that matter. Once you have your page rendering the way you want, we can move on.

<html>

<head>

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

<meta charset="UTF-8"/>

<meta name="viewport" content="width=device-width, maximum-scale=1.0" />

<title>Metric&#178;</title>

<!-- jQuery -->

<script src="https://code.jquery.com/jquery.js"></script>

<!-- Socket.IO -->

<script src='/socket.io/socket.io.js'></script>

<!-- Peity - a lightweight sparkline package for jQuery -->

<script src='js/jquery.peity.min.js'></script>

<!-- Client side code needed -->

<script src='js/client.js'></script>

<!-- Bootstrap CSS -->

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">

<!-- Latest compiled and minified JavaScript -->

<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>

<!-- CSS -->

<link rel="stylesheet" href="css/style.css">

</head>

<body>

<div id="top">

<div>

<div>

<div>

<table>

<tr>

<td rowspan="2" style="text-align: center; width: 10%;" >

<img id="statusicon" src="img/OKIcon.png"/>

</td>

<td style="vertical-align: top;">

<h1><span id="info-name">SAP HANA Instance</span>

<button data-toggle="modal" data-target="#myModal">

<span></span>

</button>

</h1>

</td>

</tr>

<tr>

<td style="padding-top: 20px;">

<span style="margin-left: 0px;" /></span><span id="info-alerts">0</span> Alerts

<span></span><span id="info-version">1.0</span>

<span></span><span id="info-detail">Server Location</span>

</td>

</tr>

</table>

</div>

<div>

<span>0</span>

</div>

<div>

<table>

<tr>

<td id="infoUSERS" onClick="setChart('USERS');">

<!-- The ID of each of our <SPAN> tags is important for updating the data being returned from the server -->

<span id="info-users">0</span><br />

<span>Users</span>

</td>

<td> </td>

<td id="infoDISK" onClick="setChart('DISK');">

<span id="info-disk">0</span> <sup>GB</sup><br />

<span>Free Disk</span>

</td>

<td id="infoMEM" onClick="setChart('MEM');">

<span id="info-mem">0</span> <sup>GB</sup><br />

<span>Free Memory</span>

</td>

<td id="infoCPU" onClick="setChart('CPU');">

<span id="info-cpu">0</span> <sup>%</sup><br />

<span>CPU</span>

</td>

</tr>

</table>

</div> <!-- /.containerfooter -->

</div> <!-- /.container -->

</div> <!-- /.centercontainer -->

</div> <!-- /.top -->

<!-- Modal -->

<div id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

<div>

<div>

<div>

<button type="button" data-dismiss="modal" aria-hidden="true">&times;</button>

<h4 id="myModalLabel">Settings</h4>

</div>

<div>

<form id="modalbox" role="form">

<div>

<label for="servername">Name</label>

<input type="text" id="servername" placeholder="Enter a reference server name">

</div>

<div>

<label for="serverdetail">Location</label>

<input type="text" id="serverdetail" placeholder="Description, Location or Other Information">

</div>

<div>

<label for="bg">Background</label><br />

<label>

<input type="radio" name="bg" value="../img/bg1.jpg" checked> Background 1

</label>

<label>

<input type="radio" name="bg" value="../img/bg2.jpg"> Background 2

</label>

<label>

<input type="radio" name="bg" value="../img/bg3.jpg"> Background 3

</label>

<label>

<input type="radio" name="bg" value="none;"> None

</label>

</div>

<div>

<label for="colorscheme">Color Scheme</label><br />

<label>

<input type="radio" name="colorscheme" value="Dark" checked> Dark

</label>

<label>

<input type="radio" name="colorscheme" value="Light"> Light

</label>

<label>

<input type="radio" name="colorscheme" value="Fiori"> Fiori

</label>

</div>

<div>

<button type="button" data-dismiss="modal">Close</button>

<button type="button" id="modalSave" onClick="saveSettings();">Save changes</button>

</div>

</div><!-- /.modal-content -->

</div><!-- /.modal-dialog -->

</div><!-- /.modal -->

</body>

</html>

App.js

Next we develop the app.js file which is the brains of our operation. This file is firstly going to act as our web server for our web site, and secondly provide the data from our HANA server to the web page, pushing the data via web sockets.

Below is the app.js code, here you can see how we process each request based on the type and subsequently respond with the requested data. You can also see how simple it is to call the HANA DB and respond with the results.

 

var express = require('express'),

http = require('http'),

hdb = require('hdb');

try {

var app = express();

var server = http.createServer(app);

server.listen(3000);

var io = require('socket.io').listen(server);

app.use(express.static(__dirname + '/'));

// development only

if ('development' == app.get('env')) {

app.use(express.errorHandler());

}

var client = hdb.createClient({

host     : 'Your HANA IP Address or DNS Name',

port     : 30015,

user     : 'username',

password : 'password'

});

client.connect(function (err) {

if (err) {

console.error('Connect Error:', err);

} else {

console.log('Connected to server');

}

});

process.on('uncaughtException', function (err) {

console.log('Caught exception: ' + err);

});

strContent = '';

io.sockets.on('connection', function (socket) {

socket.on('request', function (data) {

// Handle Service Requests

switch (data.service) {

case 'CPU':

client.exec("SELECT ABS(SUM(PROCESS_CPU)) as CPU from SYS.M_SERVICE_STATISTICS", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: 'CPU', response: rows[0].CPU});

}

});

break;

case 'MEM':

client.exec("select TO_VARCHAR(ROUND((FREE_PHYSICAL_MEMORY) /1024/1024/1024, 2)) AS FREEMEM

from PUBLIC.M_HOST_RESOURCE_UTILIZATION", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].FREEMEM});

}

});

break;

case 'INFO':

client.exec("SELECT VALUE FROM SYS.M_SYSTEM_OVERVIEW WHERE NAME = 'Version'", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].VALUE});

}

});

break;

case 'DISK':

client.exec("select TO_VARCHAR((ROUND(d.total_size/1024/1024/1024, 2) - ROUND(d.used_size/1024/1024/1024,2))) as FREESPACE

from ( ( m_volumes as v1 join M_VOLUME_SIZES as v2 on v1.volume_id = v2.volume_id ) right outer join m_disks as d on d.disk_id = v2.disk_id )

where d.usage_type = 'DATA' group by v1.host, d.usage_type, d.total_size,    d.device_id, d.path, d.used_size", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].FREESPACE});

}

});

break;

case 'USERS':

client.exec("SELECT COUNT(CONNECTION_ID) as STATUS FROM SYS.M_CONNECTIONS

WHERE CONNECTION_STATUS = 'RUNNING'", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].STATUS});

}

});

break;

case 'ALERTS':

client.exec("SELECT COUNT(ALERT_DETAILS) as ALERTCOUNT FROM _SYS_STATISTICS.STATISTICS_CURRENT_ALERTS", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].ALERTCOUNT});

}

});

break;

}

});

});

} catch(err) {

console.log(err);

}

 

The App does have a couple of different themes which will hopefully make it fit with your office decor

Below you can see a couple of images of the app running and showing the output. You can obviously very easily modify the code to show anything relevant to your business case as well. The Node-hdb package for node.js really makes developing HANA connected Node apps a breeze! Thanks Holger!

Fiori Styled
Light Theme
Image5.png
Dark Theme
Image6.png
As usual – please feel free to comment on your experience with Node.js and if you feel like this type of technology is a good fit in the enterprise? Do you have any suggestions on what I could have done differently?You can download the app here: Metric² for Node
Credits: The Bokeh backgrounds are from devientArt

Image1

Metric² for SAP HANA

Metric² is a web based, realtime dashboarding platform for SAP HANA, on SAP HANA.I recently gave a demo of the app at Demojam in Las Vegas (You can read my blog post about the event here). Metric² is a free app/download and this blog gives some insight into how it works, and how you can download and install it in your own HANA system:

Overview

Metric² is made up of 3 key areas:

Dashboards: Metric² can have multiple dashboards. Dashboards are designed as blank canvases, are quite flexible, and can contain widgets which are added can be simply dragged and dropped into their needed locations and also sized accordingly.

Widgets: Dashboards can have multiple widgets displayed. There are a variety of widgets including a range of predefined datasources (CPU, Memory, Disk etc.) but also include custom widgets (SQL, JSON, Yahoo) which can display a myriad of information to your team.

Alerts: Certain widgets can have alerts “attached” to them, when the value meets the conditions, the alert is logged and displayed.

  1. Why realtime? The intent is to be proactive about your systems or applications health, having the Metric² dashboards up on a large format monitor ensures that everyone is well aware of how your system is performing, and more importantly, when it is not.
  2. Why Web Based? While I personally prefer Native/Traditional/Window types apps, having Metric² run as a web app (using SAPUI5) means it can be used and displayed on a variety of devices and formats.
  3. Why do you call it a platform? Its more than just a bunch of metrics, everything is customizable, you can create your own widgets, your own dashboards and alerts, it also acts as a large data warehouse for any of the data you are monitoring/tracking, taking it past being an app, to a small platform which you can build, and extend upon.
Image1.png

Architecture:

This was an interesting dilemma for me, I wanted to keep the app as simple as possible by not requiring that admins install *any* additional components (thus deemed as a “Native” XS HANA app). It has a DB schema which Metric² needs to have present, and subsequently a set of files which get installed in the content repository via a package.

This lead to an interesting challenge, because the XS Engine did not support web sockets for “true” realtime app runtime, the app uses timers and HTTP polling to fetch the data from the backend system (read xsjs file). This is less than perfect. I have high hopes that SPS7 will include WebSocket support and we can start writing true realtime web apps directly on XS Engine. Another alternative is the recent availability of Node.js library for HANA, while its awesome, still requires additional components outside of the core HANA platform.

Image2.png

Design:

The app is based on a “Fiori” themed SAP UI5 foundation. I also used a variety of JQuery add-on’s to help (read: not reinvent the wheel) with the display of  the data. I also used the standard D3 visualization library of UI5 along with a helper class called NVD3 which is very useful in simplifying the D3 charting experience.

Image3.pngWhats Missing:

- Currently the app does not support multiple users.

- Browser support … currently its developed for Firefox only, but does not look too bad on Safari or Chrome (CSS Changes needed).

- The polling aspect, because the data is being fetched from your XSJS file and returned to the main page, I am constantly having to eval the returned code to update the chart widgets. Eval is Evil

- Widget history: Because widgets are being polled, if the screen is not open, it will not capture any historical data. Not very useful for troubleshooting.

Whats Next:

I am currently working on porting the app to support the realtime abilities. Planning on a new theme (not so much Fiori like) to make it a little more differentiated. Also planning on adding a few more predefined widgets (suggestions welcomed!!!).

Download:

Here

Install Guide:

  1. Import the Metric² Package to the content repository in XS Engine (This can be done via Web or Studio)
    1. Open http://YOURIP:8000/sap/hana/xs/ide/
    2. Click on the Delivery Unit Menu and then Import Delivery Unit From File System
    3. Select the downloaded/unzipped file (REPO_20131109-203950826-HDB–METRIC2.tgz)
  2. Run the Install script (InstallScript.sql) for the DB which is included in the download – This can be done in either HANA Studio or the Web IDE
  3. Optional: Run the Overview dashboard script (Overview Dashboard.sql) from here to give you a sample dashboard  – This can be done in either HANA Studio or the IDE
  4. Open your browser to http://YOURIP:8000/lilabs/metric2/Index.html

- Optional: Predictive Analytics: You may need to enable PAL on your server in order to use the libraries and forecasting feature under some of the widgets.

Known Issues:

- The ping response widget is not functional currently

- The Total CPU reported on the “System overview” widget should be converted to a legitimate percentage (0 – 100%) as SLES displays a summed percentage of all the CPU’s.

- The Map of the US Widget – coordinates are not accurate, they need an offset due to the images size and padding within the widget

- The dashboard itself is not fully responsive, when displaying on an iPad the view is often too small to display all the widgets

- There is no mail server functionality built into XS Engine, so alerts are only displayed on the monitor and in the notifications area on the right of the screen.

You can submit an issue log on my website making it easier to track, share, resolve: http://blog.li-labs.com/issue-log/

Disclaimer:

Vishal Sikka made a humorous reference at the Las Vegas Keynote to a certain “Pre-release” Beta product, so I am going to do the same This version of Metric² is a “Prerelease” beta please use and test it thoroughly in your development environment.

Stay up to date:

Please head over to http://www.metric2.com and signup for the newsletter, this way I can stay in touch with people interested in learning more.

License:

This software is provided as is, and with no warranty. You may copy, modify and share the code for personal purposes. You may not sell or include, any parts, or as a whole, the software. Please share the download via the URL provided – Thanks.

Favor:

If you install Metric² and build an interesting dashboard, please tweet or share it in the comments. Also if you find any errors or issues on the installation process, please let me know and I will gladly update this guide. Thanks


pastedImage_1

HANA Talk – A Simple helper class for SAP HANA Development

HANA Talk is a small Javascript class which help facilitate the communication between your front end html/js files and HANA database when using SAP
HANA XS Engine. This is intended to help people who are just starting out development on XS Engine and would like a easy place to get  their feet wet without having to go through too much trial and error. This is also a great starting point for people involved in events like InnoJam, Hackathons, etc. when POC’s and demos need to developed quickly, but not necessarily perfectly *cough* or securely *cough*

By providing this tutorial and the HANA Talk download, my hope is that it will encourage more people to consider using XS Engine as a app platform to drive their front end web apps and subsequently, encourage the use and innovation around HANA in general. Anne Hardy had a comment in her blog post regarding the Developer Advisory Board which was along the lines of “Developers want to get it in 5mins max; they want to build real stuff in less than an hour”.

I frequently get discouraged by the amount of learning and effort always needed to learn new technologies and products which companies “get into bed with”. Nearly every one of the apps I develop start out in a POC type phase, where my imagination and reality clash and inevitably produce the equivalent of a 3yr old’s self portrait, often resembling “Unconventional”. While going through these exercises I often wish it was simple to get somethings done, and understanding the cost and willing to accept the trade offs. This is why I developed HANA Talk – to make those unconventional portraits, easier to deliver

OK – so what does it do?

By adding a HANA Talk js and xsjs file to your project, you can simply write SQL statements in your HTML file and have the results returned synchronously.

e.g.  Index.html

  1. <script type=”text/javascript”>
  2. var resp = hana.executeScalar(‘SELECT 1 FROM DUMMY’);
  3. console.log(resp); //Outputs 1
  4. </script>

Super simple and easy. See below for further details.

Prerequisites

1. Download/fork these 2 files – client.js & server.xsjs from Github and add them to your package. The filenames/structure can be changed if you are feeling adventurous. In your HTML file, you will need to reference client.js, this is as simple as adding a tag to you header. For reference, if you are not using SAP UI5 or jQuery – you will need to add this to your HTML header as well.

A Basic Example

2. In your javascript code, instantiate a new HanaTalk object. We will use this to “pass” our SQL commands to our HANA DB.

  1. var hana = new HanaTalk(‘SYS’); //The ‘SYS’ reference is in relation to the Schema. It can be specified here or within your TSQL Statement

3. Call your HanaTalk object with the operation type and SQL you would like execute (see below for additional operations).

  1. var result = hana.executeRecordSet(“SELECT 1 FROM DUMMY”);

4. We can populate that response into our html (DOM)

  1. document.getElementById(“SomeElementID”).innerHTML = result;

A few more examples

a.) Insert/Update/Delete a record – use .executeChange, this will execute your code and respond with the records which have been updated

  1. document.getElementById(“resp4″).innerHTML = /*hana.executeChange(“UPDATE/INSERT/DELETE …. “) + */ ‘ Record Changed’;

b.) Return a Table – using .executeRecordSet will return a html formatted table, displaying the select’s record set

  1. document.getElementById(“resp2″).innerHTML = hana.executeRecordSet(“SELECT TOP 5 * FROM M_HOST_INFORMATION”);

c.) Return a Object – .executeRecordSetObj allows us to loop through records, and have quite a lot of control of the display of each record and its column name.

  1. document.getElementById(“resp3″).innerHTML = hana.executeRecordSetObj(“SELECT TOP 5 * FROM M_HOST_INFORMATION”);

Here are the results of the calls above:

As you can see, making these types of calls is fairly simple and since your files reside directly on the DB app server, responsiveness is not too bad. So what’s so bad about this method?

Security: Because you are passing your SQL text directly from your browser to the backend server, you open yourself up to all kinds of SQL Injection hacks. Technically, we are not parsing URL arguments/parameters into the server side DB request but rather entire statements. In order for us to hack this, we could simply change the URL request to include some devious SQL.

Speed: For simplicity and to avoid AJAX Callbacks, the execution is performed Synchronously (i.e. We wait for the server to completely respond before we continue processing). The good: Code is “inline” and easy to manipulate the response/results from the server. The Bad: if we do a Select * on a massive (read billion) row table, the entire window is locked/hung until it either times out or completes. Not a particularly nice behaving UI.

The usual disclaimer: As mentioned, the intent of this post/download is to encourage simplicity, this comes at a cost, both performance and security are less than perfect – in this case, we will do our best to mitigate some of these. In fact, I expect a snarling comment from Thomas Jung, like a high school math teacher, disappointed that one of his protege openSAP students would even suggest these obscenities

I encourage you to test this out and provide some feedback or makes some changes and share this with the community.


Mockup

SAP UI5 – A Photoshop template of GUI elements

Mockup.png

For me (and I am sure many others!), UI5 has become a really useful toolkit for easily developing web apps and POC’s with little effort around the SAP Ecosystem. The OData support, rich controls and business inspired examples lend itself well to the mantra of “Don’t reinvent the wheel”. At a recent SAP Inside Track event in NY, I made reference to the fact, that while developing a mobile app, I, or a graphic designer, can spend close to 40% of the total design & development phase/hours on the UI. Building “consumer grade” enterprise apps is a different way of thinking for app developers. I am sure many of you, like me, started out with a redefined canvas of boring, grey .NET controls or a “Enjoy” SAP CXTAB_CONTROL. But times are changing and we should all look to the creative and vibrant consumer world of both web and mobile apps to reconsider our methods and processes for developing great apps.

When I started working with the UI5 toolkit, I would more often than not, start coding right away, without going through my traditional methods, and ultimately ended up in a frustrating muddled mess. Why wouldn’t you start coding immediately …. everything you need is right there? Wrong, planning is everything when it comes to design. Properly designing a app which is going to judged, by today’s standards, is not an option – but a requirement. I am not saying every application in your organization needs a UI Designer, but planning should start with sketches, process flows, and subsequently lead to the UI design and  development. When you have a toolkit which has some great looking components, its easy to skip this phase and get cracking. Don’t do it. Since I have spent a lot of time developing both web, mobile and traditional apps for the enterprise, my approach and system development life cycle (SDLC) resembles more of a artistic approach and design definition, than a “traditional” enterprise app. Yours can be entirely different, but the point is that I would like to encourage you to consider that a *great* design should be a part of your project goals.

The Reason

That’s the reason I developed the PSD file of UI5 elements. To make that design planning process quicker, easier and to encourage all of us collectively to make great designs and awesome apps.   Screen Shot 2013-07-09 at 9.19.16 PM.png

The Process

I used the online test suite and replicated the majority of the objects using shapes in Photoshop. Each object has groups/folders categorizing and defining it, both for extensibility and this makes finding a component/object easier. Some objects are not included: Icons and some of the VIZ Charts are not individual objects. Maybe in the near future if I can get some form of ‘OK’ from SAP for not copying/redistributing their font I will consider it (hint?).

Screen Shot 2013-07-09 at 9.15.29 PM.png  Screen Shot 2013-07-09 at 9.20.44 PM.png

The UI Toolkit

95% of graphic designers will spend time working with a UX/UI in Photoshop prior to coding and this toolkit makes creating those mockups considerably easier. Each object is defined as a shape and can be moved, and styled as needed. Currently the file has 897 individual layers which makes up the +- 8.2 million pixels of UI goodness . Building a new UI mockup should not take long … create a new file, duplicate the objects you need and get creative. (Please also consider the fact someone is going to need to code this and that your imagination, should be limited by *their* capabilities!)

Whats next …

I am hoping someone else interested in the UI/UX aspect will be able to contribute to the project and consider extending this file and its objects to cover all the aspects. I also hope that SAP will consider releasing its “Master” file to the community as ultimately it will encourage better adoption and use of the product.

My challenge to you ….

Does you/your company/partner have a UI/UX designer? Do you think its important to design a UI before coding? Do *you* have any great UI/Designs you would like to share? Post a link in the comments, or better yet, create a post here: https://experience.sap.com/ (SAP Why is experience.sap.com not directly integrated/on SCN??? )

You can download the file here:http://www.li-labs.com/downloads/sap%20ui5%20gui.psd

Don’t have Photoshop? Here are a couple of the elements split up and are available in PNG format: http://www.li-labs.com/sap%20ui5%20png.zip