profoundjs-swagger-stats 1.1.4 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/dashboards/prometheus/swagger-stats dashboard v3.json +1269 -0
- package/examples/authtest/authtest.js +5 -10
- package/examples/fastify/fasifytest.js +24 -5
- package/examples/hapijstest/hapijstest.js +17 -2
- package/examples/restify/restifytest.js +16 -1
- package/examples/spectest/spectest.js +7 -9
- package/examples/testapp/petstore.json +1699 -0
- package/examples/testapp/testapp.js +6 -62
- package/lib/sws-api-swagger.yaml +1 -1
- package/lib/swsAPIStats.js +6 -1
- package/lib/swsAuth.js +140 -0
- package/lib/swsElasticEmitter.js +103 -45
- package/lib/swsHapi.js +29 -34
- package/lib/swsInterface.js +40 -189
- package/lib/swsProcessor.js +6 -1
- package/lib/swsReqResStats.js +1 -1
- package/lib/swsUtil.js +7 -21
- package/lib/swssettings.js +8 -2
- package/package.json +90 -91
- package/schema/elasticsearch/api_index_template.json +1 -1
- package/schema/elasticsearch/api_index_template_7x.json +185 -0
- package/scripts/elasticsearch/elastic7/docker-compose.yml +6 -17
- package/scripts/elasticsearch/elastic8/docker-compose.yml +34 -0
- package/ux/css/app.dc22c4da.css +7 -0
- package/ux/css/chunk-vendors.a6da6d7a.css +10 -0
- package/ux/fonts/KFOkCnqEu92Fr1MmgVxIIzQ.4aa2e698.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.40bcb2b8.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.ea60988b.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.0774a8b7.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmYUtfBBc-.bcb7c7e2.woff +0 -0
- package/ux/fonts/KFOmCnqEu92Fr1Mu4mxM.d3907d0c.woff +0 -0
- package/ux/fonts/fa-brands-400.1a575a41.woff +0 -0
- package/ux/fonts/fa-brands-400.ed311c7a.woff2 +0 -0
- package/ux/fonts/fa-regular-400.b91d376b.woff2 +0 -0
- package/ux/fonts/fa-regular-400.d1d7e3b4.woff +0 -0
- package/ux/fonts/fa-solid-900.d745348d.woff +0 -0
- package/ux/fonts/fa-solid-900.d824df7e.woff2 +0 -0
- package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.3e1afe59.woff +0 -0
- package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.a4160421.woff2 +0 -0
- package/ux/index.html +1 -1
- package/ux/js/app.d095d0d6.js +1 -0
- package/ux/js/chunk-2d0b90b4.afe783bc.js +8 -0
- package/ux/js/chunk-2d0daf1e.a05fda31.js +11 -0
- package/ux/js/chunk-461883cd.a2aa4876.js +82 -0
- package/ux/js/chunk-vendors.4f167dc9.js +39 -0
- package/ux/logo.png +0 -0
- package/.editorconfig +0 -21
- package/.travis.yml +0 -23
- package/dashboards/prometheus/swagger-stats dashboard.json +0 -1118
- package/dist/css/sws.min.css +0 -18
- package/dist/fonts/FontAwesome.otf +0 -0
- package/dist/fonts/fontawesome-webfont.eot +0 -0
- package/dist/fonts/fontawesome-webfont.svg +0 -2671
- package/dist/fonts/fontawesome-webfont.ttf +0 -0
- package/dist/fonts/fontawesome-webfont.woff +0 -0
- package/dist/fonts/fontawesome-webfont.woff2 +0 -0
- package/dist/fonts/glyphicons-halflings-regular.eot +0 -0
- package/dist/fonts/glyphicons-halflings-regular.svg +0 -288
- package/dist/fonts/glyphicons-halflings-regular.ttf +0 -0
- package/dist/fonts/glyphicons-halflings-regular.woff +0 -0
- package/dist/fonts/glyphicons-halflings-regular.woff2 +0 -0
- package/dist/images/favicon.png +0 -0
- package/dist/js/sws.min.js +0 -1
- package/gulpfile.js +0 -103
- package/karma.conf.js +0 -153
- package/ux/css/app.71245b0e.css +0 -7
- package/ux/css/chunk-vendors.809c52d1.css +0 -10
- package/ux/fonts/KFOkCnqEu92Fr1MmgVxIIzQ.5cb7edfc.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.87284894.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.b00849e0.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.adcde98f.woff +0 -0
- package/ux/fonts/KFOlCnqEu92Fr1MmYUtfBBc-.bb1e4dc6.woff +0 -0
- package/ux/fonts/KFOmCnqEu92Fr1Mu4mxM.60fa3c06.woff +0 -0
- package/ux/fonts/fa-brands-400.c5e0f14f.woff +0 -0
- package/ux/fonts/fa-brands-400.cccc9d29.woff2 +0 -0
- package/ux/fonts/fa-regular-400.c4f508e7.woff +0 -0
- package/ux/fonts/fa-regular-400.f5f2566b.woff2 +0 -0
- package/ux/fonts/fa-solid-900.333bae20.woff +0 -0
- package/ux/fonts/fa-solid-900.44d537ab.woff2 +0 -0
- package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.29b882f0.woff +0 -0
- package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.0509ab09.woff2 +0 -0
- package/ux/js/app.0159ef6a.js +0 -1
- package/ux/js/chunk-2d0b90b4.92f1ea49.js +0 -8
- package/ux/js/chunk-461883cd.442efb25.js +0 -76
- package/ux/js/chunk-vendors.31d3ce30.js +0 -33
- /package/ux/js/{chunk-2d0de2f2.553bf976.js → chunk-2d0de2f2.2848649c.js} +0 -0
package/lib/swsInterface.js
CHANGED
|
@@ -9,60 +9,15 @@ const path = require('path');
|
|
|
9
9
|
const url = require('url');
|
|
10
10
|
const debug = require('debug')('sws:interface');
|
|
11
11
|
const promClient = require("prom-client");
|
|
12
|
-
const basicAuth = require("basic-auth");
|
|
13
|
-
const Cookies = require('cookies');
|
|
14
|
-
const uuidv1 = require('uuid/v1');
|
|
15
|
-
|
|
16
12
|
const swsSettings = require('./swssettings');
|
|
17
13
|
const swsUtil = require('./swsUtil');
|
|
18
14
|
const swsProcessor = require('./swsProcessor');
|
|
19
15
|
const swsEgress = require('./swsegress');
|
|
16
|
+
const swsAuth = require('./swsAuth');
|
|
20
17
|
const send = require('send');
|
|
21
18
|
const qs = require('qs');
|
|
22
|
-
|
|
23
19
|
const swsHapi = require('./swsHapi');
|
|
24
20
|
|
|
25
|
-
// API data processor
|
|
26
|
-
//var processor = null;
|
|
27
|
-
|
|
28
|
-
var uiMarkup = swsUtil.swsEmbeddedUIMarkup;
|
|
29
|
-
|
|
30
|
-
// Session IDs storage
|
|
31
|
-
var sessionIDs = {};
|
|
32
|
-
|
|
33
|
-
// Store / update session id
|
|
34
|
-
function storeSessionID(sid){
|
|
35
|
-
// PJS - Create sid value if not passed
|
|
36
|
-
sid = sid || uuidv1();
|
|
37
|
-
|
|
38
|
-
var tssec = Date.now() + swsSettings.sessionMaxAge*1000;
|
|
39
|
-
sessionIDs[sid] = tssec;
|
|
40
|
-
//debug('Session ID updated: %s=%d', sid,tssec);
|
|
41
|
-
|
|
42
|
-
// PJS - Send back sid value
|
|
43
|
-
return sid;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Remove Session ID
|
|
47
|
-
function removeSessionID(sid){
|
|
48
|
-
delete sessionIDs[sid];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// If authentication is enabled, executed periodically and expires old session IDs
|
|
52
|
-
function expireSessionIDs(){
|
|
53
|
-
var tssec = Date.now();
|
|
54
|
-
var expired = [];
|
|
55
|
-
for(var sid in sessionIDs){
|
|
56
|
-
if(sessionIDs[sid] < (tssec + 500)){
|
|
57
|
-
expired.push(sid);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
for(var i=0;i<expired.length;i++){
|
|
61
|
-
delete sessionIDs[expired[i]];
|
|
62
|
-
debug('Session ID expired: %s', expired[i]);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
21
|
// Request hanlder
|
|
67
22
|
function handleRequest(req, res){
|
|
68
23
|
try {
|
|
@@ -92,108 +47,12 @@ function handleResponseFinished(res){
|
|
|
92
47
|
}
|
|
93
48
|
}
|
|
94
49
|
|
|
95
|
-
function processAuth(req,res,useWWWAuth) {
|
|
96
|
-
|
|
97
|
-
return new Promise( function (resolve, reject) {
|
|
98
|
-
if( !swsSettings.authentication ){
|
|
99
|
-
return resolve(true);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if( swsSettings.customAuth ){
|
|
103
|
-
//return resolve(swsSettings.customAuth(req));
|
|
104
|
-
// PJS Custom
|
|
105
|
-
return resolve(swsSettings.customAuth(req, res, sessionIDs, storeSessionID));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
var cookies = new Cookies( req, res );
|
|
109
|
-
|
|
110
|
-
// Check session cookie
|
|
111
|
-
var sessionIdCookie = cookies.get('sws-session-id');
|
|
112
|
-
if( (sessionIdCookie !== undefined) && (sessionIdCookie !== null) ){
|
|
113
|
-
|
|
114
|
-
if( sessionIdCookie in sessionIDs ){
|
|
115
|
-
// renew it
|
|
116
|
-
//sessionIDs[sessionIdCookie] = Date.now();
|
|
117
|
-
storeSessionID(sessionIdCookie);
|
|
118
|
-
cookies.set('sws-session-id',sessionIdCookie,{path:swsSettings.basePath+swsSettings.uriPath,maxAge:swsSettings.sessionMaxAge*1000});
|
|
119
|
-
// Ok
|
|
120
|
-
req['sws-auth'] = true;
|
|
121
|
-
return resolve(true);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
var authInfo = basicAuth(req);
|
|
126
|
-
|
|
127
|
-
var authenticated = false;
|
|
128
|
-
var msg = 'Authentication required';
|
|
129
|
-
|
|
130
|
-
if( (authInfo !== undefined) && (authInfo!==null) && ('name' in authInfo) && ('pass' in authInfo)){
|
|
131
|
-
if(typeof swsSettings.onAuthenticate === 'function'){
|
|
132
|
-
|
|
133
|
-
Promise.resolve(swsSettings.onAuthenticate(req, authInfo.name, authInfo.pass)).then(function(onAuthResult) {
|
|
134
|
-
if( onAuthResult ){
|
|
135
|
-
|
|
136
|
-
authenticated = true;
|
|
137
|
-
|
|
138
|
-
// Session is only for stats requests
|
|
139
|
-
if(req.url.startsWith(swsSettings.pathStats)){
|
|
140
|
-
// Generate session id
|
|
141
|
-
var sessid = uuidv1();
|
|
142
|
-
storeSessionID(sessid);
|
|
143
|
-
// Set session cookie with expiration in 15 min
|
|
144
|
-
cookies.set('sws-session-id',sessid,{path:swsSettings.basePath+swsSettings.uriPath,maxAge:swsSettings.sessionMaxAge*1000});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
req['sws-auth'] = true;
|
|
148
|
-
return resolve(true);
|
|
149
|
-
|
|
150
|
-
}else{
|
|
151
|
-
msg = 'Invalid credentials';
|
|
152
|
-
res.statusCode = 403;
|
|
153
|
-
res.end(msg);
|
|
154
|
-
return resolve(false);
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
}else{
|
|
159
|
-
res.statusCode = 403;
|
|
160
|
-
res.end(msg);
|
|
161
|
-
return resolve(false);
|
|
162
|
-
}
|
|
163
|
-
}else{
|
|
164
|
-
res.statusCode = 403;
|
|
165
|
-
res.end(msg);
|
|
166
|
-
return resolve(false);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function processLogout(req,res){
|
|
174
|
-
|
|
175
|
-
var cookies = new Cookies( req, res );
|
|
176
|
-
|
|
177
|
-
// Check session cookie
|
|
178
|
-
var sessionIdCookie = cookies.get('sws-session-id');
|
|
179
|
-
if( (sessionIdCookie !== undefined) && (sessionIdCookie !== null) ){
|
|
180
|
-
if( sessionIdCookie in sessionIDs ){
|
|
181
|
-
removeSessionID(sessionIdCookie);
|
|
182
|
-
cookies.set('sws-session-id'); // deletes cookie
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
res.statusCode = 200;
|
|
187
|
-
res.end('Logged out');
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
50
|
// Process /swagger-stats/stats request
|
|
192
51
|
// Return statistics according to request parameters
|
|
193
52
|
// Query parameters (fields, path, method) defines which stat fields to return
|
|
194
53
|
function processGetStats(req,res){
|
|
195
54
|
|
|
196
|
-
processAuth(req,res).then(
|
|
55
|
+
swsAuth.processAuth(req,res).then((authResult) => {
|
|
197
56
|
if(!authResult){
|
|
198
57
|
return;
|
|
199
58
|
}
|
|
@@ -211,42 +70,39 @@ function processGetStats(req,res){
|
|
|
211
70
|
// Return all metrics for Prometheus
|
|
212
71
|
function processGetMetrics(req,res){
|
|
213
72
|
|
|
214
|
-
processAuth(req,res).then(
|
|
73
|
+
swsAuth.processAuth(req,res).then((authResult) => {
|
|
215
74
|
if(!authResult){
|
|
216
75
|
return;
|
|
217
76
|
}
|
|
218
77
|
res.statusCode = 200;
|
|
219
78
|
res.setHeader('Content-Type', 'text/plain');
|
|
220
|
-
|
|
79
|
+
// [sv2] This should handle both non-promise (prom-client 11,12) and promise results (prom-client 13+)
|
|
80
|
+
Promise.resolve(promClient.register.metrics()).then( (x) => {
|
|
81
|
+
res.end(x);
|
|
82
|
+
});
|
|
221
83
|
});
|
|
222
84
|
}
|
|
223
85
|
|
|
224
86
|
// Process /swagger-stats/ux request
|
|
225
87
|
function processGetUX(req,res){
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
fileName =
|
|
235
|
-
let qidx = fileName.indexOf('?');
|
|
236
|
-
if ( qidx != -1 ) {
|
|
237
|
-
fileName = fileName.substring(0, qidx);
|
|
238
|
-
}
|
|
88
|
+
// alwauys serve ux, it will perform auth as needed
|
|
89
|
+
let fileName = null;
|
|
90
|
+
if(req.url === swsSettings.pathUX){
|
|
91
|
+
fileName = 'index.html';
|
|
92
|
+
} else {
|
|
93
|
+
fileName = req.url.replace(swsSettings.pathUX, '');
|
|
94
|
+
let qidx = fileName.indexOf('?');
|
|
95
|
+
if ( qidx != -1 ) {
|
|
96
|
+
fileName = fileName.substring(0, qidx);
|
|
239
97
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
});
|
|
249
|
-
return;
|
|
98
|
+
}
|
|
99
|
+
let options = {
|
|
100
|
+
root: path.join(__dirname,'..','ux'),
|
|
101
|
+
dotfiles: 'deny'
|
|
102
|
+
// TODO Caching
|
|
103
|
+
};
|
|
104
|
+
res.setHeader('Content-Type', send.mime.lookup(path.basename(fileName)));
|
|
105
|
+
send(req, fileName, options).pipe(res);
|
|
250
106
|
}
|
|
251
107
|
|
|
252
108
|
// Express Middleware
|
|
@@ -258,9 +114,11 @@ function expressMiddleware(options) {
|
|
|
258
114
|
// Init probes
|
|
259
115
|
swsEgress.init();
|
|
260
116
|
|
|
117
|
+
/*
|
|
261
118
|
if( swsSettings.authentication ){
|
|
262
119
|
setInterval(expireSessionIDs,500);
|
|
263
120
|
}
|
|
121
|
+
*/
|
|
264
122
|
|
|
265
123
|
swsProcessor.init();
|
|
266
124
|
|
|
@@ -272,30 +130,20 @@ function expressMiddleware(options) {
|
|
|
272
130
|
|
|
273
131
|
// Respond to requests handled by swagger-stats
|
|
274
132
|
// swagger-stats requests will not be counted in statistics
|
|
275
|
-
if(req.url
|
|
133
|
+
if(req.url === swsSettings.uriPath ){
|
|
134
|
+
if(('serverName' in req) && (req.serverName === 'restify') ){
|
|
135
|
+
res.redirect(swsSettings.uriPath + '/', next);
|
|
136
|
+
} else {
|
|
137
|
+
res.redirect(swsSettings.uriPath + '/');
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
else if(req.url.startsWith(swsSettings.pathStats)) {
|
|
276
142
|
return processGetStats(req, res);
|
|
277
143
|
}else if(req.url.startsWith(swsSettings.pathMetrics)){
|
|
278
144
|
return processGetMetrics(req,res);
|
|
279
145
|
}else if(req.url.startsWith(swsSettings.pathLogout)){
|
|
280
|
-
processLogout(req,res);
|
|
281
|
-
return;
|
|
282
|
-
}else if(req.url.startsWith(swsSettings.pathUI) ){
|
|
283
|
-
res.statusCode = 200;
|
|
284
|
-
res.setHeader('Content-Type', 'text/html');
|
|
285
|
-
res.end(uiMarkup);
|
|
286
|
-
return;
|
|
287
|
-
}else if(req.url.startsWith(swsSettings.pathDist)) {
|
|
288
|
-
var fileName = req.url.replace(swsSettings.pathDist+'/','');
|
|
289
|
-
var qidx = fileName.indexOf('?');
|
|
290
|
-
if(qidx!=-1) fileName = fileName.substring(0,qidx);
|
|
291
|
-
|
|
292
|
-
var options = {
|
|
293
|
-
root: path.join(__dirname,'..','dist'),
|
|
294
|
-
dotfiles: 'deny'
|
|
295
|
-
// TODO Caching
|
|
296
|
-
};
|
|
297
|
-
res.setHeader('Content-Type', send.mime.lookup(path.basename(fileName)));
|
|
298
|
-
send(req, fileName, options).pipe(res);
|
|
146
|
+
swsAuth.processLogout(req,res);
|
|
299
147
|
return;
|
|
300
148
|
} else if(req.url.startsWith(swsSettings.pathUX)) {
|
|
301
149
|
return processGetUX(req, res);
|
|
@@ -389,5 +237,8 @@ module.exports = {
|
|
|
389
237
|
// Add one (or more) OpenAPI PathSpecs
|
|
390
238
|
addPathSpecs(pathSpecs) {
|
|
391
239
|
swsProcessor.addPathSpecs(pathSpecs);
|
|
392
|
-
}
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// Expose the SwsAuth object for the custom authentication function
|
|
243
|
+
swsAuth: swsAuth
|
|
393
244
|
};
|
package/lib/swsProcessor.js
CHANGED
|
@@ -234,7 +234,12 @@ class SwsProcessor {
|
|
|
234
234
|
|
|
235
235
|
if (req.hasOwnProperty("body")) {
|
|
236
236
|
rrr.http.request.body = Object.assign({}, req.body);
|
|
237
|
-
swsUtil.swsStringRecursive(rrr.http.request.body, req.body);
|
|
237
|
+
//swsUtil.swsStringRecursive(rrr.http.request.body, req.body);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// PJS-1116: Add response body to record if it's there
|
|
241
|
+
if (res.hasOwnProperty("body")) {
|
|
242
|
+
rrr.http.response.body = res.body;
|
|
238
243
|
}
|
|
239
244
|
|
|
240
245
|
return rrr;
|
package/lib/swsReqResStats.js
CHANGED
|
@@ -54,7 +54,7 @@ SwsReqResStats.prototype.countResponse = function(code,codeclass,duration,clengt
|
|
|
54
54
|
this.avg_res_clength = Math.floor(this.total_res_clength / this.responses);
|
|
55
55
|
|
|
56
56
|
// Apdex: https://en.wikipedia.org/wiki/Apdex
|
|
57
|
-
if( codeclass
|
|
57
|
+
if( codeclass === "success" || codeclass === "redirect" ) {
|
|
58
58
|
if (duration <= this.apdex_threshold) {
|
|
59
59
|
this.apdex_satisfied++;
|
|
60
60
|
} else if (duration <= (this.apdex_threshold * 4)) {
|
package/lib/swsUtil.js
CHANGED
|
@@ -100,6 +100,12 @@ module.exports.supportedOptions = {
|
|
|
100
100
|
// Password for Elasticsearch, if anonymous user is disbaled . Default is empty (disabled)
|
|
101
101
|
elasticsearchPassword : "elasticsearchPassword",
|
|
102
102
|
|
|
103
|
+
// Elasticsearch key for SSL connection
|
|
104
|
+
elasticsearchKey : "elasticsearchSSLKey",
|
|
105
|
+
|
|
106
|
+
// Elasticsearch certificat for SSL connection
|
|
107
|
+
elasticsearchCert : "elasticsearchSSLCert",
|
|
108
|
+
|
|
103
109
|
// Set to true to track only requests defined in swagger spec. Default false.
|
|
104
110
|
swaggerOnly : "swaggerOnly"
|
|
105
111
|
|
|
@@ -185,7 +191,7 @@ module.exports.swsStringValue = function (val) {
|
|
|
185
191
|
module.exports.swsStringRecursive = function (output, val) {
|
|
186
192
|
if (typeof val === "object" && !Array.isArray(val)) {
|
|
187
193
|
for (var key in val) {
|
|
188
|
-
output[key] = this.swsStringValue(val);
|
|
194
|
+
output[key] = this.swsStringValue(val[key]);
|
|
189
195
|
}
|
|
190
196
|
} else {
|
|
191
197
|
output = this.swsStringValue(val);
|
|
@@ -230,23 +236,3 @@ module.exports.swsCPUUsagePct = function(starthrtime, startusage) {
|
|
|
230
236
|
return cpuPercent;
|
|
231
237
|
};
|
|
232
238
|
|
|
233
|
-
module.exports.swsEmbeddedUIMarkup = '<!DOCTYPE html><html><head><title>Profound API Dashboard</title><link href="dist/css/sws.min.css" rel="stylesheet"><link rel="icon" type="image/png" href="dist/images/favicon.png"/> \
|
|
234
|
-
<script>\
|
|
235
|
-
window.parent.showSwaggerStatsRoute = function(route, delayLoadTime) {\
|
|
236
|
-
delayLoadTime = parseInt(delayLoadTime,10) || 0;\
|
|
237
|
-
document.body.style.display = "none";\
|
|
238
|
-
setTimeout(function(){\
|
|
239
|
-
window.setActivePageIdHash("#&routeKey=" + route["routeKey"] + "&modFile=" + route["modfile"]);\
|
|
240
|
-
document.body.style.display = "";\
|
|
241
|
-
}, (delayLoadTime*1000));\
|
|
242
|
-
}\
|
|
243
|
-
</script>\
|
|
244
|
-
</head>\
|
|
245
|
-
<body>\
|
|
246
|
-
<div id="SWSUI"></div>\
|
|
247
|
-
<script src="dist/js/sws.min.js"></script>\
|
|
248
|
-
<script>\
|
|
249
|
-
$(document).ready(function(){$("#SWSUI").swaggerstatsui({});});\
|
|
250
|
-
</script>\
|
|
251
|
-
</body>\
|
|
252
|
-
</html>';
|
package/lib/swssettings.js
CHANGED
|
@@ -77,7 +77,7 @@ class SwsSettings {
|
|
|
77
77
|
// Enable Basic authentication: true or false. Default false.
|
|
78
78
|
// Basic & custom authentication are supported
|
|
79
79
|
this.authentication = false;
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
// Enable Your own authentication: a function that takes
|
|
82
82
|
// customAuth(req)
|
|
83
83
|
// - req - request
|
|
@@ -113,6 +113,12 @@ class SwsSettings {
|
|
|
113
113
|
// Password for Elasticsearch, if anonymous user is disbaled . Default is empty (disabled)
|
|
114
114
|
this.elasticsearchPassword = null;
|
|
115
115
|
|
|
116
|
+
// Elasticsearch key for SSL connection
|
|
117
|
+
this.elasticsearchKey = null;
|
|
118
|
+
|
|
119
|
+
// Elasticsearch certificat for SSL connection
|
|
120
|
+
this.elasticsearchCert = null;
|
|
121
|
+
|
|
116
122
|
// Set to true to track only requests defined in swagger spec. Default false.
|
|
117
123
|
this.swaggerOnly = false;
|
|
118
124
|
|
|
@@ -160,7 +166,7 @@ class SwsSettings {
|
|
|
160
166
|
|
|
161
167
|
this.pathUI = this.uriPath+'/ui';
|
|
162
168
|
this.pathDist = this.uriPath+'/dist';
|
|
163
|
-
this.pathUX = this.uriPath+'/
|
|
169
|
+
this.pathUX = this.uriPath+'/';
|
|
164
170
|
this.pathStats = this.uriPath+'/stats';
|
|
165
171
|
this.pathMetrics = this.uriPath+'/metrics';
|
|
166
172
|
this.pathLogout = this.uriPath+'/logout';
|
package/package.json
CHANGED
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "profoundjs-swagger-stats",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "API Telemetry and APM. Trace API calls and Monitor API performance, health and usage statistics in Node.js Microservices, based on express routes and Swagger (Open API) specification",
|
|
4
5
|
"main": "lib/index.js",
|
|
5
|
-
"contributors": [],
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"hapitestapp": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/hapitestapp node examples/hapijstest/hapijstest.js",
|
|
14
|
-
"fastifytestapp": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/fastifytestapp node examples/fastify/fasifytest.js",
|
|
15
|
-
"restifytestapp": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/restifytestapp node examples/restify/restifytest.js",
|
|
7
|
+
"build": "npm run copy:ux",
|
|
8
|
+
"copy:ux": "ncp node_modules/profoundjs-swagger-stats-ux/dist ux",
|
|
9
|
+
"start": "node examples/testapp/testapp.js",
|
|
10
|
+
"hapitestapp": "cross-env SWS_AUTHTEST_MAXAGE=2 nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/hapitestapp node examples/hapijstest/hapijstest.js",
|
|
11
|
+
"fastifytestapp": "cross-env SWS_AUTHTEST_MAXAGE=2 nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/fastifytestapp node examples/fastify/fasifytest.js",
|
|
12
|
+
"restifytestapp": "cross-env SWS_AUTHTEST_MAXAGE=2 nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/restifytestapp node examples/restify/restifytest.js",
|
|
16
13
|
"testappstop": "mocha --delay --exit test/stoptestapp.js",
|
|
17
14
|
"delay1s": "mocha --delay --exit test/delay.js",
|
|
18
|
-
"test
|
|
19
|
-
"
|
|
20
|
-
"test": "npm run testExpress && npm run testHapi && npm run testFastify && npm run coverage-report",
|
|
21
|
-
"testExpress": "npm run cov000 && npm run cov010 && npm run cov100 && npm run cov200 && npm run cov300 && npm run cov400 && npm run cov500 && npm run karma-ci",
|
|
15
|
+
"test": "npm run testExpress && npm run testHapi && npm run testFastify && npm run testRestify && npm run coverage-report",
|
|
16
|
+
"testExpress": "npm run cov000 && npm run cov010 && npm run cov100 && npm run cov200 && npm run cov300 && npm run cov400 && npm run cov500",
|
|
22
17
|
"cov000": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/000 mocha --delay --exit test/000_baseline.js",
|
|
23
18
|
"cov010": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/010 mocha --delay --exit test/010_swsapistats.js",
|
|
24
19
|
"cov100": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/100 mocha --delay --exit test/100_method.js",
|
|
@@ -27,7 +22,7 @@
|
|
|
27
22
|
"cov400": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/400 mocha --delay --exit test/400_auth.js",
|
|
28
23
|
"cov500": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/500 mocha --delay --exit test/500_elastic.js",
|
|
29
24
|
"testHapi": "concurrently -k --success first \"npm run hapitestapp\" \"npm run covHapi\"",
|
|
30
|
-
"covHapi": "npm run delay1s && npm run cov000h && npm run cov100h && npm run cov200h && npm run cov300h && npm run cov500h && npm run testappstop",
|
|
25
|
+
"covHapi": "npm run delay1s && npm run cov000h && npm run cov100h && npm run cov200h && npm run cov300h && npm run cov400h && npm run cov500h && npm run testappstop",
|
|
31
26
|
"cov000h": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/000h mocha --delay --exit test/000_baseline.js",
|
|
32
27
|
"cov100h": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/100h mocha --delay --exit test/100_method.js",
|
|
33
28
|
"cov200h": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/200h mocha --delay --exit test/200_apicore.js",
|
|
@@ -50,90 +45,94 @@
|
|
|
50
45
|
"cov300r": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/300f mocha --delay --exit test/300_timeline.js",
|
|
51
46
|
"cov400r": "nyc --reporter=lcov --reporter=html --reporter=json --reporter=text --report-dir=coverage/400f mocha --delay --exit test/400_auth.js",
|
|
52
47
|
"coverage-report": "node_modules/.bin/istanbul report --root ./coverage --dir ./coverage-report lcov",
|
|
53
|
-
"specstest": "mocha test/specstest/swaggerspecstest.js"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
"
|
|
48
|
+
"specstest": "mocha test/specstest/swaggerspecstest.js"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"api",
|
|
52
|
+
"observability",
|
|
53
|
+
"telemetry",
|
|
54
|
+
"node",
|
|
55
|
+
"express",
|
|
56
|
+
"koa",
|
|
57
|
+
"hapi",
|
|
58
|
+
"fastify",
|
|
59
|
+
"rest",
|
|
60
|
+
"statistics",
|
|
61
|
+
"monitoring",
|
|
62
|
+
"alerting",
|
|
63
|
+
"swagger",
|
|
64
|
+
"openapi",
|
|
65
|
+
"schema",
|
|
66
|
+
"prometheus",
|
|
67
|
+
"metrics",
|
|
68
|
+
"elasticsearch",
|
|
69
|
+
"kibana",
|
|
70
|
+
"grafana"
|
|
71
|
+
],
|
|
72
|
+
"files": [
|
|
73
|
+
"dashboards/**/*",
|
|
74
|
+
"examples/**/*",
|
|
75
|
+
"lib/**/*",
|
|
76
|
+
"schema/**/*",
|
|
77
|
+
"scripts/**/*",
|
|
78
|
+
"ux/**/*",
|
|
79
|
+
"package.json",
|
|
80
|
+
"README.md",
|
|
81
|
+
"CHANGELOG.md",
|
|
82
|
+
"CONTRIBUTING.md",
|
|
83
|
+
"LICENSE"
|
|
84
|
+
],
|
|
85
|
+
"repository": {
|
|
86
|
+
"type": "git",
|
|
87
|
+
"url": "https://github.com/slanatech/swagger-stats"
|
|
88
|
+
},
|
|
89
|
+
"author": "https://github.com/sv2",
|
|
90
|
+
"homepage": "http://swaggerstats.io",
|
|
91
|
+
"bugs": {
|
|
92
|
+
"url": "https://github.com/slanatech/swagger-stats/issues",
|
|
93
|
+
"email": "sv2@slana.tech"
|
|
58
94
|
},
|
|
59
95
|
"license": "MIT",
|
|
60
96
|
"dependencies": {
|
|
61
97
|
"basic-auth": "^2.0.1",
|
|
62
98
|
"cookies": "^0.8.0",
|
|
63
|
-
"debug": "^4.
|
|
64
|
-
"moment": "^2.
|
|
65
|
-
"path-to-regexp": "^6.1
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
|
|
99
|
+
"debug": "^4.3.4",
|
|
100
|
+
"moment": "^2.29.4",
|
|
101
|
+
"path-to-regexp": "^6.2.1",
|
|
102
|
+
"qs": "^6.11.2",
|
|
103
|
+
"send": "^0.18.0",
|
|
104
|
+
"uuid": "^9.0.0",
|
|
105
|
+
"axios": "^1.4.0"
|
|
106
|
+
},
|
|
107
|
+
"peerDependencies": {
|
|
108
|
+
"prom-client": ">= 10 <= 14"
|
|
71
109
|
},
|
|
72
110
|
"devDependencies": {
|
|
73
|
-
"@hapi/hapi": "^
|
|
74
|
-
"@hapi/inert": "^
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"css-loader": "^3.6.0",
|
|
86
|
-
"cuid": "^1.3.8",
|
|
87
|
-
"d3": "^4.12.0",
|
|
88
|
-
"d3-horizon-chart": "0.0.6",
|
|
89
|
-
"datatables": "^1.10.13",
|
|
90
|
-
"del": "^5.1.0",
|
|
91
|
-
"express": "^4.16.2",
|
|
92
|
-
"fastify": "^2.8.0",
|
|
93
|
-
"file-loader": "^0.11.1",
|
|
94
|
-
"font-awesome": "^4.7.0",
|
|
95
|
-
"gulp": "^4.0.2",
|
|
96
|
-
"gulp-clean-css": "^4.2.0",
|
|
97
|
-
"gulp-concat": "^2.6.1",
|
|
98
|
-
"gulp-concat-css": "^3.1.0",
|
|
99
|
-
"gulp-css-base64": "^1.3.4",
|
|
100
|
-
"gulp-minify": "^3.1.0",
|
|
101
|
-
"gulp-pack": "^0.0.15",
|
|
102
|
-
"gulp-publish": "^0.8.7",
|
|
103
|
-
"gulp-rename": "^2.0.0",
|
|
104
|
-
"gulp-sourcemaps": "^2.6.5",
|
|
105
|
-
"gulp-uglify": "^3.0.2",
|
|
106
|
-
"highlightjs": "^9.10.0",
|
|
111
|
+
"@hapi/hapi": "^21.3.2",
|
|
112
|
+
"@hapi/inert": "^7.1.0",
|
|
113
|
+
"body-parser": "^1.20.2",
|
|
114
|
+
"chai": "^4.3.7",
|
|
115
|
+
"chokidar": "^3.5.3",
|
|
116
|
+
"concurrently": "^8.0.1",
|
|
117
|
+
"coveralls": "^3.1.1",
|
|
118
|
+
"cross-env": "^7.0.3",
|
|
119
|
+
"cuid": "^3.0.0",
|
|
120
|
+
"express": "^4.18.2",
|
|
121
|
+
"fastify": "^4.17.0",
|
|
122
|
+
"fastify-express": "^0.4.0",
|
|
107
123
|
"istanbul": "^0.4.5",
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"karma": "^5.1.0",
|
|
111
|
-
"karma-chai": "^0.1.0",
|
|
112
|
-
"karma-chrome-launcher": "^2.2.0",
|
|
113
|
-
"karma-cli": "^1.0.1",
|
|
114
|
-
"karma-coverage": "^2.0.2",
|
|
115
|
-
"karma-firefox-launcher": "^1.1.0",
|
|
116
|
-
"karma-fixture": "^0.2.6",
|
|
117
|
-
"karma-html2js-preprocessor": "^1.1.0",
|
|
118
|
-
"karma-mocha": "^2.0.1",
|
|
119
|
-
"karma-mocha-reporter": "^2.2.5",
|
|
120
|
-
"karma-phantomjs-launcher": "^1.0.4",
|
|
121
|
-
"karma-should": "^1.0.0",
|
|
122
|
-
"mocha": "^8.0.1",
|
|
123
|
-
"mocha-jscs": "^5.0.1",
|
|
124
|
-
"mocha-jshint": "^2.3.1",
|
|
124
|
+
"mocha": "^10.2.0",
|
|
125
|
+
"ncp": "^2.0.0",
|
|
125
126
|
"nyc": "^15.1.0",
|
|
126
|
-
"
|
|
127
|
-
"postcss-loader": "^2.0.9",
|
|
127
|
+
"prom-client": "^14.2.0",
|
|
128
128
|
"q": "^1.5.1",
|
|
129
|
-
"restify": "^
|
|
130
|
-
"serve-favicon": "^2.
|
|
131
|
-
"serve-static": "^1.
|
|
132
|
-
"should": "^
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"swagger-
|
|
136
|
-
"
|
|
137
|
-
"swagger-stats-ux": "^0.95.22"
|
|
129
|
+
"restify": "^11.1.0",
|
|
130
|
+
"serve-favicon": "^2.5.0",
|
|
131
|
+
"serve-static": "^1.15.0",
|
|
132
|
+
"should": "^13.2.3",
|
|
133
|
+
"supertest": "^6.3.3",
|
|
134
|
+
"swagger-parser": "^10.0.3",
|
|
135
|
+
"profoundjs-swagger-stats-ux": "^1.0.0",
|
|
136
|
+
"request": "^2.88.2"
|
|
138
137
|
}
|
|
139
138
|
}
|