Slack messaging #169

Merged
bones7242 merged 11 commits from slack-messaging into master 2017-09-21 21:11:32 +02:00
13 changed files with 81 additions and 34 deletions

View file

@ -3,7 +3,10 @@
"LbryClaimAddress": "LBRY_CLAIM_ADDRESS" "LbryClaimAddress": "LBRY_CLAIM_ADDRESS"
}, },
"Database": { "Database": {
"username": "MYSQL_USERNAME", "Username": "MYSQL_USERNAME",
"password": "MYSQL_PASSWORD" "Password": "MYSQL_PASSWORD"
},
"Logging": {
"SlackWebHook": "SLACK_WEB_HOOK"
} }
} }

View file

@ -6,9 +6,9 @@
"GoogleId": "none" "GoogleId": "none"
}, },
"Database": { "Database": {
"database": "lbry", "Database": "lbry",
"username": "none", "Username": "none",
"password": "none" "Password": "none"
}, },
"Logging": { "Logging": {
"LogLevel": "none" "LogLevel": "none"

View file

@ -9,6 +9,8 @@
"MySqlConnectionUri": "none" "MySqlConnectionUri": "none"
}, },
"Logging": { "Logging": {
"LogLevel": "silly" "LogLevel": "silly",
"SlackErrorChannel": "#staging_speech-errors",
"SlackInfoChannel": "none"
} }
} }

View file

@ -12,6 +12,10 @@ module.exports = (winston, logLevel) => {
], ],
}); });
// winston.on('error', (err) => {
// console.log('unhandled exception in winston >> ', err);
// });
winston.error('Level 0'); winston.error('Level 0');
winston.warn('Level 1'); winston.warn('Level 1');
winston.info('Level 2'); winston.info('Level 2');

View file

@ -9,6 +9,8 @@
"MySqlConnectionUri": "none" "MySqlConnectionUri": "none"
}, },
"Logging": { "Logging": {
"LogLevel": "verbose" "LogLevel": "verbose",
"SlackErrorChannel": "#speech-errors",
"SlackInfoChannel": "#speech-logs"
} }
} }

View file

@ -0,0 +1,27 @@
const config = require('config');
const SLACK_WEB_HOOK = config.get('Logging.SlackWebHook');
const SLACK_ERROR_CHANNEL = config.get('Logging.SlackErrorChannel');
const SLACK_INFO_CHANNEL = config.get('Logging.SlackInfoChannel');
const winstonSlackWebHook = require('winston-slack-webhook').SlackWebHook;
module.exports = (winston) => {
// add a transport for errors
winston.add(winstonSlackWebHook, {
name : 'slack-errors-transport',
level : 'error',
webhookUrl: SLACK_WEB_HOOK,
channel : SLACK_ERROR_CHANNEL,
username : 'spee.ch',
iconEmoji : ':face_with_head_bandage:',
});
winston.add(winstonSlackWebHook, {
name : 'slack-info-transport',
level : 'info',
webhookUrl: SLACK_WEB_HOOK,
channel : SLACK_INFO_CHANNEL,
username : 'spee.ch',
iconEmoji : ':nerd_face:',
});
// send test message
winston.error('Testing slack logging... slack logging is online.');
};

View file

@ -35,7 +35,7 @@ module.exports = {
}); });
}) })
.catch(error => { .catch(error => {
logger.error('Sequelize error', error); logger.error('Sequelize error >>', error);
}); });
}, },
sendGoogleAnalytics (action, headers, ip, originalUrl) { sendGoogleAnalytics (action, headers, ip, originalUrl) {
@ -137,7 +137,7 @@ module.exports = {
resolve({ records: resultHashTable, totals: { totalServe, totalPublish, totalShow, totalCount, totalSuccess, totalFailure }, percentSuccess }); resolve({ records: resultHashTable, totals: { totalServe, totalPublish, totalShow, totalCount, totalSuccess, totalFailure }, percentSuccess });
}) })
.catch(error => { .catch(error => {
logger.error('sequelize error', error); logger.error('sequelize error >>', error);
reject(error); reject(error);
}); });
}); });
@ -161,7 +161,7 @@ module.exports = {
resolve(results); resolve(results);
}) })
.catch(error => { .catch(error => {
logger.error('sequelize error', error); logger.error('sequelize error >>', error);
reject(error); reject(error);
}); });
}); });

View file

@ -1,32 +1,38 @@
const logger = require('winston'); const logger = require('winston');
const { postToStats } = require('../controllers/statsController.js'); const { postToStats } = require('../controllers/statsController.js');
function useObjectPropertiesIfNoKeys (err) {
if (Object.keys(err).length === 0) {
let newErrorObject = {};
Object.getOwnPropertyNames(err).forEach((key) => {
kauffj commented 2017-09-16 00:18:31 +02:00 (Migrated from github.com)
Review

When is there a non-enumerable property being passed that this is required?

When is there a non-enumerable property being passed that this is required?
bones7242 commented 2017-09-21 21:10:37 +02:00 (Migrated from github.com)
Review

for errors created by node (e.g. new Error('error message')) the stack and message are non-enumerable

for errors created by node (e.g. `new Error('error message')`) the stack and message are non-enumerable
newErrorObject[key] = err[key];
});
return newErrorObject;
}
return err;
}
module.exports = { module.exports = {
handleRequestError (action, originalUrl, ip, error, res) { handleRequestError (action, originalUrl, ip, error, res) {
logger.error('Request Error >>', error); logger.error('Request Error:', useObjectPropertiesIfNoKeys(error));
postToStats(action, originalUrl, ip, null, null, error);
if (error.response) { if (error.response) {
postToStats(action, originalUrl, ip, null, null, error.response.data.error.messsage);
res.status(error.response.status).send(error.response.data.error.message); res.status(error.response.status).send(error.response.data.error.message);
} else if (error.code === 'ECONNREFUSED') { } else if (error.code === 'ECONNREFUSED') {
postToStats(action, originalUrl, ip, null, null, 'Connection refused. The daemon may not be running.');
res.status(503).send('Connection refused. The daemon may not be running.'); res.status(503).send('Connection refused. The daemon may not be running.');
} else if (error.message) { } else if (error.message) {
postToStats(action, originalUrl, ip, null, null, error);
res.status(400).send(error.message); res.status(400).send(error.message);
} else { } else {
postToStats(action, originalUrl, ip, null, null, error);
res.status(400).send(error); res.status(400).send(error);
} }
}, },
handlePublishError (error) { handlePublishError (error) {
logger.error('Publish Error:', useObjectPropertiesIfNoKeys(error));
if (error.code === 'ECONNREFUSED') { if (error.code === 'ECONNREFUSED') {
logger.error('Publish Error:', 'Connection refused. The daemon may not be running.');
return 'Connection refused. The daemon may not be running.'; return 'Connection refused. The daemon may not be running.';
} else if (error.response.data.error) { } else if (error.response.data.error) {
logger.error('Publish Error:', error.response.data.error);
return error.response.data.error.message; return error.response.data.error.message;
} else { } else {
logger.error('Unhandled Publish Error:', error.message);
return error; return error;
} }
}, },

View file

@ -110,11 +110,12 @@ module.exports = {
if (data.result) { if (data.result) {
resolve(data.result.download_directory); resolve(data.result.download_directory);
} else { } else {
reject(new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.')); // reject(new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.'));
return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.');
} }
}) })
.catch((error) => { .catch(error => {
logger.error('Unable to retrieve daemon download directory. Restart spee.ch once the daemon is ready. Using default "/home/lbry/Downloads".', error); logger.error('Lbrynet Error:', error);
resolve('/home/lbry/Downloads/'); resolve('/home/lbry/Downloads/');
}); });
}); });

View file

@ -11,7 +11,7 @@ function createOpenGraphInfo ({ fileType, claimId, name, fileName, fileExt }) {
module.exports = { module.exports = {
serveFile ({ fileName, fileType, filePath }, res) { serveFile ({ fileName, fileType, filePath }, res) {
logger.info(`serving file ${fileName}`); logger.verbose(`serving file ${fileName}`);
// set default options // set default options
let options = { let options = {
headers: { headers: {

View file

@ -6,9 +6,9 @@ const config = require('config');
const db = {}; const db = {};
const logger = require('winston'); const logger = require('winston');
const database = config.get('Database.database'); const database = config.get('Database.Database');
const username = config.get('Database.username'); const username = config.get('Database.Username');
const password = config.get('Database.password'); const password = config.get('Database.Password');
const sequelize = new Sequelize(database, username, password, { const sequelize = new Sequelize(database, username, password, {
host : 'localhost', host : 'localhost',
dialect: 'mysql', dialect: 'mysql',
@ -52,7 +52,7 @@ function getLongClaimIdFromShortClaimId (name, shortId) {
.then(result => { .then(result => {
switch (result.length) { switch (result.length) {
case 0: case 0:
return reject(new Error('That is an invalid Short Claim Id')); throw new Error('That is an invalid Short Claim Id');
default: // note results must be sorted default: // note results must be sorted
return resolve(result[0].claimId); return resolve(result[0].claimId);
} }
@ -179,7 +179,7 @@ db['getShortClaimIdFromLongClaimId'] = (claimId, claimName) => {
.then(result => { .then(result => {
switch (result.length) { switch (result.length) {
case 0: case 0:
return reject(new Error('That is an invalid claim name')); throw new Error('That is an invalid claim name');
default: default:
return resolve(sortResult(result, claimId)); return resolve(sortResult(result, claimId));
} }
@ -198,7 +198,7 @@ db['getShortChannelIdFromLongChannelId'] = (channelName, longChannelId) => {
.then(result => { .then(result => {
switch (result.length) { switch (result.length) {
case 0: case 0:
return reject(new Error('That is an invalid channel name')); throw new Error('That is an invalid channel name');
default: default:
return resolve(sortResult(result, longChannelId)); return resolve(sortResult(result, longChannelId));
} }
@ -238,7 +238,7 @@ db['resolveClaim'] = (name, claimId) => {
case 1: case 1:
return resolve(result[0]); return resolve(result[0]);
default: default:
return new Error('more than one entry matches that name and claimID'); throw new Error('more than one entry matches that name and claimID');
} }
}) })
.catch(error => { .catch(error => {
@ -255,7 +255,7 @@ db['getClaimIdByLongChannelId'] = (channelId, claimName) => {
.then(result => { .then(result => {
switch (result.length) { switch (result.length) {
case 0: case 0:
return reject(new Error('There is no such claim for that channel')); throw new Error('There is no such claim for that channel');
default: default:
return resolve(result[0].claimId); return resolve(result[0].claimId);
} }

View file

@ -39,7 +39,8 @@
"socket.io": "^2.0.1", "socket.io": "^2.0.1",
"socketio-file-upload": "^0.6.0", "socketio-file-upload": "^0.6.0",
"universal-analytics": "^0.4.13", "universal-analytics": "^0.4.13",
"winston": "^2.3.1" "winston": "^2.3.1",
"winston-slack-webhook": "billbitt/winston-slack-webhook"
}, },
kauffj commented 2017-09-16 00:19:43 +02:00 (Migrated from github.com)
Review

should this be billbitt?

should this be billbitt?
bones7242 commented 2017-09-21 21:11:27 +02:00 (Migrated from github.com)
Review

I made my own fork to fix an issue with the package, and submitted a PR to the main package. The PR was accepted, so will update this to point to main package in next update.

I made my own fork to fix an issue with the package, and submitted a PR to the main package. The PR was accepted, so will update this to point to main package in next update.
"devDependencies": { "devDependencies": {
"eslint": "3.19.0", "eslint": "3.19.0",

View file

@ -14,7 +14,8 @@ const db = require('./models'); // require our models for syncing
// configure logging // configure logging
const logLevel = config.get('Logging.LogLevel'); const logLevel = config.get('Logging.LogLevel');
require('./config/loggerSetup.js')(logger, logLevel); require('./config/loggerConfig.js')(logger, logLevel);
require('./config/slackLoggerConfig.js')(logger);
// trust the proxy to get ip address for us // trust the proxy to get ip address for us
app.enable('trust proxy'); app.enable('trust proxy');
@ -134,7 +135,7 @@ app.set('view engine', 'handlebars');
db.sequelize db.sequelize
.sync() // sync sequelize .sync() // sync sequelize
.then(() => { // get the download directory from the daemon .then(() => { // get the download directory from the daemon
logger.info('Retrieving daemon download directory'); logger.info('Retrieving daemon download directory...');
return getDownloadDirectory(); return getDownloadDirectory();
}) })
.then(hostedContentPath => { .then(hostedContentPath => {
@ -154,5 +155,5 @@ db.sequelize
}); });
}) })
.catch((error) => { .catch((error) => {
logger.error('Startup Error >>', error); logger.error(`Startup Error >> ${error.message}`, error);
}); });