Adding log level control

This commit is contained in:
Admin
2016-02-26 16:38:14 -06:00
parent 1a2024d92b
commit 8ce0483e54
18 changed files with 691 additions and 22 deletions

View File

@@ -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>

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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());

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -1,4 +1,4 @@
package com.bwssystems.HABridge;
package com.bwssystems.util;
import java.io.IOException;
import java.nio.file.DirectoryStream;

View File

@@ -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();
}
}

View File

@@ -1,4 +1,4 @@
package com.bwssystems.HABridge;
package com.bwssystems.util;
import com.google.gson.Gson;
import spark.ResponseTransformer;

View File

@@ -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) {

View File

@@ -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>

View File

@@ -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>