Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#115 CDI generation #116

Merged
merged 2 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Define a logger interface:
package com.foo;
...

@Log
@Logger
public interface MyLog {
@Message("Hello %s") // Uses java.util.Formatter and defaults to `INFO` level
void hello(String name);
Expand All @@ -61,12 +61,12 @@ public interface MyLog {
}
```

This will generate a class `com.foo.MyLog$impl` which actually does the logging. For Maven this can be seen in the `target/generated-sources/annotations/` folder for reference.
This will generate a class `com.foo.MyLogImpl` which actually does the logging. For Maven this can be seen in the `target/generated-sources/annotations/` folder for reference.

To get an instance use `uk.dansiviter.jule.LogProducer`:
To get an instance use `uk.dansiviter.jule.LogFactory`:
```java
public class MyClass {
private final static MyLog LOG = LogProducer.log(MyLog.class);
private final static MyLog LOG = LogFactory.log(MyLog.class);

public void myMethod() {
LOG.hello("foo");
Expand All @@ -79,18 +79,17 @@ public class MyClass {

## CDI ##

Simply create your own factory:
If you wish for CDI to manage the logger and and make it available for injection, just use:

```java
@ApplicationScoped
public class MyLogFactory {
@Produces @Dependent // Always use dependent scope to prevent proxying
public static MyLog myLog(InjectionPoint ip) {
return LogProducer.log(MyLog.class, ip.getMember().getDeclaringClass());
}
@Logger(lifecycle = Lifecycle.CDI)
interface MyLog {
...
}
```

This will generage a `@Dependent` logger implementation.

Then just inject:
```java
@ApplicationScoped
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>uk.dansiviter.jule</groupId>
<artifactId>jule-project</artifactId>
<version>0.7.0-SNAPSHOT</version>
<version>0.7.2-SNAPSHOT</version>
</parent>
<artifactId>benchmarks</artifactId>

Expand Down
14 changes: 6 additions & 8 deletions benchmarks/src/main/java/uk/dansiviter/jule/LogBenchmark.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,14 +15,12 @@
*/
package uk.dansiviter.jule;

import java.util.logging.Logger;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import uk.dansiviter.jule.annotations.Log;
import uk.dansiviter.jule.annotations.Logger;
import uk.dansiviter.jule.annotations.Message;
import uk.dansiviter.jule.annotations.Message.Level;

Expand All @@ -33,17 +31,17 @@ public static class TestState {

@Setup
public void setup() {
log = LogProducer.log(BenchmarkLog.class, LogBenchmark.class);
log = LoggerFactory.log(BenchmarkLog.class, LogBenchmark.class);
}
}

@State(Scope.Benchmark)
public static class LegacyState {
Logger log;
java.util.logging.Logger log;

@Setup
public void setup() {
log = Logger.getLogger(LogBenchmark.class.getSimpleName());
log = java.util.logging.Logger.getLogger(LogBenchmark.class.getSimpleName());
}
}

Expand All @@ -63,7 +61,7 @@ public void legLog(LegacyState state) {
}
}

@Log
@Logger
public interface BenchmarkLog {
@Message("Hello %d")
void hello(int i);
Expand Down
1 change: 0 additions & 1 deletion core/src/main/java/uk/dansiviter/jule/AsyncHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package uk.dansiviter.jule;

import static java.nio.charset.Charset.defaultCharset;
import static java.util.concurrent.ForkJoinPool.commonPool;
import static java.util.logging.ErrorManager.GENERIC_FAILURE;
import static java.util.logging.ErrorManager.OPEN_FAILURE;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,7 @@
*/
package uk.dansiviter.jule;

import static java.lang.String.format;
import static java.util.logging.Logger.getLogger;

import java.util.function.Supplier;
Expand All @@ -26,10 +27,10 @@
/**
* Base {@code java.util.Logger} implementation.
*/
public interface BaseJulLog extends BaseLog<Logger> {
public interface BaseJulLogger extends BaseLogger<Logger> {
@Override
default Logger delegate(String name) {
var bundleName = log().resourceBundleName();
var bundleName = logger().resourceBundleName();
return getLogger(name, bundleName.isBlank() ? null : bundleName);
}

Expand All @@ -49,19 +50,26 @@ default void log(Message.Level level, Supplier<String> msg, Throwable thrown) {
}
}

@Override
default String render(String msg, Object... params) {
var resourceBundle = delegate().getResourceBundle();
return format(resourceBundle != null ? resourceBundle.getString(msg) : msg, params);
}

private static Level level(Message.Level level) {
switch (level) {
case ERROR:
return Level.SEVERE;
return Level.SEVERE;
case WARN:
return Level.WARNING;
return Level.WARNING;
case INFO:
return Level.INFO;
return Level.INFO;
case DEBUG:
return Level.FINE;
return Level.FINE;
case TRACE:
return Level.FINER;
return Level.FINER;
default:
return Level.OFF;
}
throw new IllegalArgumentException("Unknown type! [" + level + "]");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,22 +29,22 @@
import java.util.function.LongSupplier;
import java.util.function.Supplier;

import uk.dansiviter.jule.annotations.Log;
import uk.dansiviter.jule.annotations.Logger;
import uk.dansiviter.jule.annotations.Message;

/**
* Defines the base implementation of the logger interface.
*/
public interface BaseLog<L> {
public interface BaseLogger<L> {
/**
* @return the delegate logger.
*/
L delegate();

/**
* @return the {@link Log} instance.
* @return the {@link Logger} instance.
*/
Log log();
Logger logger();

/**
* Gets delegate logger instance.
Expand Down Expand Up @@ -72,7 +72,7 @@ public interface BaseLog<L> {
*/
default void logp(Message.Level level, String msg, Object... params) {
// isLoggable check will already be done
BaseLog.expand(params);
BaseLogger.expand(params);

Throwable thrown = null;
if (params.length > 0 && params[params.length - 1] instanceof Throwable) {
Expand All @@ -81,7 +81,11 @@ default void logp(Message.Level level, String msg, Object... params) {
}

var finalParams = params;
log(level, () -> format(msg, finalParams), thrown);
log(level, () -> this.render(msg, finalParams), thrown);
}

default String render(String msg, Object... params) {
return format(msg, params);
}

void log(Message.Level level, Supplier<String> msg, Throwable thrown);
Expand Down
20 changes: 10 additions & 10 deletions core/src/main/java/uk/dansiviter/jule/BaseSystemLog.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,12 +30,11 @@
* <strong>Note:</strong> This API has no mechanism for finding source class and method so will likely just state this
* class as the source.
*/
public interface BaseSystemLog extends BaseLog<Logger> {

public interface BaseSystemLog extends BaseLogger<Logger> {

@Override
default Logger delegate(String name) {
var bundleName = log().resourceBundleName();
var bundleName = logger().resourceBundleName();
if (bundleName.isEmpty()) {
return getLogger(name);
}
Expand All @@ -62,16 +61,17 @@ default void log(Message.Level level, Supplier<String> msg, Throwable thrown) {
private static Level level(Message.Level level) {
switch (level) {
case ERROR:
return Level.ERROR;
return Level.ERROR;
case WARN:
return Level.WARNING;
return Level.WARNING;
case INFO:
return Level.INFO;
return Level.INFO;
case DEBUG:
return Level.DEBUG;
return Level.DEBUG;
case TRACE:
return Level.TRACE;
return Level.TRACE;
default:
return Level.OFF;
}
return Level.OFF;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,14 +22,14 @@
import java.util.Map;
import java.util.WeakHashMap;

import uk.dansiviter.jule.annotations.Log;
import uk.dansiviter.jule.annotations.Logger;

/**
* This class provides instances of the log wrappers.
*/
public enum LogProducer { ;
public enum LoggerFactory { ;
private static final Map<String, ? super Object> LOGS = new WeakHashMap<>();
public static final String SUFFIX = "$impl";
public static final String SUFFIX = "Impl";

/**
* Return an instance of the given type. This will attempt to walk the stack
Expand Down Expand Up @@ -60,23 +60,23 @@ public static <L> L log(Class<L> log, Class<?> name) {
*
* @param <L> the log type.
* @param logClass the log class type.
* @param name the log ename.
* @param name the log name.
* @return log instance. This may come from a cache of instances.
*/
public static <L> L log(Class<L> logClass, String name) {
if (!logClass.isAnnotationPresent(Log.class)) {
throw new IllegalArgumentException(format("@Log annotation not present! [%s]", logClass.getName()));
if (!logClass.isAnnotationPresent(Logger.class)) {
throw new IllegalArgumentException(format("@Logger annotation not present! [%s]", logClass.getName()));
}
var key = key(logClass, name);
return logClass.cast(LOGS.computeIfAbsent(key, k -> create(key, logClass, name)));
return logClass.cast(LOGS.computeIfAbsent(key, k -> create(logClass, name)));
}

private static Object create(String key, Class<?> logClass, String name) {
private static Object create(Class<?> logClass, String name) {
var className = logClass.getName().concat(SUFFIX);
try {
return Class.forName(className, true, logClass.getClassLoader())
.getDeclaredConstructor(String.class, String.class)
.newInstance(name, key);
.getDeclaredConstructor(String.class)
.newInstance(name);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException(format("Unable to instantiate class! [%s]", className), e);
}
Expand All @@ -90,7 +90,7 @@ private static Object create(String key, Class<?> logClass, String name) {
* @param name the log name.
* @return the key.
*/
public static String key(Class<?> log, String name) {
private static String key(Class<?> log, String name) {
return format("%s-%s", log.getName(), requireNonNull(name)).intern();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,7 +38,7 @@
*/
@Target({ TYPE, FIELD })
@Retention(RUNTIME)
public @interface Log {
public @interface Logger {
/**
* @return the name of the resource bundle.
* @see java.util.logging.Logger#setResourceBundle(java.util.ResourceBundle)
Expand All @@ -50,6 +50,15 @@
*/
Type type() default Type.JUL;

/**
* @return the lifecycle management of the logger.
*/
Lifecycle lifecycle() default Lifecycle.DEFAULT;


/**
* Type of underlying delegate logger.
*/
public enum Type {
/**
* Uses {@link java.util.logging.Logger} as delegate.
Expand All @@ -60,4 +69,18 @@ public enum Type {
*/
SYSTEM
}

/**
* Type of lifecycle for the logger.
*/
public enum Lifecycle {
/**
* Logger can be accessed via {@code LogFactory#log(...)} methods.
*/
DEFAULT,
/**
* In addition to {@link #DEFAULT} logger lifecycle will be managed by CDI as a {@link Dependent}
*/
CDI
}
}
Loading