1
1
package com .acuity .iot .dsa .dslink .sys .logging ;
2
2
3
+ import java .io .PrintWriter ;
4
+ import java .io .StringWriter ;
3
5
import java .util .LinkedList ;
4
6
import java .util .List ;
5
7
import java .util .logging .Handler ;
8
+ import java .util .logging .Level ;
6
9
import java .util .logging .LogRecord ;
7
10
import java .util .logging .Logger ;
8
11
import org .iot .dsa .dslink .Action .ResultsType ;
17
20
import org .iot .dsa .node .DSString ;
18
21
import org .iot .dsa .node .action .DSAction ;
19
22
import org .iot .dsa .node .action .DSIActionRequest ;
23
+ import org .iot .dsa .time .DSDateTime ;
20
24
21
25
/**
22
26
* @author Daniel Shapiro
@@ -25,36 +29,51 @@ public abstract class StreamableLogNode extends DSNode {
25
29
26
30
private static DSList levelRange ;
27
31
28
- public abstract DSInfo getLevelInfo ();
32
+ public abstract DSInfo <?> getLevelInfo ();
29
33
30
34
public abstract Logger getLoggerObj ();
31
35
32
- protected DSAction getStreamLogAction () {
36
+ protected DSAction getStreamLogAction (boolean isRoot ) {
33
37
DSAction act = new DSAction () {
34
38
@ Override
35
39
public ActionResults invoke (DSIActionRequest req ) {
36
40
return ((StreamableLogNode ) req .getTarget ()).startLogStream (req );
37
41
}
38
42
};
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" );
39
47
act .addParameter ("Filter" , DSString .NULL , "Optional regex filter" );
40
48
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" );
42
53
return act ;
43
54
}
44
55
45
56
private ActionResults startLogStream (final DSIActionRequest req ) {
46
57
final Logger loggerObj = getLoggerObj ();
58
+ final String name = req .getParameters ().getString ("Log Name" );
59
+ final DSLevel level = DSLevel .make (req .getParameters ().getString ("Log Level" ));
47
60
final String filter = req .getParameters ().getString ("Filter" );
48
- final List <String > lines = new LinkedList <>();
61
+ final List <DSList > lines = new LinkedList <>();
49
62
final Handler handler = new DSLogHandler () {
50
63
@ Override
51
64
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
+
54
73
while (lines .size () > 1000 ) {
55
74
lines .remove (0 );
56
75
}
57
- lines .add (line );
76
+ lines .add (DSList . valueOf ( ts . toString (), recordName , DSLevel . valueOf ( recordLevel ). toString (), recordMsg ) );
58
77
req .sendResults ();
59
78
}
60
79
}
@@ -63,17 +82,25 @@ protected void write(LogRecord record) {
63
82
return new ActionResults () {
64
83
@ Override
65
84
public int getColumnCount () {
66
- return 1 ;
85
+ return 4 ;
67
86
}
68
87
69
88
@ Override
70
89
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
+ }
72
99
}
73
100
74
101
@ Override
75
102
public void getResults (DSList bucket ) {
76
- bucket .add ( DSString . valueOf ( lines .remove (0 ) ));
103
+ bucket .addAll ( lines .remove (0 ));
77
104
}
78
105
79
106
@ Override
@@ -93,6 +120,44 @@ public void onClose() {
93
120
}
94
121
};
95
122
}
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
+ }
96
161
97
162
static {
98
163
levelRange = new DSList ();
0 commit comments