mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Adding log level control
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>1.4.0d</version>
|
||||
<version>1.4.0e</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.apache.http.conn.util.InetAddressUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.util.BackupHandler;
|
||||
import com.bwssystems.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class BridgeSettings extends BackupHandler {
|
||||
|
||||
@@ -20,6 +20,7 @@ public class BridgeSettingsDescriptor {
|
||||
private boolean harmonyconfigured;
|
||||
private boolean nestconfigured;
|
||||
private String configfile;
|
||||
private Integer numberoflogmessages;
|
||||
|
||||
public BridgeSettingsDescriptor() {
|
||||
super();
|
||||
@@ -137,6 +138,12 @@ public class BridgeSettingsDescriptor {
|
||||
public void setConfigfile(String configfile) {
|
||||
this.configfile = configfile;
|
||||
}
|
||||
public Integer getNumberoflogmessages() {
|
||||
return numberoflogmessages;
|
||||
}
|
||||
public void setNumberoflogmessages(Integer numberoflogmessages) {
|
||||
this.numberoflogmessages = numberoflogmessages;
|
||||
}
|
||||
public Boolean isValidVera() {
|
||||
if(this.getVeraAddress() == null)
|
||||
return false;
|
||||
|
||||
@@ -17,6 +17,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.logservices.LoggingManager;
|
||||
import com.bwssystems.util.JsonFreeTextStringFormatter;
|
||||
import com.bwssystems.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
@@ -33,6 +36,7 @@ public class SystemControl {
|
||||
private Version version;
|
||||
private CyclicBufferAppender<ILoggingEvent> cyclicBufferAppender;
|
||||
private DateFormat dateFormat;
|
||||
private LoggingManager theLogServiceMgr;
|
||||
|
||||
|
||||
public SystemControl(BridgeSettings theBridgeSettings, Version theVersion) {
|
||||
@@ -41,6 +45,9 @@ public class SystemControl {
|
||||
this.lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
this.dateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss.SSS");
|
||||
reacquireCBA();
|
||||
theLogServiceMgr = new LoggingManager();
|
||||
theLogServiceMgr.setShowAll(true);
|
||||
theLogServiceMgr.init();
|
||||
}
|
||||
|
||||
// This function sets up the sparkjava rest calls for the hue api
|
||||
@@ -53,7 +60,7 @@ public class SystemControl {
|
||||
return "{\"version\":\"" + version.getVersion() + "\"}";
|
||||
});
|
||||
|
||||
// http://ip_address:port/system/logmsgs gets the version of this bridge instance
|
||||
// http://ip_address:port/system/logmsgs gets the log messages for the bridge
|
||||
get (SYSTEM_CONTEXT + "/logmsgs", "application/json", (request, response) -> {
|
||||
log.debug("Get logmsgs.");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
@@ -73,14 +80,23 @@ public class SystemControl {
|
||||
LoggingEvent le;
|
||||
for (int i = 0; i < count; i++) {
|
||||
le = (LoggingEvent) cyclicBufferAppender.get(i);
|
||||
logMsgs = logMsgs + ( i > 0?",{":"{") + "\"time\":\"" + dateFormat.format(le.getTimeStamp()) + "\",\"level\":\"" + le.getLevel().levelStr + "\",\"component\":\"" + le.getLoggerName() + "\",\"message\":\"" + le.getFormattedMessage() + "\"}";
|
||||
logMsgs = logMsgs + ( i > 0?",{":"{") + "\"time\":\"" + dateFormat.format(le.getTimeStamp()) + "\",\"level\":\"" + le.getLevel().levelStr + "\",\"component\":\"" + le.getLoggerName() + "\",\"message\":\"" + JsonFreeTextStringFormatter.forJSON(le.getFormattedMessage()) + "\"}";
|
||||
}
|
||||
}
|
||||
logMsgs = logMsgs + "]";
|
||||
response.status(200);
|
||||
return logMsgs;
|
||||
});
|
||||
|
||||
// http://ip_address:port/system/settings which returns the bridge configuration settings
|
||||
// http://ip_address:port/system/logmgmt/loggers gets the logger info for the bridge
|
||||
get (SYSTEM_CONTEXT + "/logmgmt/loggers", "application/json", (request, response) -> {
|
||||
log.debug("Get loggers info.");
|
||||
theLogServiceMgr.init();
|
||||
response.status(200);
|
||||
return theLogServiceMgr.getConfiguredLoggers();
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/system/settings which returns the bridge configuration settings
|
||||
get(SYSTEM_CONTEXT + "/settings", "application/json", (request, response) -> {
|
||||
log.debug("bridge settings requested from " + request.ip());
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ import java.util.Random;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BackupHandler;
|
||||
import com.bwssystems.HABridge.JsonTransformer;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.util.BackupHandler;
|
||||
import com.bwssystems.util.JsonTransformer;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
import com.bwssystems.HABridge.JsonTransformer;
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.DeviceRepository;
|
||||
@@ -25,6 +24,7 @@ import com.bwssystems.NestBridge.NestHome;
|
||||
import com.bwssystems.harmony.HarmonyHome;
|
||||
import com.bwssystems.luupRequests.Device;
|
||||
import com.bwssystems.luupRequests.Scene;
|
||||
import com.bwssystems.util.JsonTransformer;
|
||||
import com.bwssystems.vera.VeraHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
import com.bwssystems.HABridge.JsonTransformer;
|
||||
import com.bwssystems.HABridge.api.UserCreateRequest;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||
@@ -14,6 +13,7 @@ import com.bwssystems.harmony.HarmonyHandler;
|
||||
import com.bwssystems.harmony.HarmonyHome;
|
||||
import com.bwssystems.harmony.RunActivity;
|
||||
import com.bwssystems.nest.controller.Nest;
|
||||
import com.bwssystems.util.JsonTransformer;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
50
src/main/java/com/bwssystems/logservices/LogFileInfo.java
Normal file
50
src/main/java/com/bwssystems/logservices/LogFileInfo.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* http://www.jrecruiter.org
|
||||
*
|
||||
* Disclaimer of Warranty.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, Licensor provides
|
||||
* the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
* including, without limitation, any warranties or conditions of TITLE,
|
||||
* NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
* solely responsible for determining the appropriateness of using or
|
||||
* redistributing the Work and assume any risks associated with Your exercise of
|
||||
* permissions under this License.
|
||||
*
|
||||
*/
|
||||
package com.bwssystems.logservices;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Log file information.
|
||||
*
|
||||
*/
|
||||
public class LogFileInfo {
|
||||
|
||||
private String fileName;
|
||||
private Long fileSize;
|
||||
private Date fileLastChanged;
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
public Long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
public void setFileSize(Long fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
public Date getFileLastChanged() {
|
||||
return fileLastChanged;
|
||||
}
|
||||
public void setFileLastChanged(Date fileLastChanged) {
|
||||
this.fileLastChanged = fileLastChanged;
|
||||
}
|
||||
|
||||
}
|
||||
51
src/main/java/com/bwssystems/logservices/LoggerInfo.java
Normal file
51
src/main/java/com/bwssystems/logservices/LoggerInfo.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.bwssystems.logservices;
|
||||
|
||||
import com.bwssystems.logservices.LoggingUtil.LogLevels;
|
||||
|
||||
/**
|
||||
* Logger information.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class LoggerInfo {
|
||||
|
||||
private String loggerName;
|
||||
private LogLevels logLevel;
|
||||
private LogLevels newLogLevel;
|
||||
|
||||
//~~~~~Constructors~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LoggerInfo() {
|
||||
super();
|
||||
}
|
||||
public LoggerInfo(String loggerName, int logLevelAsInt) {
|
||||
super();
|
||||
this.loggerName = loggerName;
|
||||
this.logLevel = LogLevels.getLogLevelFromId(logLevelAsInt);
|
||||
}
|
||||
|
||||
//~~~~~Getters and Setters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public String getLoggerName() {
|
||||
return loggerName;
|
||||
}
|
||||
public void setLoggerName(String loggerName) {
|
||||
this.loggerName = loggerName;
|
||||
}
|
||||
public LogLevels getLogLevel() {
|
||||
return logLevel;
|
||||
}
|
||||
public void setLogLevel(LogLevels logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
public LogLevels getNewLogLevel() {
|
||||
return newLogLevel;
|
||||
}
|
||||
public void setNewLogLevel(LogLevels newLogLevel) {
|
||||
this.newLogLevel = newLogLevel;
|
||||
}
|
||||
|
||||
}
|
||||
58
src/main/java/com/bwssystems/logservices/LoggingForm.java
Normal file
58
src/main/java/com/bwssystems/logservices/LoggingForm.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.bwssystems.logservices;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Form for the Logging Action.
|
||||
*/
|
||||
public class LoggingForm implements Serializable {
|
||||
|
||||
/** serialVersionUID. */
|
||||
private static final long serialVersionUID = 5970927715241338665L;
|
||||
|
||||
/** List of Loggers, simplified for display purposes */
|
||||
private List<LoggerInfo> updatedLoggers = new ArrayList<LoggerInfo>();
|
||||
|
||||
/** The user can enter a new logger to be configured */
|
||||
private LoggerInfo newLogger;
|
||||
|
||||
/** Used for requesting a logfile download */
|
||||
private String fileName;
|
||||
|
||||
//~~~~~Constructors~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public LoggingForm() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
//~~~~~Getters and Setters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
public List<LoggerInfo> getUpdatedLoggers() {
|
||||
return updatedLoggers;
|
||||
}
|
||||
|
||||
public void setUpdatedLoggers(List<LoggerInfo> updatedLoggers) {
|
||||
this.updatedLoggers = updatedLoggers;
|
||||
}
|
||||
|
||||
public LoggerInfo getNewLogger() {
|
||||
return newLogger;
|
||||
}
|
||||
|
||||
public void setNewLogger(LoggerInfo newLogger) {
|
||||
this.newLogger = newLogger;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
}
|
||||
163
src/main/java/com/bwssystems/logservices/LoggingManager.java
Normal file
163
src/main/java/com/bwssystems/logservices/LoggingManager.java
Normal file
@@ -0,0 +1,163 @@
|
||||
package com.bwssystems.logservices;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.bwssystems.logservices.LoggingUtil;
|
||||
import com.bwssystems.logservices.LoggingUtil.LogLevels;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.Logger;
|
||||
|
||||
/**
|
||||
* Show log files and allow to set log levels for the configured loggers (logback)
|
||||
* to be changed dynamically at runtime.
|
||||
*/
|
||||
|
||||
public class LoggingManager {
|
||||
|
||||
/** Show all loggers or only the configured loggers */
|
||||
private boolean showAll = false;
|
||||
|
||||
/** List of log files and associated information */
|
||||
private List<LogFileInfo> logFileInfos = new ArrayList<LogFileInfo>();
|
||||
|
||||
/** List of Loggers, simplified for display purposes */
|
||||
private List<LoggerInfo> configuredLoggers = new ArrayList<LoggerInfo>();
|
||||
|
||||
/** Used to stream a logfile back to the client */
|
||||
private transient InputStream fileToDownLoad;
|
||||
|
||||
private LoggingForm model = new LoggingForm();
|
||||
|
||||
//~~~~~Reference Data~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/** Defines a collection of log levels. Unfortunately logback does not use
|
||||
* enums to define its log levels. */
|
||||
private Set<LogLevels> logLevels = EnumSet.allOf(LogLevels.class);
|
||||
|
||||
//~~~~~Prepare data~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public void init() {
|
||||
loadLoggers();
|
||||
loadLogFiles();
|
||||
}
|
||||
|
||||
//~~~~~Helper Methods~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
private void loadLoggers() {
|
||||
this.configuredLoggers.clear();
|
||||
|
||||
final List<Logger> loggers = LoggingUtil.getLoggers(this.showAll);
|
||||
|
||||
for (Logger logger : loggers) {
|
||||
|
||||
this.configuredLoggers.add(new LoggerInfo(logger.getName(), logger.getEffectiveLevel().levelInt));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLogFiles() {
|
||||
this.logFileInfos = LoggingUtil.getLogFileInfos();
|
||||
}
|
||||
|
||||
/** Updates loglevels for loggers */
|
||||
public String updateLogLevels() {
|
||||
|
||||
if (this.model.getUpdatedLoggers() != null && !this.model.getUpdatedLoggers().isEmpty()) {
|
||||
|
||||
for (LoggerInfo loggerInfo : this.model.getUpdatedLoggers()) {
|
||||
|
||||
if (loggerInfo != null && loggerInfo.getNewLogLevel() != null) {
|
||||
|
||||
LoggingUtil.getLogger(loggerInfo.getLoggerName())
|
||||
.setLevel(Level.toLevel(loggerInfo.getNewLogLevel().getLogLevel()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Need to refresh the loggers
|
||||
loadLoggers();
|
||||
}
|
||||
|
||||
|
||||
return "successRedirect";
|
||||
|
||||
}
|
||||
|
||||
/** Adds a new logger at runtime. */
|
||||
public String addNewLogger() {
|
||||
|
||||
if (this.model.getNewLogger() != null
|
||||
&& this.model.getNewLogger().getLoggerName() != null
|
||||
&& this.model.getNewLogger().getNewLogLevel() != null) {
|
||||
final Logger newLogger = LoggingUtil.getLogger(this.model.getNewLogger().getLoggerName());
|
||||
newLogger.setLevel(Level.toLevel(this.model.getNewLogger().getNewLogLevel().getLogLevel()));
|
||||
|
||||
//Need to refresh the loggers
|
||||
loadLoggers();
|
||||
}
|
||||
|
||||
return "successRedirect";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the requested log file.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public String download() throws Exception {
|
||||
|
||||
if (this.model.getFileName() == null) {
|
||||
throw new IllegalArgumentException("FileName must not be null.");
|
||||
}
|
||||
|
||||
final File logFile = LoggingUtil.getLogFile(this.model.getFileName());
|
||||
|
||||
if (logFile != null) {
|
||||
this.fileToDownLoad = new FileInputStream(logFile);
|
||||
}
|
||||
|
||||
return "download";
|
||||
}
|
||||
|
||||
//~~~~~Getters and Setters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public List<LogFileInfo> getLogFileInfos() {
|
||||
return logFileInfos;
|
||||
}
|
||||
|
||||
public InputStream getFileToDownLoad() {
|
||||
return fileToDownLoad;
|
||||
}
|
||||
|
||||
public List<LoggerInfo> getConfiguredLoggers() {
|
||||
return configuredLoggers;
|
||||
}
|
||||
|
||||
public boolean isShowAll() {
|
||||
return showAll;
|
||||
}
|
||||
|
||||
public void setShowAll(boolean showAll) {
|
||||
this.showAll = showAll;
|
||||
}
|
||||
|
||||
public Set<LogLevels> getLogLevels() {
|
||||
return logLevels;
|
||||
}
|
||||
|
||||
public LoggingForm getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(LoggingForm model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
}
|
||||
198
src/main/java/com/bwssystems/logservices/LoggingUtil.java
Normal file
198
src/main/java/com/bwssystems/logservices/LoggingUtil.java
Normal file
@@ -0,0 +1,198 @@
|
||||
package com.bwssystems.logservices;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.bwssystems.logservices.LogFileInfo;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Contains utility methods to interact with the logback during runtime.
|
||||
*/
|
||||
public class LoggingUtil {
|
||||
|
||||
/**
|
||||
* re-defines the logback logging levels as a Java enumeration. This is quite
|
||||
* helpful if you need to render the various log-levels as select-box. I wish
|
||||
* logback @see {@link ch.qos.logback.classic.Level} would not use static variables
|
||||
* but use enums instead.
|
||||
*/
|
||||
public enum LogLevels {
|
||||
|
||||
OFF(Integer.MAX_VALUE, "Off"),
|
||||
ERROR_INT(40000, "Error"),
|
||||
WARN_INT(30000, "Warn"),
|
||||
INFO_INT(20000, "Info"),
|
||||
DEBUG_INT(10000, "Debug"),
|
||||
TRACE(5000, "Trace"),
|
||||
ALL(Integer.MIN_VALUE, "All");
|
||||
|
||||
private int logLevel;
|
||||
private String logLevelName;
|
||||
|
||||
LogLevels(final int logLevel, final String logLevelName) {
|
||||
this.logLevel = logLevel;
|
||||
this.logLevelName = logLevelName;
|
||||
}
|
||||
|
||||
public int getLogLevel() {
|
||||
return this.logLevel;
|
||||
}
|
||||
|
||||
public String getLogLevelName() {
|
||||
return this.logLevelName;
|
||||
}
|
||||
|
||||
public static LogLevels getLogLevelFromId(final int logLevelAsInt) {
|
||||
|
||||
for (LogLevels logLevel : LogLevels.values()) {
|
||||
|
||||
if (logLevelAsInt == logLevel.logLevel) {
|
||||
return logLevel;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Loglevel " + logLevelAsInt + " does not exist.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.logLevelName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all configured logback loggers.
|
||||
*
|
||||
* @param showAll If set return ALL loggers, not only the configured ones.
|
||||
* @return List of Loggers
|
||||
*/
|
||||
public static List<ch.qos.logback.classic.Logger> getLoggers(final boolean showAll) {
|
||||
|
||||
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
final List<ch.qos.logback.classic.Logger> loggers = new ArrayList<ch.qos.logback.classic.Logger>();
|
||||
|
||||
for (ch.qos.logback.classic.Logger log : lc.getLoggerList()) {
|
||||
if(showAll == false) {
|
||||
if(log.getLevel() != null || LoggingUtil.hasAppenders(log)) {
|
||||
loggers.add(log);
|
||||
}
|
||||
} else {
|
||||
loggers.add(log);
|
||||
}
|
||||
}
|
||||
|
||||
return loggers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single logger.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public static ch.qos.logback.classic.Logger getLogger(final String loggerName) {
|
||||
|
||||
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
return lc.getLogger(loggerName);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the provided logger has appenders.
|
||||
*
|
||||
* @param logger The logger to test
|
||||
* @return true if the logger has appenders.
|
||||
*/
|
||||
public static boolean hasAppenders(ch.qos.logback.classic.Logger logger) {
|
||||
Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders();
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logfile information for the roor logger.
|
||||
*
|
||||
* @return List of LogFileInfo obejcts
|
||||
*/
|
||||
public static List<LogFileInfo> getLogFileInfos() {
|
||||
|
||||
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
final List<LogFileInfo> logFileInfos = new ArrayList<LogFileInfo>();
|
||||
|
||||
final Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
final Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders();
|
||||
|
||||
while (it.hasNext()) {
|
||||
|
||||
final Appender<ILoggingEvent> appender = it.next();
|
||||
|
||||
if (appender instanceof FileAppender) {
|
||||
|
||||
final FileAppender<ILoggingEvent> fileAppender = (FileAppender<ILoggingEvent>) appender;
|
||||
|
||||
final File logFile = new File(fileAppender.getFile());
|
||||
final LogFileInfo logFileInfo = new LogFileInfo();
|
||||
|
||||
logFileInfo.setFileName(logFile.getName());
|
||||
logFileInfo.setFileLastChanged(new Date(logFile.lastModified()));
|
||||
logFileInfo.setFileSize(logFile.length());
|
||||
logFileInfos.add(logFileInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return logFileInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log file.
|
||||
*
|
||||
* @param logFileName The name of the log file
|
||||
* @return The actual file
|
||||
*/
|
||||
public static File getLogFile(final String logFileName) {
|
||||
|
||||
if (logFileName == null) {
|
||||
throw new IllegalArgumentException("logFileName cannot be null.");
|
||||
}
|
||||
|
||||
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
final Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
final Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders();
|
||||
|
||||
while (it.hasNext()) {
|
||||
|
||||
final Appender<ILoggingEvent> appender = it.next();
|
||||
|
||||
if (appender instanceof FileAppender) {
|
||||
|
||||
final FileAppender<ILoggingEvent> fileAppender = (FileAppender<ILoggingEvent>) appender;
|
||||
|
||||
final File logFile = new File(fileAppender.getFile());
|
||||
|
||||
if (logFile.getName().equalsIgnoreCase(logFileName)) {
|
||||
return logFile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bwssystems.HABridge;
|
||||
package com.bwssystems.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.bwssystems.util;
|
||||
|
||||
import java.text.StringCharacterIterator;
|
||||
|
||||
public final class JsonFreeTextStringFormatter {
|
||||
private JsonFreeTextStringFormatter(){
|
||||
//empty - prevent construction
|
||||
}
|
||||
|
||||
public static String forJSON(String aText){
|
||||
final StringBuilder result = new StringBuilder();
|
||||
StringCharacterIterator iterator = new StringCharacterIterator(aText);
|
||||
char character = iterator.current();
|
||||
while (character != StringCharacterIterator.DONE){
|
||||
if( character == '\"' ){
|
||||
result.append("\\\"");
|
||||
}
|
||||
else if(character == '\\'){
|
||||
result.append("\\\\");
|
||||
}
|
||||
else if(character == '/'){
|
||||
result.append("\\/");
|
||||
}
|
||||
else if(character == '\b'){
|
||||
result.append("\\b");
|
||||
}
|
||||
else if(character == '\f'){
|
||||
result.append("\\f");
|
||||
}
|
||||
else if(character == '\n'){
|
||||
result.append("\\n");
|
||||
}
|
||||
else if(character == '\r'){
|
||||
result.append("\\r");
|
||||
}
|
||||
else if(character == '\t'){
|
||||
result.append("\\t");
|
||||
}
|
||||
else {
|
||||
//the char is not a special one
|
||||
//add it to the result as is
|
||||
result.append(character);
|
||||
}
|
||||
character = iterator.next();
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bwssystems.HABridge;
|
||||
package com.bwssystems.util;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import spark.ResponseTransformer;
|
||||
@@ -44,7 +44,7 @@ app.run( function (bridgeService) {
|
||||
|
||||
app.service('bridgeService', function ($http, $window, ngToast) {
|
||||
var self = this;
|
||||
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], type: "", settings: [], myToastMsg: [], logMsgs: [], olddevicename: "", isInControl: false, showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
|
||||
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], olddevicename: "", isInControl: false, showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
|
||||
|
||||
this.displayWarn = function(errorTitle, error) {
|
||||
if(error == null || typeof(error) != 'undefined') {
|
||||
@@ -188,6 +188,17 @@ app.service('bridgeService', function ($http, $window, ngToast) {
|
||||
);
|
||||
};
|
||||
|
||||
this.viewLoggerInfo = function () {
|
||||
return $http.get(this.state.systemsbase + "/logmgmt/loggers").then(
|
||||
function (response) {
|
||||
self.state.loggerInfo = response.data;
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Get logger info Error: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.viewNestItems = function () {
|
||||
if(!this.state.showNest)
|
||||
return;
|
||||
@@ -253,6 +264,18 @@ app.service('bridgeService', function ($http, $window, ngToast) {
|
||||
);
|
||||
};
|
||||
|
||||
this.updateLogLevels = function(logComponents) {
|
||||
return $http.put(this.state.systemsbase + "/logmgmt/update", logComponents ).then(
|
||||
function (response) {
|
||||
self.displaySuccess("Updated " + logComponents.length + " loggers for log levels.")
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Update Log components Error: ", error);
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
this.findDeviceByMapId = function(id, target, type) {
|
||||
for(var i = 0; i < this.state.devices.length; i++) {
|
||||
if(this.state.devices[i].mapId == id && this.state.devices[i].mapType == type && this.state.devices[i].targetDevice == target)
|
||||
@@ -537,8 +560,6 @@ app.controller('SystemController', function ($scope, $location, $http, $window,
|
||||
$scope.isInControl = false;
|
||||
$scope.visible = false;
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
$scope.visibleBk = false;
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||
$scope.addVeratoSettings = function (newveraname, newveraip) {
|
||||
if($scope.bridge.settings.veraaddress == null) {
|
||||
$scope.bridge.settings.veraaddress = { devices: [] };
|
||||
@@ -605,21 +626,44 @@ app.controller('SystemController', function ($scope, $location, $http, $window,
|
||||
else
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
$scope.toggleBk = function () {
|
||||
$scope.visibleBk = !$scope.visibleBk;
|
||||
if($scope.visibleBk)
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-minus";
|
||||
else
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('LogsController', function ($scope, $location, $http, $window, bridgeService) {
|
||||
bridgeService.viewLogs();
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.levels = ["INFO_INT", "WARN_INT", "DEBUG_INT", "TRACE_INT"];
|
||||
$scope.updateComponents = [];
|
||||
$scope.visible = false;
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
$scope.updateLogs = function() {
|
||||
bridgeService.viewLogs();
|
||||
};
|
||||
$scope.toggle = function () {
|
||||
$scope.visible = !$scope.visible;
|
||||
if($scope.visible) {
|
||||
$scope.imgUrl = "glyphicon glyphicon-minus";
|
||||
bridgeService.viewLoggerInfo();
|
||||
}
|
||||
else
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
$scope.addToUpdate = function (logInfo) {
|
||||
var idx = $scope.updateComponents.indexOf(logInfo);
|
||||
|
||||
// is currently selected
|
||||
if (idx > -1) {
|
||||
$scope.updateComponents.splice(idx, 1);
|
||||
}
|
||||
|
||||
// is newly selected
|
||||
else {
|
||||
$scope.updateComponents.push(logInfo);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.updateLoggers = function () {
|
||||
bridgeService.updateLogLevels($scope.updateComponents);
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('ViewingController', function ($scope, $location, $http, $window, bridgeService, ngDialog) {
|
||||
|
||||
@@ -39,4 +39,35 @@
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default logconfig">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">Logging Configuration <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></h1>
|
||||
</div>
|
||||
<div ng-if="visible" class="animate-if" class="panel-body">
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit"
|
||||
ng-click="updateLoggers()">Update Log Levels</button>
|
||||
</p>
|
||||
<scrollable-table watch="bridge.loggerInfo">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th sortable-header col="logLevel">Log Level</th>
|
||||
<th sortable-header col="loggerName">Component</th>
|
||||
<th>New Log Level</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="logInfo in bridge.loggerInfo">
|
||||
<td>{{logInfo.logLevel.substr(0,4)}}</td>
|
||||
<td>{{logInfo.loggerName}}</td>
|
||||
<td>
|
||||
<select name="new-log-level" id="new-log-level" ng-change="addToUpdate(logInfo)" ng-model="logInfo.newLogLevel">
|
||||
<option ng-repeat="alevel in levels" value="{{alevel}}">{{alevel.substr(0,4)}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -174,9 +174,9 @@
|
||||
</div>
|
||||
<div class="panel panel-default backup">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">Bridge Settings Backup <a ng-click="toggleBk()"><span class={{imgBkUrl}} aria-hidden="true"></a></h1>
|
||||
<h1 class="panel-title">Bridge Settings Backup <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></h1>
|
||||
</div>
|
||||
<div ng-if="visibleBk" class="animate-if" class="panel-body">
|
||||
<div ng-if="visible" class="animate-if" class="panel-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="backup-name">Backup Settings File Name</label>
|
||||
|
||||
Reference in New Issue
Block a user