mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-03 22:30:58 +01:00
Plugin metrics (#7626)
* feat: add enable/disable checkbox for plugin usage * feat: submit plugin data to packages.nodebb.org only submit in production mode submit once every 24 hours dont submit for plugins that have "private": true in plugin.json enabled on new installs disabled on existing installs * fix: hash not working after first send fix statusCode * fix: remove url * feat: show compatibilty * feat: add install question for submit plugin usage
This commit is contained in:
committed by
GitHub
parent
3f4f8aface
commit
5fa5e999f8
@@ -122,5 +122,6 @@
|
||||
"eventLoopInterval": 500,
|
||||
"onlineCutoff": 30,
|
||||
"timeagoCutoff": 30,
|
||||
"categoryWatchState": "watching"
|
||||
"categoryWatchState": "watching",
|
||||
"submitPluginUsage": 1
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
"plugin-search": "Plugin Search",
|
||||
"plugin-search-placeholder": "Search for plugin...",
|
||||
"submit-anonymous-usage": "Submit anonymous plugin usage data.",
|
||||
"reorder-plugins": "Re-order Plugins",
|
||||
"order-active": "Order Active Plugins",
|
||||
"dev-interested": "Interested in writing plugins for NodeBB?",
|
||||
@@ -29,6 +30,8 @@
|
||||
"plugin-item.more-info": "For more information:",
|
||||
"plugin-item.unknown": "Unknown",
|
||||
"plugin-item.unknown-explanation": "The state of this plugin could not be determined, possibly due to a misconfiguration error.",
|
||||
"plugin-item.compatible": "This plugin works on NodeBB %1",
|
||||
"plugin-item.not-compatible": "This plugin has no compatibility data, make sure it works before installing on your production environment.",
|
||||
|
||||
"alert.enabled": "Plugin Enabled",
|
||||
"alert.disabled": "Plugin Disabled",
|
||||
|
||||
@@ -150,6 +150,16 @@ define('admin/extend/plugins', ['jqueryui', 'translator', 'benchpress'], functio
|
||||
});
|
||||
});
|
||||
|
||||
$('#plugin-submit-usage').on('click', function () {
|
||||
socket.emit('admin.config.setMultiple', {
|
||||
submitPluginUsage: $(this).prop('checked') ? '1' : '0',
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#plugin-order').on('click', function () {
|
||||
$('#order-active-plugins-modal').modal('show');
|
||||
socket.emit('admin.plugins.getActive', function (err, activePlugins) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
var nconf = require('nconf');
|
||||
var plugins = require('../../plugins');
|
||||
var meta = require('../../meta');
|
||||
|
||||
var pluginsController = module.exports;
|
||||
|
||||
@@ -57,6 +59,8 @@ pluginsController.get = function (req, res, next) {
|
||||
incompatible: payload.all.filter(function (plugin) {
|
||||
return !compatiblePkgNames.includes(plugin.name);
|
||||
}),
|
||||
submitPluginUsage: meta.config.submitPluginUsage,
|
||||
version: nconf.get('version'),
|
||||
});
|
||||
},
|
||||
], next);
|
||||
|
||||
@@ -28,6 +28,11 @@ questions.main = [
|
||||
description: 'Please enter a NodeBB secret',
|
||||
default: nconf.get('secret') || utils.generateUUID(),
|
||||
},
|
||||
{
|
||||
name: 'submitPluginUsage',
|
||||
description: 'Would you like to submit anonymous plugin usage to nbbpm?',
|
||||
default: 'yes',
|
||||
},
|
||||
{
|
||||
name: 'database',
|
||||
description: 'Which database to use',
|
||||
@@ -198,6 +203,14 @@ function completeConfigSetup(config, next) {
|
||||
// ref: https://github.com/indexzero/nconf/issues/300
|
||||
delete config.type;
|
||||
|
||||
var meta = require('./meta');
|
||||
meta.configs.set('submitPluginUsage', config.submitPluginUsage === 'yes' ? 1 : 0, function (err) {
|
||||
next(err, config);
|
||||
});
|
||||
},
|
||||
function (config, next) {
|
||||
delete config.submitPluginUsage;
|
||||
|
||||
install.save(config, next);
|
||||
},
|
||||
], next);
|
||||
|
||||
@@ -15,6 +15,7 @@ var Plugins = module.exports;
|
||||
require('./install')(Plugins);
|
||||
require('./load')(Plugins);
|
||||
require('./hooks')(Plugins);
|
||||
require('./usage')(Plugins);
|
||||
Plugins.data = require('./data');
|
||||
|
||||
Plugins.getPluginPaths = Plugins.data.getPluginPaths;
|
||||
@@ -33,6 +34,7 @@ Plugins.libraryPaths = [];
|
||||
Plugins.versionWarning = [];
|
||||
Plugins.soundpacks = [];
|
||||
Plugins.languageData = {};
|
||||
Plugins.loadedPlugins = [];
|
||||
|
||||
Plugins.initialized = false;
|
||||
|
||||
@@ -105,6 +107,7 @@ Plugins.reload = function (callback) {
|
||||
Plugins.clientScripts.length = 0;
|
||||
Plugins.acpScripts.length = 0;
|
||||
Plugins.libraryPaths.length = 0;
|
||||
Plugins.loadedPlugins.length = 0;
|
||||
|
||||
async.waterfall([
|
||||
Plugins.getPluginPaths,
|
||||
|
||||
@@ -150,8 +150,16 @@ module.exports = function (Plugins) {
|
||||
},
|
||||
], function (err) {
|
||||
if (err) {
|
||||
winston.error(err.stack);
|
||||
winston.verbose('[plugins] Could not load plugin : ' + pluginData.id);
|
||||
return callback(err);
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (!pluginData.private) {
|
||||
Plugins.loadedPlugins.push({
|
||||
id: pluginData.id,
|
||||
version: pluginData.version,
|
||||
});
|
||||
}
|
||||
|
||||
winston.verbose('[plugins] Loaded plugin: ' + pluginData.id);
|
||||
@@ -196,9 +204,8 @@ module.exports = function (Plugins) {
|
||||
callback();
|
||||
}
|
||||
} catch (err) {
|
||||
winston.error(err.stack);
|
||||
winston.warn('[plugins] Unable to parse library for: ' + pluginData.id);
|
||||
callback();
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
43
src/plugins/usage.js
Normal file
43
src/plugins/usage.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const nconf = require('nconf');
|
||||
const request = require('request');
|
||||
const winston = require('winston');
|
||||
const crypto = require('crypto');
|
||||
const cronJob = require('cron').CronJob;
|
||||
|
||||
const pkg = require('../../package.json');
|
||||
|
||||
const meta = require('../meta');
|
||||
|
||||
module.exports = function (Plugins) {
|
||||
Plugins.startJobs = function () {
|
||||
new cronJob('0 0 0 * * *', function () {
|
||||
Plugins.submitUsageData();
|
||||
}, null, true);
|
||||
};
|
||||
|
||||
Plugins.submitUsageData = function () {
|
||||
if (!meta.config.submitPluginUsage || !Plugins.loadedPlugins.length || global.env !== 'production') {
|
||||
return;
|
||||
}
|
||||
|
||||
const hash = crypto.createHash('sha256');
|
||||
hash.update(nconf.get('url'));
|
||||
request.post((nconf.get('registry') || 'https://packages.nodebb.org') + '/api/v1/plugin/usage', {
|
||||
form: {
|
||||
id: hash.digest('hex'),
|
||||
version: pkg.version,
|
||||
plugins: Plugins.loadedPlugins,
|
||||
},
|
||||
timeout: 5000,
|
||||
}, function (err, res, body) {
|
||||
if (err) {
|
||||
return winston.error(err);
|
||||
}
|
||||
if (res.statusCode !== 200) {
|
||||
winston.error('[plugins.submitUsageData] received ' + res.statusCode + ' ' + body);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -50,6 +50,7 @@ start.start = function () {
|
||||
if (nconf.get('runJobs')) {
|
||||
require('./notifications').startJobs();
|
||||
require('./user').startJobs();
|
||||
require('./plugins').startJobs();
|
||||
}
|
||||
|
||||
webserver.listen(next);
|
||||
|
||||
11
src/upgrades/1.12.3/disable_plugin_metrics.js
Normal file
11
src/upgrades/1.12.3/disable_plugin_metrics.js
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Disable plugin metrics for existing installs',
|
||||
timestamp: Date.UTC(2019, 4, 21),
|
||||
method: async function (callback) {
|
||||
db.setObjectField('config', 'submitPluginUsage', 0, callback);
|
||||
},
|
||||
};
|
||||
@@ -28,6 +28,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="checkbox">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input id="plugin-submit-usage" class="mdl-switch__input" type="checkbox" data-field="submitPluginUsage" <!-- IF submitPluginUsage -->checked<!-- ENDIF submitPluginUsage -->/>
|
||||
<span class="mdl-switch__label">[[admin/extend/plugins:submit-anonymous-usage]]</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">[[admin/extend/plugins:reorder-plugins]]</div>
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -11,6 +11,13 @@
|
||||
<!-- ENDIF download.description -->
|
||||
|
||||
<small>[[admin/extend/plugins:plugin-item.latest]] <strong class="latestVersion">{download.latest}</strong></small>
|
||||
<p>
|
||||
<!-- IF installed.isCompatible -->
|
||||
<i class="fa fa-check text-success"></i> [[admin/extend/plugins:plugin-item.compatible, {version}]]
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-question text-warning"></i> [[admin/extend/plugins:plugin-item.not-compatible]]
|
||||
<!-- ENDIF -->
|
||||
</p>
|
||||
|
||||
<!-- IF download.url -->
|
||||
<p>[[admin/extend/plugins:plugin-item.more-info]] <a target="_blank" href="{download.url}">{download.url}</a></p>
|
||||
|
||||
@@ -24,9 +24,18 @@
|
||||
<!-- ENDIF installed.description -->
|
||||
<!-- IF installed.outdated --><i class="fa fa-exclamation-triangle text-danger"></i> <!-- ENDIF installed.outdated -->
|
||||
<small>[[admin/extend/plugins:plugin-item.installed]] <strong class="currentVersion">{installed.version}</strong> | [[admin/extend/plugins:plugin-item.latest]] <strong class="latestVersion">{installed.latest}</strong></small>
|
||||
|
||||
<!-- IF installed.outdated -->
|
||||
<button data-action="upgrade" class="btn btn-success btn-xs"><i class="fa fa-download"></i> [[admin/extend/plugins:plugin-item.upgrade]]</button>
|
||||
<button data-action="upgrade" class="btn btn-success btn-xs"><i class="fa fa-download"></i> [[admin/extend/plugins:plugin-item.upgrade]]</button>
|
||||
<p>
|
||||
<!-- IF installed.isCompatible -->
|
||||
<i class="fa fa-check text-success"></i> [[admin/extend/plugins:plugin-item.compatible, {version}]]
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-question text-warning"></i> [[admin/extend/plugins:plugin-item.not-compatible]]
|
||||
<!-- ENDIF -->
|
||||
</p>
|
||||
<!-- ENDIF installed.outdated -->
|
||||
|
||||
<!-- IF installed.url -->
|
||||
<p>[[admin/extend/plugins:plugin-item.more-info]] <a target="_blank" href="{installed.url}">{installed.url}</a></p>
|
||||
<!-- ENDIF installed.url -->
|
||||
|
||||
Reference in New Issue
Block a user