|
|
|
| |
Remote logging in Java with UIQ Smartphones |
| |
Monitoring onboard debug/logging activity remotely via a web server. |
| |
|
| |
Carl Whalley, 16-Sep-2003 |
|
|
|
|
| Watching your app's internals across the internet |
|
|
Java programmers are familiar with the standard logging feature System.out.println(whatever). This is useful in an
emulator environment but increasingly apps are becoming internet aware and need a way to monitor activity on target. One approach
is to wrap the standard logging call into a common routine which can be directed to various destinations, all from the device itself.
This code is in PersonalJava for UIQ, but a J2ME version is very similar and the changes required for this are indicated.
|
|
// Example application
public class MyApp extends Frame implements ActionListener {
// Flags to control logging, managed by some means in code
private boolean logToRemote;
private boolean logToFile;
private boolean logToStdout;
...
public void log(String text) {
if (logToRemote) {
try {
Http.post("http://www.myloggingsite.com/monitor", "log="+text);
} catch (Exception e) {
}
}
if (logToFile) { // Not possible on J2ME
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter("MyApp.log"), true));
bw.write(message);
bw.newLine();
bw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
// always close the file
if (bw != null) {
try {
bw.close();
} catch (IOException ioe2) {
// just ignore it
}
}
}
}
if (logToStdout) {
System.out.println(text);
}
}
return;
}
// Utility class to POST data to a url
public class Http throws Exception {
public static String post(String url, String data) throws Exception {
String response="";
try {
URL targetUrl = new URL (url);
HttpURLConnection uc
= (HttpURLConnection) targetUrl.openConnection();
uc.setRequestMethod("POST");
uc.setAllowUserInteraction(false);
uc.setDoInput(true);
uc.setDoOutput(true);
uc.setUseCaches(false);
uc.setRequestProperty("Content-length", ""+data.length());
PrintWriter out= new PrintWriter(uc.getOutputStream(), true);
out.println(data);
BufferedReader in
= new BufferedReader(new InputStreamReader(uc.getInputStream()));
uc.connect();
String newLine="";
try {
while ((newLine=in.readLine())!=null) {
response=response+newLine+"\n";
}
} catch (IOException ioe) {
}
uc.disconnect();
uc = null;
in.close();
out.flush();
out.close();
} catch (Exception e) {
throw e;
}
return response.trim();
}
}
|
|
| Using the logger in client code |
|
|
Now all that needs to be done is to ensure all logging calls go through MyApp.log(). The flags to control logging could
be set via debug menu options or whatever. Http POST is used rather than a datagram socket (or other means) as it is the only
protocol mandated in the MIDP 1.x spec, so will be more widely compatible. The logs made to a local file open and close it
each time - this is so there is something to examine in case the program exits unexpectedly. Remote logging will obviously
slow down the apps operation, but used sensibly it can give a valuable "real time" insight into the workings of an app. Any
kind of logging calls can be made, for example it is very interesting to see memory usage remotely as a user moves through
a menu structure:
|
|
// Using the logger
public class MyAppSub {
private final SimpleDateFormat
todayDateFormatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");
MyApp app;
public MyAppSub(MyApp app) {
this.app = app;
}
private String getFormattedDateTime() {
Date today = new Date();
return new String(todayDateFormatter.format(today));
}
public void actionPerformed( ActionEvent ae ) {
app.log("MyAppSub::actionPerformed() Entry "+getFormattedDateTime()
+ " "+Runtime.getRuntime().freeMemory());
long start = System.currentTimeMillis();
// Code to analyse "ae" and perform various operations...
...
// Then, on leaving the event handler report stats
long end = System.currentTimeMillis();
long elapsed = (end - start) / 1000;
int mins = (int) elapsed / 60;
int secs = (int) elapsed % 60;
app.log("MyAppSub::actionPerformed() Exit ("+mins+"m"+secs+"s) "
+ getFormattedDateTime()+" "+Runtime.getRuntime().freeMemory());
}
}
|
|
|
Finally, a way of monitoring the calls to the remote server is needed. Using an appropriately configured J2EE server, this
could just be a tail running on its log file. The monitor servlet need do no more than the log operation itself:
|
|
| J2EE source to monitor log on server |
|
public class MonitorServlet extends HttpServlet {
public void doPost (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
System.out.println(req.getParameter("log"));
}
}
}
|
|
|
So there we have it - just remember to disable it in production code or your users really will have "Big Brother"
watching them!
|
|
|
| |
 |
|
|
|
|
|
|
|
|
Never before has it been possible to interact with such a vast market. Your business can extend right to
the place you want it the most : your customers. |
|
 |
|
|
Automated ebusiness is now very much an everyday reality across the globe. |
|
|
|
|
|
|
|
|
|
|
|
|
|
Instant access to realtime data. Make updates from any device and see
it change on all connected systems. All views of your data are supplied from one central |
|
 |
|
|
source. Use timely, accurate information where you need it the most - all secured by industry-standard
encryption systems as used by the military and governments. |
|
|
|
|
|
|
|
|
|
|
|
|
|
No-one knows your business better than you. When extending it to the internet your individuality will be
preserved. Methodologies exist which enable tried and
|
|
 |
|
|
tested business systems to be implemented modelling perfectly the business rules and logic you are using today. |
|
|
|
|
|
|
|