How can you log from a Neo4j Server Plugin? - neo4j

I'm trying to debug a problem in the Neo4J Server plugin I'm writing. Is there a log I can output to? It's not obvious where or how to do this.

Good question. I think you could use Java Logging? That should be routed into the normal logging system.

Just inject org.neo4j.logging.Log in your class containing implementation of your Neo4j stored procedure.
public class YourProcedures {
#Context
public Transaction tx;
#Context
public Log log;
#Procedure(value = "yourProcedure", mode = Mode.READ)
public Stream<YourResult> yourProcedure(#Name("input") String input) {
log.debug("something");
}
}
Logs are then dumped into standard Neo4j log file.
The level is controlled by GraphDatabaseSettings.store_internal_log_level configuration.
The level can be also changed in runtime. Just inject DependencyResolver bean and define this admin procedure. (The framework has listener hooked to config change which reconfigures the internal logging framework. This is the simplest solution I could find.)
#Context
public DependencyResolver dependencyResolver;
#Procedure(value = "setLogLevel", mode = Mode.DBMS)
#Description("Runtime change of logging level")
public void setLogLevel(#Name("level") String level) {
Config config = dependencyResolver.resolveDependency(Config.class);
config.set(GraphDatabaseSettings.store_internal_log_level, Level.valueOf(level));
}
UPDATE:
This ^ solution works, however it is insufficient when one wants to use logging the way usual in Log4j - different loggers organized in hierarchy, each logger at its own level. The org.neo4j.logging.Log component is just a wrapper of Log4j logger for the GlobalProcedures class. This logger is only one of many loggers in hierarchy. In fact, the wrapper blocks access to richer features of underlying framework. (Unfortunately, to define multiple #Context Log fields in YourProcedures class distinguished by some annotation qualifying logger is also impossible because field injection is driven by Map<Class,instance> so there is only one possible instance to inject for any #Context-annotated field according to field type.)
Solution 1:
Use JUL as in accepted answer. The disadvantage is, JUL redirects log event to underlying Log4j anyway so if logger hierarchy is defined in JUL, Log4j must be set to lowest possible level in order to make JUL levels sensitive.
Solution 2:
Use Log4j directly (i.e. public static final Logger logger = LogManager.getLogger("some.identifier.in.hierarchy") in YourProcedures). There are some issues with redefining configuration programmatically though it is possible, I dropped this solution only because I had some trouble deploying this solution in non-docker environment.
Solution 3: (finally chosen)
I defined custom component LogWithHierarchy (it can be built from own ExtensionFactory loaded using ServiceLoaders - I was inspired in APOC config implementation). This component provides API of the form debug(loggerName, message), info(loggerName, message) etc. The component knows original Log, drills down into its log4j LoggerContext and redirects all logging requests to particular logger in this LoggerContext. Log messages finally end in debug.log. With this solution the original log4j logger hierarchy is fully utilized, levels can be changed dynamically in runtime (setLogLevel must be changed to operate on aforementioned LoggerContext) and still everything is implemented using standard Neo4j plugin support.

Related

How to get and cast JNDI object correctly in Liberty

I have a big problem on getting the correct instance or at least casting the instance I got with JNDI-lookup to correct interface at Web Sphere Liberty (16.0.0.4, running on Java 7, though using Oracle Java 1.8.0_45 in the back, developing on Eclipse Neon.2).
When I start the server and the ear containing the EJB, I get the following notification into the log:
The server is binding the xxx.interfaces.MyLocal interface of the MyEJB enterprise bean in the xxx-ejb.jar module of the xxx-ear application. The binding location is: java:global/xxx/MyEJB!xxx.interfaces.MyLocal
Then I have a web application (ear) which has a service provider (with #Produces) for the previously started ejb-service, which will provide the JNDI resource as injectable (#Inject) for the rest of the application (a bit tricky thing, the main idea is to allow to change the lookup location from configuration file + do some other stuff also). It seems to work correctly for all it is supposed to, but when getting the JNDI-resource, it kind of works but not correctly.
If I put the ejb part as a dependency into my web-module, I can inject it directly (#Inject MyLocal myEjb;).
As the injected resource I get an object with the signature:
EJSMyLocal0SLMyEJB_a4549339#cc5d2cdd
with lookup I get an object with signature (at the same time as the inject):
EJSMyLocal0SLMyEJB_a4549339#cdda36a7
(Not the same instance afaik, but the "type" is correct?)
The injected resource is correctly (automatically of course) cast on 'MyLocal' interface and is ok.
When I try to check the resource got with JNDI, it does not qualify as an instance of 'MyLocal' nor as 'MyRemote'? Also the actual cast fails of course with ClassCastException. (MyRemote is basically the same as the MyLocal interface ... MyLocal extends MyRemote, both interfaces are accordingly annotated with #Local and #Remote)
The EJB looks like this at the time of testing...
#Stateless
#Named
#Default
#Local(MyLocal.class)
#Remote(MyRemote.class)
public class MyEJB implements MyLocal, MyRemote { ... }
I also tried to cast the JNDI resource like this.
InitialContext ic = new InitialContext();
Object lookedUpEjb = ic.lookup(lookup); // the 'java:global...' from log
MyRemote jndiEjb = (MyRemote) PortableRemoteObject.narrow(lookedUpEjb, MyRemote.class)
// Tried also casting/checking 'instanceof' to MyLocal...
No difference with that, the same ClassCastException occurs?!
I have the following features in server.xml
<featureManager>
<feature>javaee-7.0</feature>
<feature>ldapRegistry-3.0</feature>
<feature>localConnector-1.0</feature>
<feature>adminCenter-1.0</feature>
<feature>wsSecurity-1.1</feature>
<feature>ejbLite-3.2</feature>
<feature>ejbRemote-3.2</feature>
<feature>cdi-1.2</feature>
<feature>jpa-2.1</feature>
<feature>jsf-2.2</feature>
<feature>jaxrs-2.0</feature>
<feature>jaxws-2.2</feature>
</featureManager>
I found this documentation on the Liberty JNDI functionality:
https://www.ibm.com/support/knowledgecenter/SSAW57_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_ejb_remote.html
I can't see where I go wrong. How do I cast that object from JNDI lookup to MyLocal or MyRemote interfaces?
---- Note ----
Using the #EJB annotation is not an option (it works though), since it will be hard coded reference to the resource. I want it to be optional though, thus JNDI lookup. #EJB will cause the app to crash when the resource is not available.
The problem is that each application has a different ClassLoader and the object that has been bound into JNDI was loaded with the ClassLoader of the application that defined the EJB.
This should not be an issue for Remote EJB interfaces as the ORB should have taken care of this for you. On a remote call that returns such an object, the ORB will serialize the object (from the target ClassLoader) and then deserialize using the client ClassLoader. For a lookup like this, the PortableRemoteObject.narrow should also take care of this. The failure here appears to just be a bug in the ORB.
In order to support cross application access to Local EJB interfaces, either the Local EJB interface needs to be moved to a shared library, that is used by both applications, or both applications configured to use a single global ClassLoader. See this link for more information about using Local EJB interfaces across applications: Correct way to lookup local EJB in websphere - Getting ClassCastException (Note: this link is discussing traditional WebSphere, but the issue is the same with Liberty, as is the resolution to use a shared library for the interface).

log is not accessible in normal groovy file of grails3

Migrated grails2 to grails3.
In grails2 i used lots of
log.info,log.debug
statements in side src/main/groovy files.
but in grails-3 by default log is not injected.
it's giving error like No such property: log for class
This is a planned change. You can use #groovy.util.logging.Commons annotations on your non-grails classes to have log available. Also other like #Log4j, #Slf4j are available, depending on your logging library.
There is one more difference which is important - those annotations will add log as private property and classes which will inherit from them, will also need to be annotated to use logging. Alternative is to manually define protected logger on your class.

How to configure Simple Injector depending on build configuration

I want to be able, to configure Simple Injector differently for each developer (for prototyping purposes for example).
The default configuration should be hardcoded, of course.
I have used Unity before, and there I was able to overwrite the hardcoded registrations by an XML configuration file. This config file was not under source control, and so other developers could overwrite the hardcoded registrations with their custom registrations without interfering with others.
The developers should not need to submit their configuration to source control.
Is such a scenario supported by Simple Injector ?
Is there any best practice for such a scenario ?
Does this make sense at all, or is there a better way to achieve what I want?
One of the design decisions for Simple Injector is to not support XML based configuration out-of-the-box. This decision is described here but can be summarizes as:
XML based configuration is brittle, error prone and always provides a
subset of what you can achieve with code based configuration. General
consensus is to use code based configuration as much as possible and
only fall back to file based configuration for the parts of the
configuration that really need to be customizable after deployment.
These are normally just a few registrations since the majority of
changes would still require developer interaction (write unit tests or
recompile for instance). Even for those few lines that do need to be
configurable, it’s a bad idea to require the fully qualified type name
in a configuration file. A configuration switch (true/false or simple
enum) is more than enough. You can read the configured value in your
code based configuration, this allows you to keep the type names in
your code. This allows you to refactor easily, gives you compile-time
support and is much more friendly to the person having to change this
configuration file.
This however doesn't completely satisfy your requirements, since you don't want to "customizable after deployment". Instead, you want to customize per developer.
For this particular case, you shouldn't fall back on XML based configuration IMO. Just as you can exclude xml files using .gitignore, you can do the same with code based configuration files that developers can change, and that will compile with the rest of the application. Here's an example:
// Global.cs
public void Application_Start() {
var container = new Container();
// Default configuration here
container.Options.AllowOverridingRegistrations = true;
DeveloperOverrides.ApplyOverrides(container);
container.Options.AllowOverridingRegistrations = false;
DependencyResolver.Current = new SimpleInjectorDependencyResolver(container);
}
// DeveloperOverrides.cs
public static class DeveloperOverrides {
public static void ApplyOverrides(Container container) {
}
}
These two files can be checked in, where the DeveloperOverrides.ApplyOverrides method is left blank. After that you add the exclusion of the DeveloperOverrides.cs to your .gitignore file.
After this, developers can add their own overrides that are checked by the compiler, but are never checked in into source control:
// DeveloperOverrides.cs
public static class DeveloperOverrides {
public static void ApplyOverrides(Container container) {
container.Register<IMailSender, FakeMailSender>(Lifestyle.Singleton);
}
}

Custom Log Level in Grails

I want to be informed when uncaught exceptions occur in my Grails 2.2.4 application. Log4j has an SMTPAppender doing something similar, but only based on a specific log level. In my application there are already a lot of log entries in all available log levels, so sending email on ERROR or FATAL is not really an option because it would also contain non-exception entries.
Filtering uncaught exceptions in Grails is quite easy, I just redirect them to a specific controller and handle it there:
static mappings = {
[...]
"500"(controller: "errors", action: "serverError")
}
My plan was to introduce my own log level and use it only for uncaught exceptions. Documentation suggests this:
final Level EXCEPTION = Level.forName("EXCEPTION", 50);
logger.log(EXCEPTION, "uncaught exception", e);
But I don't know how to use this in Grails with the injected log object. It only supports the base options like log.error('foo',e). Grails documentation says how to add custom appenders, but nothing about custom levels (or did I miss it?!)
Any suggestions?
Grails uses Slf4j and Commons Logging to abstract the logger implementation and allow changing from Log4j to another framework without having to edit every file with a logger. Instead, the wrapper library gets the correct implementation instance based on the requested logger name and what's available from the native API. If you change implementations, the wrapper loggers work the same way as far as your app code is concerned, but they call different implementation loggers to do the actual logging.
But there's no standard between implementations for configuration, so internal Grails startup code works directly with the API to configure loggers, appenders, levels, etc. You can do the same - use the traditional Log4j logger access code to get an instance by logger name, using the same one as the preconfigured logger Grails wired up. I can never remember the naming convention for loggers in artifacts, so I cheat and add a line of code
println log.name
in a method that I know runs, and call that method indirectly via whatever controller action can get there. So for example, if I want to know the logger of FractalService, put that code in its graphJuliaSet method and call the controller action that graphs Julia Sets using this service.
Log4j loggers are singletons, if you access the logger and change it, that will affect all future calls.
So that logger is available via something like:
String name = ... // the name from the println above
Logger logger = Logger.getLogger(name)

adding loggers to Grails classes

I use the following approach to access a logger instance from classes in a Grails app:
In Grails artefacts (controllers, services, domain classes, etc.) I simply use the logger that is added by Grails, e.g.
class MyController {
def someAction() {
log.debug "something"
}
}
For classes under src/groovy I annotate them with #groovy.util.logging.Slf4j, e.g.
#Slf4j
class Foo {
Foo() {
log.debug "log it"
}
}
The logger seems to behave properly in both cases, but it slightly bothers me that the class of the loggers differs. When I use the annotation, the class of the logger is org.slf4j.impl.GrailsLog4jLoggerAdapter, but when I use the logger that's automatically added to Grails artefacts the class is org.apache.commons.logging.impl.SLF4JLog.
Is there a recommended (or better) approach to adding loggers to Grails classes?
I don't see any problem with what you described. SLF4J isn't a logging framework, it's a logging framework wrapper. But aside from some Grails-specific hooks in the Grails class, they both implement the same interface and delegate eventually to the same loggers/appenders/etc. in the real implementation library, typically Log4j.
What I'm pretty sure is different though is the log category/name, because you need to configure the underlying library based on what the logger names become. With annotations the logger name is the same as the full class name an package. With the one Grails adds, there's an extra prefix based on the artifact type. I always forget the naming convention but a quick way to know the logger name is to log it; add this in your class where it will be accessed at runtime:
println log.name
and it will print the full logger name (using println instead of a log method avoids potential misconfiguration issues that could keep the message from being logged
I like to keep things simple and consistent and know that being used, so I skip the wrapper libraries and use Log4j directly. Access the logger is easy. Import the class
import org.apache.log4j.Logger
and then add this as a class field:
Logger log = Logger.getLogger(getClass().name)
This can be copy/pasted to other classes since there's no hard-coded names. It won't work in static scope, so for that I'd add
static Logger LOG = Logger.getLogger(this.name)
which also avoids hard-coding by using Groovy's support for "this" in static scope to refer to the class.
Have you tried the #Log4j (for log4j) instead.
#Log4j (for log4j)
How can i use 'log' inside a src/groovy/ class

Resources