Skip to content

Commit ba80610

Browse files
authored
Merge pull request #158 from iot-dsa-v2/develop
0.70.4
2 parents 0087bb5 + b74e19e commit ba80610

File tree

8 files changed

+116
-32
lines changed

8 files changed

+116
-32
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ subprojects {
55
apply plugin: 'maven'
66

77
group 'org.iot-dsa'
8-
version '0.70.2'
8+
version '0.70.4'
99

1010
targetCompatibility = JavaVersion.VERSION_1_8
1111
sourceCompatibility = JavaVersion.VERSION_1_8

dslink-v2-api/src/main/java/org/iot/dsa/dslink/Value.java

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ public interface Value extends Node {
1717
/**
1818
* Does not have to be the current value, used to determine the type
1919
* of the value.
20-
* @return
2120
*/
2221
public DSIValue toValue();
2322

dslink-v2-api/src/main/java/org/iot/dsa/node/action/DSAction.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.iot.dsa.node.DSIMetadata;
77
import org.iot.dsa.node.DSIObject;
88
import org.iot.dsa.node.DSIValue;
9+
import org.iot.dsa.node.DSInfo;
910
import org.iot.dsa.node.DSMap;
1011
import org.iot.dsa.node.DSMetadata;
1112

@@ -208,9 +209,15 @@ public int getParameterCount() {
208209
return -1;
209210
}
210211

212+
/**
213+
* Puts the metadata from an already added parameter into the bucket, and calls prepareParameter
214+
* so that is can be updated for any current state.
215+
* @see #prepareParameter(DSInfo, DSMap)
216+
*/
211217
@Override
212-
public void getParameterMetadata(int idx, DSMap bucket) {
218+
public void getParameterMetadata(DSInfo target, int idx, DSMap bucket) {
213219
bucket.putAll(parameters.get(idx));
220+
prepareParameter(target, bucket);
214221
}
215222

216223
@Override
@@ -228,6 +235,17 @@ public ActionResults invoke(DSIActionRequest request) {
228235
return null;
229236
}
230237

238+
/**
239+
* Called for each parameter as it is being sent to the requester in response to a list
240+
* request. The intent is to update the default value to represent the current state of the
241+
* target. Does nothing by default.
242+
*
243+
* @param target The target of the action.
244+
* @param parameter Map representing a single parameter.
245+
*/
246+
public void prepareParameter(DSInfo target, DSMap parameter) {
247+
}
248+
231249
/**
232250
* Sets the action group, which is null by default.
233251
*/

dslink-v2-api/src/main/java/org/iot/dsa/node/action/DSIAction.java

-11
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,6 @@ public default ActionResults makeResults(DSIActionRequest req, DSIResults res) {
100100
return toResults(req, res);
101101
}
102102

103-
/**
104-
* Called for each parameter as it is being sent to the requester in response to a list
105-
* request. The intent is to update the default value to represent the current state of the
106-
* target. Does nothing by default.
107-
*
108-
* @param target The info about the target of the action (its parent).
109-
* @param parameter Map representing a single parameter.
110-
*/
111-
public default void prepareParameter(DSInfo target, DSMap parameter) {
112-
}
113-
114103
/**
115104
* Makes an aync action result for the given parameters. If the DIResult defines columns those
116105
* will be used, otherwise the columns defined by the action will be used.

dslink-v2/src/main/java/com/acuity/iot/dsa/dslink/protocol/responder/DSInboundList.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.iot.dsa.node.DSNode;
3030
import org.iot.dsa.node.DSPath;
3131
import org.iot.dsa.node.DSString;
32+
import org.iot.dsa.node.action.DSIAction;
3233
import org.iot.dsa.node.event.DSEvent;
3334
import org.iot.dsa.node.event.DSISubscriber;
3435
import org.iot.dsa.node.event.DSISubscription;
@@ -451,14 +452,22 @@ private void encodeAction(Action action, DSMap cacheMap) {
451452
enqueue("$invokable", "read");
452453
}
453454
}
455+
DSIAction dsiAction = null;
456+
if (action instanceof DSIAction) {
457+
dsiAction = (DSIAction) action;
458+
}
454459
e = cacheMap.remove("$params");
455460
if (e != null) {
456461
enqueue("$params", e);
457462
} else {
458463
DSList list = new DSList();
459464
for (int i = 0, len = action.getParameterCount(); i < len; i++) {
460465
DSMap param = new DSMap();
461-
action.getParameterMetadata(i, param);
466+
if (dsiAction != null) {
467+
dsiAction.getParameterMetadata(target.getParentInfo(), i, param);
468+
} else {
469+
action.getParameterMetadata(i, param);
470+
}
462471
fixRangeTypes(param);
463472
list.add(param);
464473
}
@@ -471,7 +480,11 @@ private void encodeAction(Action action, DSMap cacheMap) {
471480
DSList list = new DSList();
472481
for (int i = 0, len = action.getColumnCount(); i < len; i++) {
473482
DSMap col = new DSMap();
474-
action.getColumnMetadata(i, col);
483+
if (dsiAction != null) {
484+
dsiAction.getColumnMetadata(target.getParentInfo(), i, col);
485+
} else {
486+
action.getColumnMetadata(i, col);
487+
}
475488
fixRangeTypes(col);
476489
list.add(col);
477490
}

dslink-v2/src/main/java/com/acuity/iot/dsa/dslink/sys/logging/LoggerNode.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
*/
99
public class LoggerNode extends StreamableLogNode {
1010

11-
private DSInfo levelInfo = getInfo("Log Level");
11+
private DSInfo<?> levelInfo = getInfo("Log Level");
1212
private Logger logger;
1313

1414
public LoggerNode() {
1515
}
1616

17-
public DSInfo getLevelInfo() {
17+
public DSInfo<?> getLevelInfo() {
1818
return levelInfo;
1919
}
2020

@@ -29,7 +29,7 @@ public Logger getLoggerObj() {
2929
protected void declareDefaults() {
3030
super.declareDefaults();
3131
declareDefault("Log Level", LoggerNodeLevel.DEFAULT);
32-
declareDefault("Stream Log", getStreamLogAction());
32+
declareDefault("Stream Log", getStreamLogAction(false));
3333
}
3434

3535
@Override
@@ -45,7 +45,7 @@ protected void onChildChanged(DSInfo info) {
4545
@Override
4646
protected void onStable() {
4747
super.onStable();
48-
DSInfo info = getLevelInfo();
48+
DSInfo<?> info = getLevelInfo();
4949
LoggerNodeLevel level = (LoggerNodeLevel) info.get();
5050
getLoggerObj().setLevel(level.toLevel());
5151
}

dslink-v2/src/main/java/com/acuity/iot/dsa/dslink/sys/logging/StreamableLogNode.java

+75-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.acuity.iot.dsa.dslink.sys.logging;
22

3+
import java.io.PrintWriter;
4+
import java.io.StringWriter;
35
import java.util.LinkedList;
46
import java.util.List;
57
import java.util.logging.Handler;
8+
import java.util.logging.Level;
69
import java.util.logging.LogRecord;
710
import java.util.logging.Logger;
811
import org.iot.dsa.dslink.Action.ResultsType;
@@ -17,6 +20,7 @@
1720
import org.iot.dsa.node.DSString;
1821
import org.iot.dsa.node.action.DSAction;
1922
import org.iot.dsa.node.action.DSIActionRequest;
23+
import org.iot.dsa.time.DSDateTime;
2024

2125
/**
2226
* @author Daniel Shapiro
@@ -25,36 +29,51 @@ public abstract class StreamableLogNode extends DSNode {
2529

2630
private static DSList levelRange;
2731

28-
public abstract DSInfo getLevelInfo();
32+
public abstract DSInfo<?> getLevelInfo();
2933

3034
public abstract Logger getLoggerObj();
3135

32-
protected DSAction getStreamLogAction() {
36+
protected DSAction getStreamLogAction(boolean isRoot) {
3337
DSAction act = new DSAction() {
3438
@Override
3539
public ActionResults invoke(DSIActionRequest req) {
3640
return ((StreamableLogNode) req.getTarget()).startLogStream(req);
3741
}
3842
};
43+
if (isRoot) {
44+
act.addParameter("Log Name", DSString.NULL, "Optional log name to filter by");
45+
}
46+
act.addDefaultParameter("Log Level", DSLevel.ALL, "Log level filter");
3947
act.addParameter("Filter", DSString.NULL, "Optional regex filter");
4048
act.setResultsType(ResultsType.STREAM);
41-
act.addColumnMetadata("Log", DSString.NULL).setEditor("textarea");
49+
act.addColumnMetadata("Timestamp", DSDateTime.NULL);
50+
act.addColumnMetadata("Log Name", DSString.NULL);
51+
act.addColumnMetadata("Level", DSLevel.ALL);
52+
act.addColumnMetadata("Message", DSString.NULL).setEditor("textarea");
4253
return act;
4354
}
4455

4556
private ActionResults startLogStream(final DSIActionRequest req) {
4657
final Logger loggerObj = getLoggerObj();
58+
final String name = req.getParameters().getString("Log Name");
59+
final DSLevel level = DSLevel.make(req.getParameters().getString("Log Level"));
4760
final String filter = req.getParameters().getString("Filter");
48-
final List<String> lines = new LinkedList<>();
61+
final List<DSList> lines = new LinkedList<>();
4962
final Handler handler = new DSLogHandler() {
5063
@Override
5164
protected void write(LogRecord record) {
52-
String line = toString(this, record);
53-
if (filter == null || line.matches(filter)) {
65+
String recordName = record.getLoggerName();
66+
Level recordLevel = record.getLevel();
67+
String recordMsg = encodeLogRecord(record);
68+
DSDateTime ts = DSDateTime.valueOf(record.getMillis());
69+
if (levelMatches(recordLevel, level.toLevel()) &&
70+
(name == null || name.isEmpty() || name.equals(recordName)) &&
71+
(filter == null || filter.isEmpty() || recordMsg.matches(filter))) {
72+
5473
while (lines.size() > 1000) {
5574
lines.remove(0);
5675
}
57-
lines.add(line);
76+
lines.add(DSList.valueOf(ts.toString(), recordName, DSLevel.valueOf(recordLevel).toString(), recordMsg));
5877
req.sendResults();
5978
}
6079
}
@@ -63,17 +82,25 @@ protected void write(LogRecord record) {
6382
return new ActionResults() {
6483
@Override
6584
public int getColumnCount() {
66-
return 1;
85+
return 4;
6786
}
6887

6988
@Override
7089
public void getColumnMetadata(int idx, DSMap bucket) {
71-
new DSMetadata(bucket).setName("Record").setType(DSString.NULL);
90+
if (idx == 0) {
91+
new DSMetadata(bucket).setName("Timestamp").setType(DSDateTime.NULL);
92+
} else if (idx == 1) {
93+
new DSMetadata(bucket).setName("Log Name").setType(DSString.NULL);
94+
} else if (idx == 2) {
95+
new DSMetadata(bucket).setName("Level").setType(DSLevel.ALL);
96+
} else if (idx == 3) {
97+
new DSMetadata(bucket).setName("Message").setType(DSString.NULL);
98+
}
7299
}
73100

74101
@Override
75102
public void getResults(DSList bucket) {
76-
bucket.add(DSString.valueOf(lines.remove(0)));
103+
bucket.addAll(lines.remove(0));
77104
}
78105

79106
@Override
@@ -93,6 +120,44 @@ public void onClose() {
93120
}
94121
};
95122
}
123+
124+
private static String encodeLogRecord(LogRecord record) {
125+
StringBuilder builder = new StringBuilder();
126+
// class
127+
if (record.getSourceClassName() != null) {
128+
builder.append(record.getSourceClassName());
129+
builder.append(" - ");
130+
}
131+
// method
132+
if (record.getSourceMethodName() != null) {
133+
builder.append(record.getSourceMethodName());
134+
builder.append(" - ");
135+
}
136+
// message
137+
String msg = record.getMessage();
138+
if ((msg != null) && (msg.length() > 0)) {
139+
Object[] params = record.getParameters();
140+
if (params != null) {
141+
msg = String.format(msg, params);
142+
}
143+
builder.append(msg);
144+
}
145+
// exception
146+
Throwable thrown = record.getThrown();
147+
if (thrown != null) {
148+
builder.append("\n");
149+
StringWriter sw = new StringWriter();
150+
PrintWriter pw = new PrintWriter(sw);
151+
thrown.printStackTrace(pw);
152+
pw.close();
153+
builder.append(sw.toString());
154+
}
155+
return builder.toString();
156+
}
157+
158+
public static boolean levelMatches(Level msgLevel, Level desiredLevel) {
159+
return msgLevel.intValue() >= desiredLevel.intValue();
160+
}
96161

97162
static {
98163
levelRange = new DSList();

dslink-v2/src/main/java/com/acuity/iot/dsa/dslink/sys/logging/SysLogService.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*/
2323
public class SysLogService extends StreamableLogNode {
2424

25-
private DSInfo levelInfo = getInfo("Default Log Level");
25+
private DSInfo<?> levelInfo = getInfo("Default Log Level");
2626

2727
public SysLogService() {
2828
}
@@ -40,7 +40,7 @@ public Logger getLoggerObj() {
4040
protected void declareDefaults() {
4141
super.declareDefaults();
4242
declareDefault("Add Log", getAddLogAction());
43-
declareDefault("Stream All", getStreamLogAction());
43+
declareDefault("Stream All", getStreamLogAction(true));
4444
declareDefault("Default Log Level", DSLevel.valueOf(getRootLevel()))
4545
.setTransient(true);
4646
}

0 commit comments

Comments
 (0)