1
+ < script runat = "server" language = "javascript" >
2
+
3
+ // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
4
+ //
5
+ // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
6
+ // NOT CONTROL.
7
+ //
8
+ // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9
+ // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10
+ // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11
+ // and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12
+ //
13
+ // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14
+ // of the Software.
15
+ //
16
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17
+ // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19
+ // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
+ // DEALINGS IN THE SOFTWARE.
21
+
22
+ /**
23
+ * Copyright: { @link https :/ / www . email360 . io / | email360 }
24
+ * < br > Author: { @link https :/ / www . linkedin . com / in / sascha - huwald / | Sascha Huwald }
25
+ * < br > Since: 2022
26
+ * < br > Version: 1.0.0
27
+ * < br > License: MIT
28
+ *
29
+ * This is a mini log4ssjs version based on log4j
30
+ *
31
+ * A log request of level p in a logger with level q is enabled if p >= q . This rule is
32
+ * at the heart of log4j . It assumes that levels are ordered . For the standard levels ,
33
+ * we have ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF .
34
+ *
35
+ * The Following example shows how we can filter all our DEBUG and INFO messages . This
36
+ * program uses of logger method level ( X ) to set a desired logging level .
37
+ *
38
+ * This example would print all the messages except DEBUG and INFO :
39
+ *
40
+ * @example
41
+ * var log = new logger ( 'myScript ') ;
42
+ * log . level = 'WARN'
43
+ *
44
+ * log . trace ( "Trace Message ! ") ;
45
+ * log . debug ( "Debug Message ! ") ;
46
+ * log . info ( "Info Message ! ") ;
47
+ * log . warn ( "Warn Message ! ") ;
48
+ * log . error ( "Error Message ! ") ;
49
+ * log . fatal ( "Fatal Message ! ") ;
50
+ *
51
+ * @description
52
+ * Output from the above example
53
+ * Warn Message !
54
+ * Error Message !
55
+ * Fatal Message !
56
+ *
57
+ * This is an example configuration .
58
+ * @example
59
+ * log . configure = {
60
+ * appenders : [
61
+ * {
62
+ * type : "DataExtension" ,
63
+ * level : "DEBUG" ,
64
+ * call : {
65
+ * name : 'My DataExtension'
66
+ * }
67
+ * } , {
68
+ * type : "HTTP" ,
69
+ * level : "ERROR" ,
70
+ * call : {
71
+ * url : "http://www.email360.io" ,
72
+ * method : "POST" ,
73
+ * header : "Bearer " + token ,
74
+ * contentType : "application/json" ,
75
+ * payload : {
76
+ * jwt : "myToken" ,
77
+ * extra : "Payload"
78
+ * }
79
+ * }
80
+ * } , {
81
+ * type : "Console" ,
82
+ * level : "TRACE" ,
83
+ * call : {
84
+ * target : [ 'console' , 'text' ]
85
+ * }
86
+ * }
87
+ * ] } ;
88
+ *
89
+ * @param { string } name - The name of the script / c a t e g o r y u s e d t o i d e n t i f y t h e l o g
90
+ *
91
+ * /
92
+ function logger ( name ) {
93
+ if ( ! name ) {
94
+ throw "[logger] No Logger category provided." ;
95
+ }
96
+
97
+ this . category = name ;
98
+ this . configure = { } ;
99
+ this . level = 'OFF' ;
100
+ // Log4j hirachy
101
+ this . levels = {
102
+ ALL : 0 ,
103
+ TRACE : 10 ,
104
+ DEBUG : 20 ,
105
+ INFO : 30 ,
106
+ WARN : 40 ,
107
+ ERROR : 50 ,
108
+ FATAL : 60 ,
109
+ OFF : 100
110
+ } ;
111
+ this . allowedAppenders = [ 'DataExtension' , 'Console' , 'HTTP' ] ;
112
+ this . logId = null ;
113
+
114
+ this . trace = function ( message ) { this . _appenders ( message , 'trace' ) ; }
115
+ this . debug = function ( message ) { this . _appenders ( message , 'debug' ) ; }
116
+ this . info = function ( message ) { this . _appenders ( message , 'info' ) ; }
117
+ this . warn = function ( message ) { this . _appenders ( message , 'warn' ) ; }
118
+ this . error = function ( message ) { this . _appenders ( message , 'error' ) ; }
119
+ this . fatal = function ( message ) { this . _appenders ( message , 'fatal' ) ; }
120
+
121
+ /**
122
+ * Wrapper to decide if the message should be handled by the appender
123
+ *
124
+ * @param {string } message - The message itself
125
+ * @param {string } messageLevel - The message level such as WARN,INFO,ERROR
126
+ */
127
+ this . _appenders = function ( message , messageLevel ) {
128
+ if ( isObject ( this . configure ) && this . configure . hasOwnProperty ( 'appenders' ) ) {
129
+ var appenders = ( ! Array . isArray ( this . configure . appenders ) ) ? [ this . configure . appenders ] : this . configure . appenders ;
130
+
131
+ for ( var i = 0 ; i < appenders . length ; i ++ ) {
132
+ var appender = appenders [ i ] ;
133
+
134
+ // check if user given level exists otherwise keep original level
135
+ if ( appender . hasOwnProperty ( 'level' ) && this . levels . hasOwnProperty ( appender . level . toUpperCase ( ) ) ) {
136
+ this . level = appender . level . toUpperCase ( ) ;
137
+ }
138
+ this . _log ( message , messageLevel , appender ) ;
139
+ }
140
+
141
+ } else {
142
+ this . _log ( message , messageLevel ) ;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * The actual log function to log the message based on the given
148
+ * appender.
149
+ *
150
+ * @param {string } message - The message to be log
151
+ * @param {string } messageLevel - The message level such as WARN, INFO, ERROR
152
+ * @param {object } appender - Appender object
153
+ *
154
+ * @param {string } appender.type - The appender type name
155
+ * @param {object } [appender.call] - Call information for each appender
156
+ */
157
+ this . _log = function ( message , messageLevel , appender ) {
158
+ var appender = ( this . allowedAppenders . includes ( appender . type ) ) ? appender : { type : 'Console' } ,
159
+ logLevelNumber = this . levels [ this . level ] ,
160
+ messageLevel = messageLevel . toUpperCase ( ) ;
161
+ messageLevelNumber = this . levels [ messageLevel ] ;
162
+
163
+ // message level must be greater or equal than log level but smaller than off
164
+ if ( messageLevelNumber >= logLevelNumber && messageLevelNumber < this . levels [ 'OFF' ] ) {
165
+
166
+ this . logId = Platform . Function . GUID ( ) ;
167
+
168
+ switch ( appender . type ) {
169
+ case 'DataExtension' :
170
+ this . _appenderDataExtension ( messageLevel , message , appender . call ) ;
171
+ break ;
172
+ case 'HTTP' :
173
+ this . _appenderHTTP ( messageLevel , message , appender . call ) ;
174
+ break ;
175
+ case 'Console' :
176
+ this . _appenderConsole ( messageLevel , message , appender . call ) ;
177
+ break ;
178
+ }
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Get the log time in a readable format
184
+ *
185
+ * @param {boolean } inMilliseconds - The given time will include milliseconds
186
+ * @returns {string }
187
+ */
188
+ this . _getLogTime = function ( inMilliseconds ) {
189
+ var dd = Platform . Function . SystemDateToLocalDate ( new Date ( getUnixTimestamp ( inMilliseconds ) ) ) ,
190
+ pad = function ( number , dec ) { var dec = dec || 2 ; return String ( number ) . padStart ( dec , '0' ) } ;
191
+
192
+ return dd . getFullYear ( ) +
193
+ '-' + pad ( dd . getMonth ( ) + 1 ) +
194
+ '-' + pad ( dd . getDate ( ) ) +
195
+ ' ' + pad ( dd . getHours ( ) ) +
196
+ ':' + pad ( dd . getMinutes ( ) ) +
197
+ ':' + pad ( dd . getSeconds ( ) ) +
198
+ '.' + pad ( dd . getMilliseconds ( ) , 3 ) ;
199
+ }
200
+
201
+ /**
202
+ * DataExtension appender
203
+ *
204
+ * This appender will store the message in the system DataExtension
205
+ *
206
+ * @param {string } level - The message level such as WARN, INFO, ERROR
207
+ * @param {string } message - The message to log
208
+ * @param {object } appender - Appender object
209
+ *
210
+ * @param {array } [appender.name] - The name of the DataExtension to log
211
+ */
212
+ this . _appenderDataExtension = function ( level , message , appender ) {
213
+ var settings = new settings ( ) ,
214
+ de = appender . name || settings . de . log . Name ,
215
+ name = [ ] ,
216
+ value = [ ] ;
217
+
218
+ var logTime = this . _getLogTime ( true ) ,
219
+ logId = this . logId ,
220
+ logCategory = this . category ;
221
+
222
+ var log = {
223
+ timestamp : logTime ,
224
+ id : logId ,
225
+ level : level ,
226
+ message : message ,
227
+ category : logCategory
228
+ } ;
229
+
230
+ // prep the data for insert
231
+ for ( var i in log ) {
232
+ name . push ( i ) ;
233
+ value . push ( log [ i ] ) ;
234
+ }
235
+
236
+ // write error log to DE
237
+ var r = Platform . Function . InsertDE ( de , name , value ) ;
238
+ }
239
+
240
+ /**
241
+ * Console appender
242
+ *
243
+ * This appender will display the message in the browser console
244
+ *
245
+ * @param {string } level - The message level such as WARN, INFO, ERROR
246
+ * @param {string } message - The message to log
247
+ * @param {object } appender - Appender object
248
+ *
249
+ * @param {array } [appender.target] - An array to define the output of the console
250
+ * Allowed values are 'console', 'text' and / or 'html'
251
+ */
252
+ this . _appenderConsole = function ( level , message , appender ) {
253
+ var message = ( typeof message === 'string' ) ? message . replace ( / < s c r i p t [ \s \S ] * ?> / gi, '' ) . replace ( / < \/ s c r i p t > / gi, '' ) : message ,
254
+ target = ( Array . isArray ( appender . target ) ) ? appender . target : [ 'console' ] ;
255
+
256
+ var log = '[' + this . _getLogTime ( true ) + '] [' + level + '] [' + this . category + '] ' + message ;
257
+
258
+ if ( target . includes ( 'console' ) ) {
259
+ console_log ( log ) ;
260
+ }
261
+ if ( target . includes ( 'html' ) ) {
262
+ log = ( typeof log == 'string' ) ? log . replace ( '\n' , '<br/>' ) . replace ( '\t' , '  ' ) : Platform . Function . Stringify ( log ) ;
263
+ Platform . Response . Write ( '<pre style="margin:0.85em 0px;"><span style="font-size: 11px;">' + log + '</span></pre>' ) ;
264
+ }
265
+ if ( target . includes ( 'text' ) ) {
266
+ Platform . Response . Write ( '{' + Platform . Function . Stringify ( log ) + '}\n' ) ;
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Console HTTP
272
+ *
273
+ * This appender will send the message via a httprequest to the appender.url
274
+ *
275
+ * @param {string } level - The message level such as WARN, INFO, ERROR
276
+ * @param {string } message - The message to log
277
+ * @param {object } appender - Appender object
278
+ *
279
+ * @param {string } appender.url - The target URL for the HTTPRequest
280
+ * @param {string } [appender.methdod=POST] - The HTTP method
281
+ * @param {string } [appender.header] - The HTTP header
282
+ * @param {string } [appender.contentType=application/json] - The HTTP contentType.
283
+ * @param {object } [appender.paylaod] - Additional payload for the HTTP request
284
+ */
285
+ this . _appenderHTTP = function ( level , message , appender ) {
286
+ if ( ! appender . url ) {
287
+ throw "[logger] No Appender URL found for appender HTTP" ;
288
+ }
289
+
290
+ // log details
291
+ var logTime = this . _getLogTime ( true ) ,
292
+ logId = this . logId ,
293
+ logCategory = this . category ;
294
+
295
+ // HTTP parameter
296
+ var header = appender . header || null ,
297
+ contentType = appender . contentType || "application/json" ,
298
+ method = appender . method || 'POST' ,
299
+ payload = {
300
+ Timestamp : logTime ,
301
+ Id : logId ,
302
+ Level : level ,
303
+ Message : message ,
304
+ Category : logCategory
305
+ } ;
306
+
307
+ payload = mergeObject ( payload , appender . payload || { } ) ;
308
+
309
+ var resp = httpRequest ( method , appender . url , contentType , payload , header ) ;
310
+ if ( resp . status != '200' ) {
311
+ throw "[logger] Failed to log to [HTTP] on [" + appender . url + "]: " + Stringify ( resp . content ) ;
312
+ }
313
+ }
314
+ }
315
+
316
+ < / s c r i p t >
0 commit comments