Browse Source

Initial work on Logback logging.

pull/578/head
Greg Holmes 9 years ago
parent
commit
6518193f7d
3 changed files with 153 additions and 0 deletions
  1. 1
    0
      build.gradle
  2. 28
    0
      src/com/dmdirc/Main.java
  3. 124
    0
      src/com/dmdirc/ProgramErrorAppender.java

+ 1
- 0
build.gradle View File

@@ -36,6 +36,7 @@ dependencies {
36 36
     compile group: 'com.squareup.dagger', name: 'dagger-compiler', version: '1.2.1'
37 37
     compile group: 'com.google.auto.value', name: 'auto-value', version: '1.0'
38 38
 
39
+    bundle group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.2+'
39 40
     bundle group: 'org.slf4j', name: 'slf4j-api', version:'1.7.10'
40 41
     bundle group: 'com.squareup.dagger', name: 'dagger', version: '1.2.1'
41 42
     bundle group: 'com.esotericsoftware.yamlbeans', name: 'yamlbeans', version: '1.08'

+ 28
- 0
src/com/dmdirc/Main.java View File

@@ -55,6 +55,12 @@ import java.util.concurrent.TimeUnit;
55 55
 
56 56
 import javax.inject.Inject;
57 57
 
58
+import org.slf4j.Logger;
59
+import org.slf4j.LoggerFactory;
60
+
61
+import ch.qos.logback.classic.LoggerContext;
62
+import ch.qos.logback.classic.joran.JoranConfigurator;
63
+import ch.qos.logback.core.spi.ContextAware;
58 64
 import dagger.ObjectGraph;
59 65
 
60 66
 /**
@@ -62,6 +68,7 @@ import dagger.ObjectGraph;
62 68
  */
63 69
 public class Main {
64 70
 
71
+    private final Logger log = LoggerFactory.getLogger(Main.class);
65 72
     /** The UI to use for the client. */
66 73
     private final Collection<UIController> CONTROLLERS = new HashSet<>();
67 74
     /** The identity manager the client will use. */
@@ -90,6 +97,14 @@ public class Main {
90 97
     private final ModeAliasReporter reporter;
91 98
     private final ServiceManager serviceManager;
92 99
 
100
+    static {
101
+        // TODO: Can this go in a Dagger module?
102
+        final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
103
+        final ContextAware configurator = new JoranConfigurator();
104
+        configurator.setContext(context);
105
+        context.reset();
106
+    }
107
+
93 108
     /**
94 109
      * Creates a new instance of {@link Main}.
95 110
      */
@@ -160,6 +175,7 @@ public class Main {
160 175
      */
161 176
     public void init() {
162 177
         Thread.setDefaultUncaughtExceptionHandler(new DMDircExceptionHandler(eventBus));
178
+        setupLogback();
163 179
         migrators.stream().filter(Migrator::needsMigration).forEach(Migrator::migrate);
164 180
         commands.forEach(c -> commandManager.registerCommand(c.getCommand(), c.getInfo()));
165 181
 
@@ -256,4 +272,16 @@ public class Main {
256 272
         }
257 273
     }
258 274
 
275
+    private void setupLogback() {
276
+        // TODO: Add a normal logging thing, with or without runtime switching.
277
+        final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
278
+        final ProgramErrorAppender appender = new ProgramErrorAppender();
279
+        appender.setEventBus(eventBus);
280
+        appender.setContext(context);
281
+        appender.setName("Error Logger");
282
+        appender.start();
283
+        final ch.qos.logback.classic.Logger rootLogger = context.getLogger(Logger.ROOT_LOGGER_NAME);
284
+        rootLogger.addAppender(appender);
285
+    }
286
+
259 287
 }

+ 124
- 0
src/com/dmdirc/ProgramErrorAppender.java View File

@@ -0,0 +1,124 @@
1
+/*
2
+ * Copyright (c) 2006-2015 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc;
24
+
25
+import com.dmdirc.events.AppErrorEvent;
26
+import com.dmdirc.events.UserErrorEvent;
27
+import com.dmdirc.logger.ErrorLevel;
28
+
29
+import java.lang.reflect.Constructor;
30
+
31
+import org.slf4j.Marker;
32
+import org.slf4j.MarkerFactory;
33
+
34
+import ch.qos.logback.classic.Level;
35
+import ch.qos.logback.classic.spi.ILoggingEvent;
36
+import ch.qos.logback.classic.spi.IThrowableProxy;
37
+import ch.qos.logback.classic.spi.StackTraceElementProxy;
38
+import ch.qos.logback.core.AppenderBase;
39
+
40
+/**
41
+ *
42
+ */
43
+public class ProgramErrorAppender extends AppenderBase<ILoggingEvent> {
44
+
45
+    private DMDircMBassador eventBus;
46
+    private Marker appError;
47
+    private Marker userError;
48
+
49
+    @Override
50
+    public void start() {
51
+        appError = MarkerFactory.getMarker("AppError");
52
+        userError = MarkerFactory.getMarker("UserError");
53
+        if (eventBus == null) {
54
+            addError("No eventBus set for the appender named ["+ name +"].");
55
+            return;
56
+        }
57
+        super.start();
58
+    }
59
+
60
+    @Override
61
+    protected void append(final ILoggingEvent eventObject) {
62
+        if (eventObject.getMarker() == null) {
63
+            return;
64
+        }
65
+        if (eventObject.getMarker() == appError) {
66
+            eventBus.publish(new AppErrorEvent(level(eventObject), throwable
67
+                    (eventObject), eventObject.getFormattedMessage(), ""));
68
+        }
69
+        if (eventObject.getMarker() == userError) {
70
+            eventBus.publish(new UserErrorEvent(level(eventObject), throwable
71
+                    (eventObject), eventObject.getFormattedMessage(), ""));
72
+        }
73
+    }
74
+
75
+    public void setEventBus(final DMDircMBassador eventBus) {
76
+        this.eventBus = eventBus;
77
+    }
78
+
79
+    private ErrorLevel level(final ILoggingEvent eventObject) {
80
+        final Level level = eventObject.getLevel();
81
+        if (level.equals(Level.ERROR)) {
82
+            return ErrorLevel.HIGH;
83
+        } else if (level.equals(Level.WARN)) {
84
+            return ErrorLevel.MEDIUM;
85
+        } else if (level.equals(Level.INFO)) {
86
+            return ErrorLevel.LOW;
87
+        } else {
88
+            return ErrorLevel.UNKNOWN;
89
+        }
90
+    }
91
+
92
+    private Throwable throwable(final ILoggingEvent eventObject) {
93
+        try {
94
+            return convert(eventObject.getThrowableProxy());
95
+        } catch (ReflectiveOperationException ex) {
96
+            return new IllegalStateException("Error converting exception");
97
+        }
98
+    }
99
+
100
+    @SuppressWarnings("unchecked")
101
+    private Throwable convert(final IThrowableProxy proxy)
102
+            throws ReflectiveOperationException {
103
+        final Class<Throwable> clazz = (Class<Throwable>) Class.forName(proxy.getClassName());
104
+        final Throwable throwable;
105
+        if (proxy.getCause() == null) {
106
+            final Constructor<Throwable> ctor = clazz.getDeclaredConstructor(String.class);
107
+            throwable = ctor.newInstance(proxy.getMessage());
108
+        } else {
109
+            final Constructor<Throwable> ctor = clazz.getDeclaredConstructor(String.class,
110
+                    Throwable.class);
111
+            throwable = ctor.newInstance(proxy.getMessage(), convert(proxy.getCause()));
112
+        }
113
+        throwable.setStackTrace(convert(proxy.getStackTraceElementProxyArray()));
114
+        return throwable;
115
+    }
116
+
117
+    private StackTraceElement[] convert(final StackTraceElementProxy... elements) {
118
+        final StackTraceElement[] returnValue = new StackTraceElement[elements.length];
119
+        for (int i = 0; i < elements.length; i++) {
120
+            returnValue[i] = elements[i].getStackTraceElement();
121
+        }
122
+        return returnValue;
123
+    }
124
+}

Loading…
Cancel
Save