My Apache Tomcat Server is getting periodic updates from a Java based client Application, At the moment the scenario is just one client and talking to the server.
I want to log the messages from the client onto the server with time-stamp what kind of framework will help me in achieving this?
EDIT: The OP goal was actually pretty unclear and I'm modifying my answer after some clarifications.
Well, I'm not sure, but maybe a logging framework will suit your needs. If so, have a look at:
Log4J: The most famous logging framework, widely used.
Java Logging aka java.util.logging: didn't succeed to replace Log4J.
Logback: "Logback is intended as a successor to the popular log4j project. It was designed, in addition to many individual contributors, by Ceki Gülcü, the founder of log4j".
SL4J: A "Simple Logging Facade for Java serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time".
And pick one of them (I'd use Log4J or Logback).
To save your messages for later processing from the webapp (e.g. generating a web page with some graphs/charts), the best approach is to use a database. Just read/write them from/to a simple table with a timestamp column.
If you are not really familiar with Java, JDBC, persistence, connection pooling, datasource, etc, I'd suggest to use the Spring framework as it will hide most of the complexity. For the database part, have a look at the Chapter 11. Data access using JDBC from the Spring documentation. Pay a special attention to the JdbcTemplate or the SimpleJdbcTemplate, they should allow you to get the job done.
Create a special JSP page for accepting log entries, and invoke it with
http://..... foo.jsp?l=the%20stuff%to%log (i.e. URL encoded)
You then just need to pick out the "l" parameter and do with it what you need to do. An initial implementation could be invoking the log(String s) method in the servlet context.
Related
I'd like to write some generic batch listeners to log out some useful information of all batches configured in my application. To do so I'd like to get the configured skippable/retryable exceptions from batch configuration. However I did not find any API for that. Is there a way to retrieve this configuration independant of the jsr352 implementation?
No you won't see this or anything similar really in the specification API (so anything that did exist would be impl-specific).
The theme of separation of concerns lies behind many of the API choices, and nothing like a "job definition model" API exists in the spec.
I'd like to trace my async application with some key checkpoint.
Is there any popular framework I can use?
For example, I may choose to use vert.x or any other java async framework. For each request/response cycle, I'd make some checkpoint to log something while these points might happen in different threads.
I'd like to see an aggregated view of 1 request to see what's going on. Supporting distributed case would be better but single JVM is good to go.
What you are looking for is OpenTracing. It's an API that allows you to have distributed tracing features in a way that is vendor agnostic.
For your specific case, you'd have to handle the context propagation yourself, as there's no other (reliable) way to do that on OpenTracing yet for teh async case. For other cases (sync JAX-RS, Servlets, Spring Boot, ...), it would be safe to use the native framework integration and/or the Java agent rules.
For Vert.x, you'll need to inject the span context into Vert.x' message, and extract this context later on.
There's an example of OpenTracing + Vert.x on the Hawkular APM example directory, that might help you get started. Note, however, that you might want to use another backend should you decide to move forward, as we (Hawkular APM team) decided to join forces with Jaeger for the OpenTracing backend.
I want to build a more advanced logging mechanism for my java web applications, similar to App engine logs.
My needs are:
Stream logs to a database (for ex. sql, bigquery or something else)
Automatically log important data (like app context, request url, request id, browser user agent, user id, etc.)
For point 1, I ca use a "buffering" implementation, where logs are put into different lists, and periodically a cron (thread) gathers all the logs in memory and write's them to database (which can also be on another server)
For point 2, the only way I found of doing this is to inject needed objects into my classes (subsystems), like ServletContext, HttpServletReqest, current user, etc, all modeled into a custom class (let's say AppLogContext), which then can be used by the logging mechanism.
The problem here is that I don't know if this is a good practice. For example, that means that many classes will have to contain this object which has access to servlet context and http request objects and I'm thinking this may create architectural problems (when building modules, layers etc) or even security issues.
App Engine will automatically log this kind of information (and much more, like latencies, cpu usage etc, but this more complicated), and it can be found in the project's Console logs (also it can duplicate logs to big query tables) and I need something for Jetty or other java web app servers.
So, is there another way of doing this, other patterns, different approaches? (couldn't find 3rd party libraries for any of these points)
Thank you.
You don't really need to invent a bicycle.
There is a common practice that you can follow:
Just log using standard logger to a file
(if you need to see logs in request context) Logback, Log4J and SLF4J supports Mapped Diagnostic Context (MDC), that's what you can use to put current request into every log line (just initialize context in a filter, put request id for example, or generate a random uuid). You can aggregate log entries by this id later
Then use ELK:
Logstash got gather logs into
ElasticSearch for storing logs
to analyze using Kibana
Requirement: Log events like Page Views and form Submits. Each page has ~1 second SLA. The application can have 100's of concurrent users at a time.
Log events are stored into the Database.
Solution: My initial thought was to use an async logging approach where the control returns back to the application and the logging happens in a different thread (via Spring's Thread pool task executor).
However someone suggested using JMS would be a more robust approach. Is the added work(Setting-up queue(s), writing to the queue(s), reading from the queue(s)) required when using this approach worthwhile?
What are some of the best practices / things to look out for (in a production environment) when implementing something like this?
Both approaches are valid, but one is vulnerable if you app unexpectedly stops. In your first scenario, events yet to be written to the database will be lost. Using a persistent JMS queue will mean that those events will be read from the queue and persisted to the database upon restart.
Of course, if your DB writes are so much slower than placing a message of similar size on to a JMS queue, you may be solving the wrong problem?
Using JMS for logging is a complete mismatch. JMS is a Java Abstraction for a Middleware Tool like MQ Series. That is complete overkill, and will let you go through a setup and configuration hell. JMS also lets you place messages in a transactional context, so you already get quickly the idea that JMS might be not much better than Database writes as #rjsang suggested.
This is not that JMS is not a nice technolgy. It is a good technology where it is applied properly.
For Assynchronous logging, you better just depend on a Logging API that directly supports it like Log4j2. In your case, you might be looking to configure a AsyncAppender with a JDBCAppender. Log4j2 has many more appenders as additional options, including one for JMS. However, by at least using a Logging abstraction, you make that all configurable and will make it possible to change your mind at a later time.
In the future we might have something similar to Asynchronous CDI Events, which should work similar to JMS, but would be much more lightweight. Maybe you can get something similar to work by combining CDI Events with EJB Asynchronous Methods. As long as you don't use EJB's with a remote interface, it should also be pretty lightweight.
You could give it a try using fully async and external tooling if you want to. If you have to stick to your SLA at any price and resilience is important for you, you could try using either logstash or process your logs offline. With doing so, you decouple your application from the database and you are no longer depending on the database performance. If the database is slow and you're using async loggers, queues might run full.
With logstash using GELF the whole log processing is handled within a different (or even remote) JVM. Offline processing (e.g. you write CSV logs) allows you to load the log data afterwards into the database.
I've learned a lot about JMX over the past couple of years and have built some pretty fancy MBeans for my web applications. However, I'm not sure I have a good answer to a pretty basic question:
Why use JMX over simple HTTP servlets?
My current web applications offer redundant monitoring options: I can access the data that needs to be monitored via JMX with a client like JConsole or I can access that same data in XML format via a servlet. I don't see a strong reason to use one method over another, but the servlet method does have the major advantage of being readable by a simple http client / web browser.
I can see how JMX would be quite useful for Java applications that aren't web apps, but I can't see any advantage to using JMX for a web app.
Why use JMX over simple HTTP servlets?
From my standpoint, JMX is better for 3 reasons:
It requires less code to enable monitoring points.
It deals with Java serialized objects end-to-end so there is better data consistency.
It works with programs that are not servlet based (as you mentioned).
JMX offers a much easier interface to specific data items. You can certainly write the same functionality in a number of servlets, but it is easier for me to expose those using JMX.
For example, if you are using Spring then you can use the org.springframework.jmx.export annotations (#ManagedResource, #ManagedAttribute, etc.) to mark up your classes. I've also published my SimpleJmx framework so you can easily expose attributes and operations with just a couple annotations independent of Spring. For example:
#JmxResource(domainName = "j256", objectName = "lookupCache")
public class LookupCache {
// this can also be done as #JmxAttributeMethod on the getter/setters
#JmxAttributeField(description = "Number of hits in the cache")
private int hitCount;
...
#JmxOperation(description = "Flush the cache")
public void flushCache() {
...
}
}
I have a fully working example program to see how it works. So all you need to do to expose a value or operation is add an annotation to the class and each attribute and/or method. The code to publish it using SimpleJmx looks like the following. Spring is similar albeit with beans:
// create a new server listening on port 8000
JmxServer jmxServer = new JmxServer(8000);
jmxServer.start();
// register our lookupCache object defined above
jmxServer.register(lookupCache);
To get similar functionality in servlets would take a lot more code than just annotations. That said, there may exist frameworks which provide similar functionality in servlet land that I don't know about.
Some more notes:
There are probably better monitoring tools that grok HTTP/HTML but there are also a ton of distributed JMX monitoring applications. Probably a toss up.
Being able to programmatically get objects from JMX servers is a plus as opposed to just strings from a servlet page. SimpleJmx also supports a simple JMX client although better ones exist out there.
Obviously a lot of other worthwhile data is already published by the JVM by default: VM settings, thread details, memory information, etc..
In addition to reading values, JMX can be used to invoke methods on Management Beans.
For example, we often use it to force a JVM garbage collection for Tomcat instances remotely.
Also because JMX is a different port that http/https you can limit access at the network level via firewalls. JMX has built-in username/password authentication as well.
A web servlet would have to implement it's own access control.
In my opinion JMX is overrated and it can be tricky to configure.
If your application is already a webcontainer I think you should definitely go for a simple servlet.
A tiny servlet approach like nudge4j would give you everything and more.