Logging configuration via SCL and UI & saving to ZIP-archive 19/1519/1
authorjsimomaa <jani.simomaa@gmail.com>
Fri, 2 Mar 2018 10:28:34 +0000 (12:28 +0200)
committerjsimomaa <jani.simomaa@gmail.com>
Fri, 2 Mar 2018 10:28:34 +0000 (12:28 +0200)
refs #7795

Change-Id: Ib8867aff85634d6a1ed6d2fe65da4e43818b83fc

41 files changed:
bundles/org.simantics.logging.ui/.classpath [new file with mode: 0644]
bundles/org.simantics.logging.ui/.project [new file with mode: 0644]
bundles/org.simantics.logging.ui/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.logging.ui/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.logging.ui/build.properties [new file with mode: 0644]
bundles/org.simantics.logging.ui/fragment.e4xmi [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/bug.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/error.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/information.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/page.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/page_white_compressed.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/page_white_edit.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/text_align_left.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/icons/warning.png [new file with mode: 0644]
bundles/org.simantics.logging.ui/plugin.xml [new file with mode: 0644]
bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/Activator.java [new file with mode: 0644]
bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/handlers/SaveLogFilesHandler.java [new file with mode: 0644]
bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/handlers/SelectLoggingLevelHandler.java [new file with mode: 0644]
bundles/org.simantics.logging/.classpath [new file with mode: 0644]
bundles/org.simantics.logging/.project [new file with mode: 0644]
bundles/org.simantics.logging/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.logging/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.logging/build.properties [new file with mode: 0644]
bundles/org.simantics.logging/dbAndMetadataLogProvider.xml [new file with mode: 0644]
bundles/org.simantics.logging/logbackLogProvider.xml [new file with mode: 0644]
bundles/org.simantics.logging/scl/LoggingUtils.scl [new file with mode: 0644]
bundles/org.simantics.logging/src/org/simantics/logging/DBAndMetadataLogProvider.java [new file with mode: 0644]
bundles/org.simantics.logging/src/org/simantics/logging/LogCollector.java [new file with mode: 0644]
bundles/org.simantics.logging/src/org/simantics/logging/LogConfigurator.java [new file with mode: 0644]
bundles/org.simantics.logging/src/org/simantics/logging/LogProvider.java [new file with mode: 0644]
bundles/org.simantics.logging/src/org/simantics/logging/LogbackLogProvider.java [new file with mode: 0644]
bundles/org.simantics.logging/src/org/simantics/logging/internal/Activator.java [new file with mode: 0644]
bundles/pom.xml
features/org.simantics.logging.feature/.project [new file with mode: 0644]
features/org.simantics.logging.feature/build.properties [new file with mode: 0644]
features/org.simantics.logging.feature/feature.xml [new file with mode: 0644]
features/org.simantics.logging.ui.feature/.project [new file with mode: 0644]
features/org.simantics.logging.ui.feature/build.properties [new file with mode: 0644]
features/org.simantics.logging.ui.feature/feature.xml [new file with mode: 0644]
features/org.simantics.sdk.feature/feature.xml
features/pom.xml

diff --git a/bundles/org.simantics.logging.ui/.classpath b/bundles/org.simantics.logging.ui/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.simantics.logging.ui/.project b/bundles/org.simantics.logging.ui/.project
new file mode 100644 (file)
index 0000000..e5853c5
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.logging.ui</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/bundles/org.simantics.logging.ui/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.logging.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..0c68a61
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/bundles/org.simantics.logging.ui/META-INF/MANIFEST.MF b/bundles/org.simantics.logging.ui/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..3f910c8
--- /dev/null
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ui
+Bundle-SymbolicName: org.simantics.logging.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.logging.ui.Activator
+Require-Bundle: javax.inject,
+ org.eclipse.osgi,
+ org.eclipse.jface,
+ org.eclipse.e4.ui.services,
+ org.eclipse.e4.core.di.annotations,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.ide,
+ org.slf4j.api,
+ org.simantics.logging,
+ org.simantics.utils,
+ org.simantics.utils.ui
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: javax.annotation;version="1.2.0"
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.simantics.logging.ui/build.properties b/bundles/org.simantics.logging.ui/build.properties
new file mode 100644 (file)
index 0000000..7af290f
--- /dev/null
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .,\
+               icons/,\
+               fragment.e4xmi
diff --git a/bundles/org.simantics.logging.ui/fragment.e4xmi b/bundles/org.simantics.logging.ui/fragment.e4xmi
new file mode 100644 (file)
index 0000000..cc14bb5
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:commands="http://www.eclipse.org/ui/2010/UIModel/application/commands" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_BxaXACerEeWxCPrV0pAZQQ">
+  <fragments xsi:type="fragment:StringModelFragment" xmi:id="_QqSikIrOEeW7h_qdP9N9fw" featurename="commands" parentElementId="xpath:/">
+    <elements xsi:type="commands:Command" xmi:id="_UCYfwIrOEeW7h_qdP9N9fw" elementId="org.simantics.logging.ui.command.saveLogFiles" commandName="Save Logs" description="Save all important application log files to a ZIP-archive"/>
+    <elements xsi:type="commands:Command" xmi:id="_34UCQB3xEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.command.selectLogLevel" commandName="Select Logging Level" description="Select current logging level">
+      <parameters xmi:id="_YFD2kB3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.commandparameter.selectLoggingLevel" name="Logging Level" optional="false"/>
+    </elements>
+  </fragments>
+  <fragments xsi:type="fragment:StringModelFragment" xmi:id="_fW12kIrOEeW7h_qdP9N9fw" featurename="handlers" parentElementId="xpath:/">
+    <elements xsi:type="commands:Handler" xmi:id="_k2L0IIrOEeW7h_qdP9N9fw" elementId="org.simantics.logging.ui.handlers.saveLogFiles" contributionURI="bundleclass://org.simantics.logging.ui/org.simantics.logging.ui.handlers.SaveLogFilesHandler" command="_UCYfwIrOEeW7h_qdP9N9fw"/>
+    <elements xsi:type="commands:Handler" xmi:id="_60CMgB3xEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.handlers.selectLogLevel" contributionURI="bundleclass://org.simantics.logging.ui/org.simantics.logging.ui.handlers.SelectLoggingLevelHandler" command="_34UCQB3xEeiTyNdCNKIG-w"/>
+  </fragments>
+  <fragments xsi:type="fragment:StringModelFragment" xmi:id="_pVgfIIrOEeW7h_qdP9N9fw" featurename="menuContributions" parentElementId="xpath:/">
+    <elements xsi:type="menu:MenuContribution" xmi:id="_tSwX0IrOEeW7h_qdP9N9fw" elementId="org.simantics.logging.ui.menucontribution.saveLogFiles" positionInParent="after=group.main.ext" parentId="help">
+      <children xsi:type="menu:HandledMenuItem" xmi:id="_2LM_MIrOEeW7h_qdP9N9fw" elementId="org.simantics.logging.ui.saveLogFiles.handledmenuitem" label="Save Logs" iconURI="platform:/plugin/org.simantics.logging.ui/icons/page_white_compressed.png" tooltip="Save all important application log files to a ZIP-archive" command="_UCYfwIrOEeW7h_qdP9N9fw"/>
+    </elements>
+    <elements xsi:type="menu:MenuContribution" xmi:id="_fGQd4B3xEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.menucontribution.selectLoggingLevelMenu" positionInParent="after=group.main.ext" parentId="help">
+      <children xsi:type="menu:Menu" xmi:id="_jtqG0B3xEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.menucontribution.selectLoggingLevelSubMenu" label="Logging Level.." iconURI="platform:/plugin/org.simantics.logging.ui/icons/page_white_edit.png">
+        <children xsi:type="menu:HandledMenuItem" xmi:id="_PVgsgB3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.handledmenuitem.selectLoggingLevel.trace" label="TRACE" iconURI="platform:/plugin/org.simantics.logging.ui/icons/text_align_left.png" type="Radio" command="_34UCQB3xEeiTyNdCNKIG-w">
+          <parameters xmi:id="_XQtogB3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.parameter.loggingLevel.trace" name="org.simantics.logging.ui.commandparameter.selectLoggingLevel" value="TRACE"/>
+        </children>
+        <children xsi:type="menu:HandledMenuItem" xmi:id="_5bsEEB3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.handledmenuitem.selectLoggingLevel.debug" label="DEBUG" iconURI="platform:/plugin/org.simantics.logging.ui/icons/bug.png" type="Radio" command="_34UCQB3xEeiTyNdCNKIG-w">
+          <parameters xmi:id="_5bsEER3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.parameter.loggingLevel.debug" name="org.simantics.logging.ui.commandparameter.selectLoggingLevel" value="DEBUG"/>
+        </children>
+        <children xsi:type="menu:HandledMenuItem" xmi:id="_5fIZoB3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.handledmenuitem.selectLoggingLevel.info" label="INFO" iconURI="platform:/plugin/org.simantics.logging.ui/icons/information.png" selected="true" type="Radio" command="_34UCQB3xEeiTyNdCNKIG-w">
+          <parameters xmi:id="_5fIZoR3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.parameter.loggingLevel.info" name="org.simantics.logging.ui.commandparameter.selectLoggingLevel" value="INFO"/>
+        </children>
+        <children xsi:type="menu:HandledMenuItem" xmi:id="_5ihE0B3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.handledmenuitem.selectLoggingLevel.warn" label="WARN" iconURI="platform:/plugin/org.simantics.logging.ui/icons/warning.png" type="Radio" command="_34UCQB3xEeiTyNdCNKIG-w">
+          <parameters xmi:id="_5ihE0R3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.parameter.loggingLevel.warn" name="org.simantics.logging.ui.commandparameter.selectLoggingLevel" value="WARN"/>
+        </children>
+        <children xsi:type="menu:HandledMenuItem" xmi:id="_55I1EB3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.handledmenuitem.selectLoggingLevel.error" label="ERROR" iconURI="platform:/plugin/org.simantics.logging.ui/icons/error.png" type="Radio" command="_34UCQB3xEeiTyNdCNKIG-w">
+          <parameters xmi:id="_55I1ER3yEeiTyNdCNKIG-w" elementId="org.simantics.logging.ui.parameter.loggingLevel.error" name="org.simantics.logging.ui.commandparameter.selectLoggingLevel" value="ERROR"/>
+        </children>
+      </children>
+    </elements>
+  </fragments>
+</fragment:ModelFragments>
diff --git a/bundles/org.simantics.logging.ui/icons/bug.png b/bundles/org.simantics.logging.ui/icons/bug.png
new file mode 100644 (file)
index 0000000..2d5fb90
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/bug.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/error.png b/bundles/org.simantics.logging.ui/icons/error.png
new file mode 100644 (file)
index 0000000..c37bd06
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/error.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/information.png b/bundles/org.simantics.logging.ui/icons/information.png
new file mode 100644 (file)
index 0000000..12cd1ae
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/information.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/page.png b/bundles/org.simantics.logging.ui/icons/page.png
new file mode 100644 (file)
index 0000000..03ddd79
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/page.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/page_white_compressed.png b/bundles/org.simantics.logging.ui/icons/page_white_compressed.png
new file mode 100644 (file)
index 0000000..2b6b100
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/page_white_compressed.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/page_white_edit.png b/bundles/org.simantics.logging.ui/icons/page_white_edit.png
new file mode 100644 (file)
index 0000000..b93e776
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/page_white_edit.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/text_align_left.png b/bundles/org.simantics.logging.ui/icons/text_align_left.png
new file mode 100644 (file)
index 0000000..6c8fcc1
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/text_align_left.png differ
diff --git a/bundles/org.simantics.logging.ui/icons/warning.png b/bundles/org.simantics.logging.ui/icons/warning.png
new file mode 100644 (file)
index 0000000..628cf2d
Binary files /dev/null and b/bundles/org.simantics.logging.ui/icons/warning.png differ
diff --git a/bundles/org.simantics.logging.ui/plugin.xml b/bundles/org.simantics.logging.ui/plugin.xml
new file mode 100644 (file)
index 0000000..f57c889
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+   <extension
+         id="org.simantics.logging.ui.fragment"
+         point="org.eclipse.e4.workbench.model">
+      <fragment
+            apply="initial"
+            uri="fragment.e4xmi">
+      </fragment>
+   </extension>
+
+</plugin>
diff --git a/bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/Activator.java b/bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/Activator.java
new file mode 100644 (file)
index 0000000..942a88b
--- /dev/null
@@ -0,0 +1,30 @@
+package org.simantics.logging.ui;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+       private static BundleContext context;
+
+       static BundleContext getContext() {
+               return context;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext bundleContext) throws Exception {
+               Activator.context = bundleContext;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext bundleContext) throws Exception {
+               Activator.context = null;
+       }
+
+}
diff --git a/bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/handlers/SaveLogFilesHandler.java b/bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/handlers/SaveLogFilesHandler.java
new file mode 100644 (file)
index 0000000..7d7983f
--- /dev/null
@@ -0,0 +1,93 @@
+package org.simantics.logging.ui.handlers;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.inject.Named;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.logging.LogCollector;
+import org.simantics.utils.FileUtils;
+import org.simantics.utils.ui.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SaveLogFilesHandler {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SaveLogFilesHandler.class);
+
+    private static final String[] FILTER_NAMES = { "ZIP-archive", "AllFiles (*:*)" };
+    private static final String[] FILTER_EXTENSIONS = { "*.zip", "*.*" };
+    private static final String USER_HOME = System.getProperty("user.home");
+    
+    @Execute
+    public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
+        
+        FileDialog dialog = new FileDialog(shell, SWT.SAVE);
+        dialog.setFilterNames(FILTER_NAMES);
+        dialog.setFilterExtensions(FILTER_EXTENSIONS);
+        if (USER_HOME != null) {
+            if (Files.exists(Paths.get(USER_HOME))) {
+                dialog.setFilterPath(USER_HOME);
+            }
+        }
+        StringBuilder fileName = new StringBuilder();
+        String productName = Platform.getProduct().getName();
+        if (productName != null)
+            fileName.append(productName.replaceAll(" ", "_")).append("-");
+        
+        fileName.append("logs-").append(currentLocalDateTimeStamp());
+        String actualFileName = fileName.toString();
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Resolved log files name {}", actualFileName);
+        dialog.setFileName(actualFileName);
+        
+        String destination = dialog.open();
+        if (destination != null) {
+            if (LOGGER.isDebugEnabled())
+                LOGGER.debug("Destination for saving log files is {}", destination);
+            
+            try {
+                Path tempDir = Files.createTempDirectory(actualFileName);
+                Map<String, List<Path>> allLogs = LogCollector.allLogs();
+                for (Entry<String, List<Path>> logEntry : allLogs.entrySet()) {
+                    Path subFolder = tempDir.resolve(logEntry.getKey());
+                    Files.createDirectory(subFolder);
+                    for (Path p : logEntry.getValue()) {
+                        try {
+                            Files.copy(p, subFolder.resolve(p.getFileName()));
+                        } catch (IOException e) {
+                            LOGGER.error("Could not copy {}", p.toAbsolutePath(), e);
+                        }
+                    }
+                }
+                FileUtils.compressZip(tempDir.toAbsolutePath().toString(), destination);
+                FileUtils.delete(tempDir);
+            } catch (Throwable t) {
+                LOGGER.error("Could not save log files to ZIP", t);
+                ExceptionUtils.logAndShowError("Could not save log files to ZIP", t);
+            }
+        } else {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("No destination selected for saving logs");
+            }
+        }
+    }
+    
+    private static String currentLocalDateTimeStamp() {
+        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HHmm"));
+    }
+
+}
diff --git a/bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/handlers/SelectLoggingLevelHandler.java b/bundles/org.simantics.logging.ui/src/org/simantics/logging/ui/handlers/SelectLoggingLevelHandler.java
new file mode 100644 (file)
index 0000000..27473f1
--- /dev/null
@@ -0,0 +1,21 @@
+package org.simantics.logging.ui.handlers;
+
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.simantics.logging.LogConfigurator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SelectLoggingLevelHandler {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SelectLoggingLevelHandler.class);
+
+    @Execute
+    public void execute(@Named("org.simantics.logging.ui.commandparameter.selectLoggingLevel") String level) {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Setting logging level to {}", level);
+        LogConfigurator.setLoggingLevel(level);
+    }
+
+}
diff --git a/bundles/org.simantics.logging/.classpath b/bundles/org.simantics.logging/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.simantics.logging/.project b/bundles/org.simantics.logging/.project
new file mode 100644 (file)
index 0000000..9f60062
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.logging</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ds.core.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/bundles/org.simantics.logging/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.logging/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..0c68a61
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/bundles/org.simantics.logging/META-INF/MANIFEST.MF b/bundles/org.simantics.logging/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..115019a
--- /dev/null
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics Logging Core
+Bundle-SymbolicName: org.simantics.logging
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.logging.internal.Activator
+Bundle-Vendor: Semantum Oy
+Require-Bundle: org.eclipse.core.runtime,
+ org.slf4j.api,
+ ch.qos.logback.classic,
+ ch.qos.logback.core
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Service-Component: logbackLogProvider.xml,
+ dbAndMetadataLogProvider.xml
+Export-Package: org.simantics.logging
diff --git a/bundles/org.simantics.logging/build.properties b/bundles/org.simantics.logging/build.properties
new file mode 100644 (file)
index 0000000..c5cc5f8
--- /dev/null
@@ -0,0 +1,7 @@
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               scl/,\
+               logbackLogProvider.xml,\
+               dbAndMetadataLogProvider.xml
+source.. = src/
diff --git a/bundles/org.simantics.logging/dbAndMetadataLogProvider.xml b/bundles/org.simantics.logging/dbAndMetadataLogProvider.xml
new file mode 100644 (file)
index 0000000..aa4678f
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.simantics.logging.dbAndMetadataLogProvider">
+   <implementation class="org.simantics.logging.DBAndMetadataLogProvider"/>
+   <service>
+      <provide interface="org.simantics.logging.LogProvider"/>
+   </service>
+</scr:component>
diff --git a/bundles/org.simantics.logging/logbackLogProvider.xml b/bundles/org.simantics.logging/logbackLogProvider.xml
new file mode 100644 (file)
index 0000000..9e9e6db
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.simantics.logging">
+   <implementation class="org.simantics.logging.LogbackLogProvider"/>
+   <service>
+      <provide interface="org.simantics.logging.LogProvider"/>
+   </service>
+</scr:component>
diff --git a/bundles/org.simantics.logging/scl/LoggingUtils.scl b/bundles/org.simantics.logging/scl/LoggingUtils.scl
new file mode 100644 (file)
index 0000000..500ba1b
--- /dev/null
@@ -0,0 +1,9 @@
+import "Files"
+import "Map" as Map
+
+importJava "org.simantics.logging.LogConfigurator" where
+    setLoggingLevel :: String -> <Proc> ()
+    setLoggingLevelForLogger :: String -> String -> <Proc> ()
+
+importJava "org.simantics.logging.LogCollector" where
+    allLogs :: <Proc> Map.T String [Path]
\ No newline at end of file
diff --git a/bundles/org.simantics.logging/src/org/simantics/logging/DBAndMetadataLogProvider.java b/bundles/org.simantics.logging/src/org/simantics/logging/DBAndMetadataLogProvider.java
new file mode 100644 (file)
index 0000000..79e10db
--- /dev/null
@@ -0,0 +1,60 @@
+package org.simantics.logging;
+
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+import org.slf4j.LoggerFactory;
+
+public class DBAndMetadataLogProvider implements LogProvider {
+
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DBAndMetadataLogProvider.class);
+    
+    @Override
+    public List<Path> get() {
+        List<Path> logs = new ArrayList<>();
+        Path dbClientLog = getDBClientLogLocation();
+        if (dbClientLog != null)
+            logs.add(dbClientLog);
+        Path metadataLogLocation = getMetadataLogLocation();
+        if (metadataLogLocation != null)
+            logs.add(metadataLogLocation);
+        return logs;
+    }
+
+    private static Path getDBClientLogLocation() {
+        Bundle bundle = Platform.getBundle("org.simantics.db.common");
+        try {
+            Class<?> forName = bundle.loadClass("org.simantics.db.common.internal.config.InternalClientConfig");
+            Field field = forName.getField("DB_CLIENT_LOG_FILE");
+            String value = (String) field.get(null);
+            return Paths.get(value);
+        } catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            LOGGER.error("Could not read db-client.log location", e);
+        }
+        return null;
+    }
+
+    private static Path getMetadataLogLocation() {
+        String prop = System.getProperty("osgi.instance.area", null);
+        if (prop != null) {
+            try {
+                URL url = new URL(prop);
+                if ("file".equals(url .getProtocol())) {
+                    Path path = Paths.get(url.toURI());
+                    return path.resolve(".metadata").resolve(".log");
+                } else {
+                    LOGGER.warn("Unsupported protocol {}", url);
+                }
+            } catch (Throwable t) {
+                LOGGER.error("Could not get .metadata/.log", t);
+            }
+        }
+        return null;
+    }
+}
diff --git a/bundles/org.simantics.logging/src/org/simantics/logging/LogCollector.java b/bundles/org.simantics.logging/src/org/simantics/logging/LogCollector.java
new file mode 100644 (file)
index 0000000..4d98e27
--- /dev/null
@@ -0,0 +1,65 @@
+package org.simantics.logging;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.simantics.logging.internal.Activator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class LogCollector {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(LogCollector.class);
+
+    public static Map<String, List<Path>> allLogs() {
+        Map<String, List<Path>> results = new HashMap<>();
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Collecting all logs from declarative services");
+
+        Collection<LogProvider> logProviders = getLogProviders();
+        for (LogProvider logProvider : logProviders) {
+            List<Path> logs = logProvider.get();
+            String key = logProvider.getClass().getSimpleName();
+            Collection<Path> existing = results.get(key);
+            if (existing != null) {
+                LOGGER.info("Duplicate log providers with name {} exist, merging logs", key);
+                logs.addAll(existing);
+            }
+            results.put(key, logs);
+        }
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Found logs from {} providers", results.keySet());
+        return results;
+    }
+
+    private static List<LogProvider> getLogProviders() {
+        ServiceReference<?>[] serviceReferences = new ServiceReference<?>[0];
+        String key = LogProvider.class.getName();
+        try {
+            serviceReferences = Activator.getContext().getAllServiceReferences(key, null);
+        } catch (InvalidSyntaxException e) {
+            LOGGER.error("Could not get service references for {}!", key, e);
+        }
+        if (serviceReferences.length == 0) {
+            if (LOGGER.isDebugEnabled())
+                LOGGER.debug("No service references found for {}", key);
+            return Collections.emptyList();
+        }
+
+        List<LogProvider> logProviders = new ArrayList<>(serviceReferences.length);
+        for (ServiceReference<?> reference : serviceReferences) {
+            LogProvider logProvider = (LogProvider) Activator.getContext().getService(reference);
+            logProviders.add(logProvider);
+        }
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Found {} log providers", logProviders);
+        return logProviders;
+    }
+}
diff --git a/bundles/org.simantics.logging/src/org/simantics/logging/LogConfigurator.java b/bundles/org.simantics.logging/src/org/simantics/logging/LogConfigurator.java
new file mode 100644 (file)
index 0000000..047bac8
--- /dev/null
@@ -0,0 +1,54 @@
+package org.simantics.logging;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+
+/**
+ * Class for modifying the active logging configuration
+ * 
+ * @author Jani Simomaa
+ *
+ */
+public final class LogConfigurator {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(LogConfigurator.class);
+
+    private LogConfigurator() {
+    }
+
+    /**
+     * Sets logging level to represent the given argument
+     * 
+     * @param level ERROR WARN INFO DEBUG TRACE
+     */
+    public static void setLoggingLevel(String level) {
+        if (LOGGER.isInfoEnabled())
+            LOGGER.info("Setting logger level to {}", level);
+        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+        Level ll = getLoggerLevel(level);
+        List<ch.qos.logback.classic.Logger> loggerList = context.getLoggerList();
+        loggerList.forEach(l -> l.setLevel(ll));
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Loggers installed {}", loggerList);
+    }
+
+    public static void setLoggingLevelForLogger(String logger, String level) {
+        if (LOGGER.isInfoEnabled())
+            LOGGER.info("Setting logger level to {} for loggers {}", level, logger);
+        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+        Level ll = getLoggerLevel(level);
+        ch.qos.logback.classic.Logger loggerList = context.getLogger(logger);
+        loggerList.setLevel(ll);
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Loggers installed {}", loggerList);
+    }
+
+    private static Level getLoggerLevel(String level) {
+        return Level.valueOf(level);
+    }
+}
diff --git a/bundles/org.simantics.logging/src/org/simantics/logging/LogProvider.java b/bundles/org.simantics.logging/src/org/simantics/logging/LogProvider.java
new file mode 100644 (file)
index 0000000..7f7a827
--- /dev/null
@@ -0,0 +1,9 @@
+package org.simantics.logging;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Supplier;
+
+public interface LogProvider extends Supplier<List<Path>> {
+
+}
diff --git a/bundles/org.simantics.logging/src/org/simantics/logging/LogbackLogProvider.java b/bundles/org.simantics.logging/src/org/simantics/logging/LogbackLogProvider.java
new file mode 100644 (file)
index 0000000..3c88cd5
--- /dev/null
@@ -0,0 +1,83 @@
+package org.simantics.logging;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.FileAppender;
+import ch.qos.logback.core.rolling.RollingFileAppender;
+import ch.qos.logback.core.spi.AppenderAttachable;
+
+public class LogbackLogProvider implements LogProvider {
+
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(LogbackLogProvider.class);
+    
+    @Override
+    public List<Path> get() {
+        List<Path> logs = new ArrayList<>();
+        try {
+            LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+            Logger logger = context.getLogger(Logger.ROOT_LOGGER_NAME);
+            Iterator<Appender<ILoggingEvent>> appenderIter = logger.iteratorForAppenders();
+            while (appenderIter.hasNext()) {
+                FileAppender<ILoggingEvent> appender = findFileAppender(appenderIter.next());
+                if (appender != null) {
+                    String logFile = ((FileAppender<ILoggingEvent>)appender).getFile();
+                    Path log = Paths.get(logFile).toAbsolutePath();
+                    if (appender instanceof RollingFileAppender) {
+                        // Collect all logs
+                        Path parent = log.getParent();
+                        List<Path> newLogs = Files.walk(parent).collect(Collectors.toList());
+                        if (LOGGER.isDebugEnabled())
+                            LOGGER.debug("Found {} from {}", newLogs, appender);
+                        logs.addAll(newLogs);
+                    } else {
+                        logs.add(log);
+                    }
+                } else {
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("Appender is not {} but is {} instead", FileAppender.class.getName(), appender != null ? appender.getClass().getName() : "null");
+                    }
+                }
+            }
+        } catch (ClassCastException e) {
+            // Okay, we are not using logback here
+            if (LOGGER.isDebugEnabled())
+                LOGGER.debug("Seems like we are not using logback but {} instead", LoggerFactory.getILoggerFactory(), e);
+        } catch (Throwable t) {
+            LOGGER.error("Could not collect logs", t);
+        }
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Found {} log files : {}", logs.size(), logs);
+        return logs;
+    }
+    
+    private static FileAppender<ILoggingEvent> findFileAppender(Appender<ILoggingEvent> appender) {
+        if (appender instanceof AppenderAttachable) {
+            // Ok, has child appender
+            Iterator<Appender<ILoggingEvent>> children = ((AppenderAttachable<ILoggingEvent>) appender).iteratorForAppenders();
+            while (children.hasNext()) {
+                FileAppender<ILoggingEvent> app = findFileAppender(children.next());
+                // TODO: returns only first FileAppender that it founds but not a collection
+                if (app != null)
+                    return app;
+            }
+            return null;
+        } else if (appender instanceof FileAppender) {
+            return (FileAppender<ILoggingEvent>) appender;
+        } else {
+            return null;
+        }
+    }
+
+}
diff --git a/bundles/org.simantics.logging/src/org/simantics/logging/internal/Activator.java b/bundles/org.simantics.logging/src/org/simantics/logging/internal/Activator.java
new file mode 100644 (file)
index 0000000..abedac6
--- /dev/null
@@ -0,0 +1,30 @@
+package org.simantics.logging.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+       private static BundleContext context;
+
+       public static BundleContext getContext() {
+               return context;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext bundleContext) throws Exception {
+               Activator.context = bundleContext;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext bundleContext) throws Exception {
+               Activator.context = null;
+       }
+
+}
index 7ac841ad17399d1596fe3d8cb6997bc52a9e2809..6bcbd66578d6127d39be65a0e2be7f6addbbaccc 100644 (file)
                <module>org.simantics.layer0.utils</module>
                <module>org.simantics.layer0x.ontology</module>
                <module>org.simantics.logback.configuration</module>
+        <module>org.simantics.logging</module>
+        <module>org.simantics.logging.ui</module>
                <module>org.simantics.ltk</module>
                <module>org.simantics.ltk.antlr</module>
                <module>org.simantics.lz4</module>
diff --git a/features/org.simantics.logging.feature/.project b/features/org.simantics.logging.feature/.project
new file mode 100644 (file)
index 0000000..3ba0077
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.logging.feature</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.pde.FeatureBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.FeatureNature</nature>
+       </natures>
+</projectDescription>
diff --git a/features/org.simantics.logging.feature/build.properties b/features/org.simantics.logging.feature/build.properties
new file mode 100644 (file)
index 0000000..64f93a9
--- /dev/null
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/features/org.simantics.logging.feature/feature.xml b/features/org.simantics.logging.feature/feature.xml
new file mode 100644 (file)
index 0000000..3f4e573
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.simantics.logging.feature"
+      label="Simantics Logging Feature"
+      version="1.0.0.qualifier"
+      provider-name="Semantum Oy">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <plugin
+         id="org.simantics.logging"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.simantics.logging.ui.feature/.project b/features/org.simantics.logging.ui.feature/.project
new file mode 100644 (file)
index 0000000..e464046
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.logging.ui.feature</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.pde.FeatureBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.FeatureNature</nature>
+       </natures>
+</projectDescription>
diff --git a/features/org.simantics.logging.ui.feature/build.properties b/features/org.simantics.logging.ui.feature/build.properties
new file mode 100644 (file)
index 0000000..64f93a9
--- /dev/null
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/features/org.simantics.logging.ui.feature/feature.xml b/features/org.simantics.logging.ui.feature/feature.xml
new file mode 100644 (file)
index 0000000..6f94a0e
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.simantics.logging.ui.feature"
+      label="Simantics Logging UI Feature"
+      version="1.0.0.qualifier"
+      provider-name="Semantum Oy">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <includes
+         id="org.simantics.logging.feature"
+         version="0.0.0"/>
+
+   <plugin
+         id="org.simantics.logging.ui"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
index 0fc787e69f7428a35820077230a9f16d08f3c424..b7dc9adeea7d6960aae8e4137c0076ab1de5d997 100644 (file)
          id="hdf.hdf5"
          version="0.0.0"/>
 
+   <includes
+         id="org.simantics.logging.feature"
+         version="0.0.0"/>
+
+   <includes
+         id="org.simantics.logging.ui.feature"
+         version="0.0.0"/>
+
    <plugin
          id="org.simantics.fileimport"
          download-size="0"
index 110983d19165ca6cb380a67daf28741d40758cb6..0f4197b1a9a5dd432641361129feca4b2c19362f 100644 (file)
         <module>org.simantics.issues.feature</module>
         <module>org.simantics.issues.ui.feature</module>
         <module>org.simantics.layer0.feature</module>
+        <module>org.simantics.logging.feature</module>
+        <module>org.simantics.logging.ui.feature</module>
         <module>org.simantics.message.feature</module>
         <module>org.simantics.migration.feature</module>
         <module>org.simantics.modeling.feature</module>