Skip to content

Commit

Permalink
refactor: handling url from alert msg
Browse files Browse the repository at this point in the history
  • Loading branch information
mrrishimeena committed Aug 29, 2024
1 parent fd7f8b2 commit a5ab185
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 50 deletions.
6 changes: 3 additions & 3 deletions lib/main/server/utils/alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ SlackService.sendAlert = async function (message, type, messageExtraInfo, errsol
return false; // Slack integration is disabled
}
const webhookUrl = parsedValue.url;
const payload = blockKit(message, type, messageExtraInfo);
const payload = blockKit(message, type, messageExtraInfo, errsoleLogId);

payload.username = parsedValue.username || 'Errsole';
payload.icon_url = parsedValue.icon_url || 'https://avatars.githubusercontent.com/u/84983840';
Expand All @@ -82,7 +82,7 @@ SlackService.sendAlert = async function (message, type, messageExtraInfo, errsol
}
};

function blockKit (message, type, messageExtraInfo = {}) {
function blockKit (message, type, messageExtraInfo = {}, errsoleLogId) {
const payload = {
blocks: []
};
Expand All @@ -96,7 +96,7 @@ function blockKit (message, type, messageExtraInfo = {}) {
if (messageExtraInfo.serverName) {
payload.blocks.push({ type: 'rich_text', elements: [{ type: 'rich_text_section', elements: [{ type: 'text', text: 'Server Name: ', style: { bold: true } }, { type: 'text', text: messageExtraInfo.serverName }] }] });
}
payload.blocks.push({ type: 'rich_text', elements: [{ type: 'rich_text_preformatted', elements: [{ type: 'text', text: message }] }] });
payload.blocks.push({ type: 'rich_text', elements: [{ type: 'rich_text_preformatted', elements: [{ type: 'text', text: message + ' - ' + errsoleLogId }] }] });
return payload;
}

Expand Down
119 changes: 77 additions & 42 deletions lib/web/src/components/ConsoleLogs.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ class ConsoleLogs extends React.Component {
const ConsoleLogs = this.props.currentConsoleLogs;

let search = this.props.location.search;
let errsoleLogId = null;
let errsoleLogQueryId = null;
let errsoleLogQueryTimestamp = null;
if (search !== '') {
search = search.toLowerCase();
const qparams = new URLSearchParams(search);
errsoleLogId = qparams.get('errsole_log_id');
errsoleLogQueryId = qparams.get('errsole_log_id');
errsoleLogQueryTimestamp = qparams.get('timestamp');
if (errsoleLogQueryId || errsoleLogQueryTimestamp) window.sessionStorage.removeItem('errsole-filter-details');
}

this.state = {
Expand All @@ -57,30 +60,23 @@ class ConsoleLogs extends React.Component {
searchTime: null,
selectedDatetime: null,
searchTerms: [],
errsoleLogId,
errsoleLogQueryId,
errsoleLogQueryTimestamp,
timezone: timezone || 'Local'
};
}

componentDidMount () {
// set or update timezone
const filterDetailsFromSession = window.sessionStorage.getItem('errsole-filter-details');
if (filterDetailsFromSession) {
const filterDetails = JSON.parse(filterDetailsFromSession);
filterDetails.timezone = this.state.timezone;
window.sessionStorage.setItem('errsole-filter-details', JSON.stringify(filterDetails));
} else {
const filterDetails = {};
filterDetails.timezone = this.state.timezone;
window.sessionStorage.setItem('errsole-filter-details', JSON.stringify(filterDetails));
}
const filterDetails = JSON.parse(window.sessionStorage.getItem('errsole-filter-details')) || {};
filterDetails.timezone = this.state.timezone;
window.sessionStorage.setItem('errsole-filter-details', JSON.stringify(filterDetails));

// reupdate filters if revisit the page or component
this.updateFilterState();
// get console logs
setTimeout(() => {
if (this.state.currentConsoleLogs.length === 0 && this.state.errsoleLogId) {
this.getAlertLogs(null, 'componentReload');
} else if (this.state.currentConsoleLogs.length === 0) {
if (this.state.currentConsoleLogs.length === 0) {
this.getConsoleLogs(null, 'componentReload');
}
}, 200);
Expand All @@ -104,8 +100,39 @@ class ConsoleLogs extends React.Component {

updateFilterState () {
const filterDetailsFromSession = window.sessionStorage.getItem('errsole-filter-details');
if (filterDetailsFromSession) {
const filterDetails = JSON.parse(filterDetailsFromSession);
const filterDetails = JSON.parse(filterDetailsFromSession);
// if query has errsole_log_id, set it in session and clean query from url
const errsoleLogQueryId = this.state.errsoleLogQueryId;
const errsoleLogQueryTimestamp = this.state.errsoleLogQueryTimestamp
? this.state.errsoleLogQueryTimestamp.replace('t', 'T').replace('z', 'Z')
: null;
if (errsoleLogQueryId) {
if (!filterDetails.httpQuery) filterDetails.httpQuery = {};
filterDetails.httpQuery.errsole_id = errsoleLogQueryId;
if (errsoleLogQueryTimestamp) {
// handle time and timezone
const timezone = this.state.timezone || 'Local';
// Convert UTC timestamp based on the timezone state
let formattedDatetime;
if (timezone === 'UTC') {
formattedDatetime = moment.utc(errsoleLogQueryTimestamp).format('YYYY-MM-DD HH:mm:ss');
} else {
const formattedLocalDatetime = moment.utc(errsoleLogQueryTimestamp).local();
formattedDatetime = formattedLocalDatetime.format('YYYY-MM-DD HH:mm:ss');
}
const [searchDate, searchTime] = formattedDatetime.split(' ');
filterDetails.search_date = searchDate;
filterDetails.search_time = searchTime;
filterDetails.httpQuery.lte_timestamp = errsoleLogQueryTimestamp;
}
window.sessionStorage.setItem('errsole-filter-details', JSON.stringify(filterDetails));
// push url state
const url = new URL(window.location.href);
url.hash = '#/logs';
url.search = '';
window.history.pushState({}, '', url);
}
if (filterDetails) {
// restore
const timezone = filterDetails.timezone;
const searchDate = filterDetails.search_date;
Expand All @@ -126,6 +153,7 @@ class ConsoleLogs extends React.Component {
}
const levelJson = filterDetails?.httpQuery?.level_json;
const hostnames = filterDetails?.httpQuery?.hostnames;
const errsoleLogId = filterDetails?.httpQuery?.errsole_id;
let logsType = [];
if (levelJson) {
logsType = JSON.parse(levelJson).map(function (item) {
Expand All @@ -138,15 +166,19 @@ class ConsoleLogs extends React.Component {
});
logsType = logsType.concat(hostnameList);
}
if (errsoleLogId) {
logsType = logsType.concat('errsolelogid.' + errsoleLogId);
}
this.setState({
logsType
logsType,
errsoleLogId
});
} else {
} else if (!errsoleLogQueryId) {
this.setState({
logsType: ['console.errorLogs', 'errsole.alertLogs', 'errsole.errorLogs']
});
}
} else {
} else if (!errsoleLogQueryId) {
this.setState({
logsType: ['console.errorLogs', 'errsole.alertLogs', 'errsole.errorLogs']
});
Expand Down Expand Up @@ -217,6 +249,8 @@ class ConsoleLogs extends React.Component {
} else {
delete query.hostnames;
}
// errsole_id
query.errsole_id = this.getErrsoleIdFilters(logsType);
}
query.logOrder = queryRequest?.logOrder;

Expand Down Expand Up @@ -248,14 +282,6 @@ class ConsoleLogs extends React.Component {
this.getCurrentConsoleLogs(query);
}

getAlertLogs () {
// http req
const query = {
errsole_id: this.state.errsoleLogId
};
this.getCurrentConsoleLogs(query);
}

getCurrentConsoleLogs (query) {
const self = this;
const logOrder = query.logOrder;
Expand Down Expand Up @@ -358,6 +384,20 @@ class ConsoleLogs extends React.Component {
return result;
}

getErrsoleIdFilters (filterList) {
const result = [];
filterList.forEach(list => {
if (list.startsWith('errsolelogid.')) {
const parts = list.split('errsolelogid.');
if (parts.length === 2) {
const hostname = parts[1];
result.push(hostname);
}
}
});
return result;
}

combineLogs (newLogs, logOrder) {
const oldLogs = this.state.currentConsoleLogs || [];
let allLogs;
Expand Down Expand Up @@ -502,12 +542,6 @@ class ConsoleLogs extends React.Component {

apply () {
const self = this;
if (this.state.errsoleLogId) {
const url = new URL(window.location.href);
url.hash = '#/logs';
url.search = '';
window.history.pushState({}, '', url);
}
const searchDate = this.state.searchDate;
const searchTime = this.state.searchTime;

Expand Down Expand Up @@ -556,12 +590,6 @@ class ConsoleLogs extends React.Component {
}

reset () {
if (this.state.errsoleLogId) {
const url = new URL(window.location.href);
url.hash = '#/logs';
url.search = '';
window.history.pushState({}, '', url);
}
this.setState({
logsType: [],
selectedDatetime: null,
Expand Down Expand Up @@ -683,7 +711,6 @@ class ConsoleLogs extends React.Component {

render () {
const logsType = this.state.logsType || [];
console.log(logsType);
const consoleLogLoading = this.state.consoleLogLoading || false;
const searchDate = this.state.searchDate;
const searchTime = this.state.searchTime;
Expand All @@ -698,6 +725,7 @@ class ConsoleLogs extends React.Component {
const activeLogMeta = this.state.activeLogMeta || null;
const metaModalStatus = this.state.metaModalStatus || false;
const hostnames = this.state.hostnames || [];
const errsoleLogId = this.state.errsoleLogId;

const renderConsoleLogs = () => {
return currentConsoleLogs.map((log) => {
Expand Down Expand Up @@ -776,6 +804,12 @@ class ConsoleLogs extends React.Component {
});
};

const showErrsoleLogId = () => {
if (errsoleLogId) {
return <Option value={'errsolelogid.' + errsoleLogId} key={errsoleLogId}>Log Id: {errsoleLogId}</Option>;
}
};

return (
<div className='logs-layout'>
<Spin indicator={antIcon} spinning={consoleLogLoading} delay={100}>
Expand All @@ -800,6 +834,7 @@ class ConsoleLogs extends React.Component {
<OptGroup label='Hostnames'>
{hostnames.length > 0 && showHostnames()}
</OptGroup>
{errsoleLogId && showErrsoleLogId()}
</Select>
</div>
<div className='filter float-l date-picker'>
Expand Down
23 changes: 18 additions & 5 deletions lib/web/src/components/Integrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@ class Integrations extends React.Component {
this.getSlackDetails();
this.getEmailDetails();
this.getAllUsers();
this.getAlertURL();
}

getAlertURL () {
// const self = this;
// this.props.appActions.getAlertURL(function (err, response) {
// if (!err && response) {
// const users = response.map((user) => { return user.attributes.url; });
// self.setState({
// allUsers: users
// });
// } else {
// self.setState({
// loadingStatus: false
// });
// }
// });
}

getAllUsers () {
Expand Down Expand Up @@ -337,11 +354,7 @@ class Integrations extends React.Component {
</ol>
</div>
</>}
{slackDetails &&
<><Result status='success' title={slackStatus ? <span><Icon type='check-circle' style={{ color: 'green' }} theme='filled' className='custom-check' /> Slack Integrated</span> : <span><Icon type='pause-circle' style={{ color: 'orange' }} theme='filled' /> Slack Notifications Paused</span>} subTitle={slackStatus ? 'You will receive notifications for app downtime and custom alerts directly on Slack.' : 'You have paused Slack notifications for app downtime and custom alerts.'} extra={[<Button type='primary' onClick={this.updateSlackDetails.bind(this, !slackStatus)} key='1'> {slackStatus ? 'Pause Notifications' : 'Resume Notifications'} </Button>, <Button type='danger' onClick={this.deleteSlackDetails.bind(this)} key='2'> Remove </Button>, <Button type='primary' ghost onClick={this.testNotifications.bind(this, 'slack')} key='3' loading={testNotificationLoading}> Test Notification </Button>]} />
<Divider>URL</Divider>
<p>This is URL format you will receive on Slack to view the log. If it's incorrect please update this</p>
</>}
{slackDetails && <Result status='success' title={slackStatus ? <span><Icon type='check-circle' style={{ color: 'green' }} theme='filled' className='custom-check' /> Slack Integrated</span> : <span><Icon type='pause-circle' style={{ color: 'orange' }} theme='filled' /> Slack Notifications Paused</span>} subTitle={slackStatus ? 'You will receive notifications for app downtime and custom alerts directly on Slack.' : 'You have paused Slack notifications for app downtime and custom alerts.'} extra={[<Button type='primary' onClick={this.updateSlackDetails.bind(this, !slackStatus)} key='1'> {slackStatus ? 'Pause Notifications' : 'Resume Notifications'} </Button>, <Button type='danger' onClick={this.deleteSlackDetails.bind(this)} key='2'> Remove </Button>, <Button type='primary' ghost onClick={this.testNotifications.bind(this, 'slack')} key='3' loading={testNotificationLoading}> Test Notification </Button>]} />}
</TabPane>
<TabPane tab={<span><Icon type='mail' />Email</span>} key='3'>
{(!emailDetails || editEmailDetails) &&
Expand Down

0 comments on commit a5ab185

Please sign in to comment.