Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DDW-248] Refactor compress/download logs handling #995

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ffd61bd
[DDW-248] Refactor compress/download logs handling
thedanheller Jun 26, 2018
3f4af8c
[DDW-248] Saving with the same timestamp
thedanheller Jun 27, 2018
88b9c50
[DDW-248] Removing logs on init
thedanheller Jun 27, 2018
c8f2a81
[DDW-248] Get fresh logs when submitting a support request
thedanheller Jun 29, 2018
15c2a1e
[DDW-248] CHANGELOG
thedanheller Jul 2, 2018
5976494
[DDW-248] UTC timestamp and FLOW
thedanheller Jul 4, 2018
e39f322
[DDW-248] Requesting logs only upon form submition
thedanheller Jul 4, 2018
2d5a251
[DDW-248] Removes useless extra lines
thedanheller Jul 4, 2018
7ab1f8f
[DDW-248] Renaming getFreshLogs to avoid confusion
thedanheller Jul 4, 2018
afd1343
Merge branch 'develop' into chore/ddw-248-refactor-compress-download-…
thedanheller Jul 4, 2018
242710e
[DDW-248] Flow errors
thedanheller Jul 4, 2018
81a444d
[DDW-248] lint error
thedanheller Jul 4, 2018
9a3a123
[DDW-248] Adjustments
thedanheller Jul 5, 2018
344d5d5
[DDW-248] linting
thedanheller Jul 5, 2018
37d9bf5
[DDW-248] getting logs on dialog open
thedanheller Jul 6, 2018
0d42e24
[DDW-248] Adjustments
thedanheller Jul 6, 2018
74ada87
Merge branch 'develop' into chore/ddw-248-refactor-compress-download-…
thedanheller Jul 6, 2018
6913da9
Merge branch 'develop' into chore/ddw-248-refactor-compress-download-…
DominikGuzei Jul 10, 2018
a7af4f1
[DDW-248] Code style improvements
nikolaglumac Jul 10, 2018
af76c11
[DDW-248] Code style improvements
nikolaglumac Jul 10, 2018
27fc619
[DDW-248] Code improvements
thedanheller Jul 10, 2018
43a75fc
[DDW-248] lint warning
thedanheller Jul 10, 2018
d68a724
[DDW-248] Code style improvements
nikolaglumac Jul 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Changelog
- Added acceptance tests for node update notification with apply and postpone update scenarios ([PR 977](https://github.com/input-output-hk/daedalus/pull/977))
- Added acceptance tests for maximum wallets limit ([PR 979](https://github.com/input-output-hk/daedalus/pull/979))
- Added acceptance tests for the About dialog ([PR 975](https://github.com/input-output-hk/daedalus/pull/975))
- Refactored compress/download logs handling ([PR 995](https://github.com/input-output-hk/daedalus/pull/995))

## 0.10.1
=======
Expand Down
8 changes: 8 additions & 0 deletions source/common/fileName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @flow
import moment from 'moment';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniloprates please add // @flow to the top of this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔︎


export const filenameWithTimestamp = (prefix:string = 'logs', filetype:string = 'zip') =>
`${prefix}-${moment.utc().format('YYYY-MM-DDThhmmss.0SSS')}.${filetype}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniloprates please use the following format YYYY-MM-DDTHH:mm:ss.0SSS here (and this should be reflected on the getFilenameWithTimestamp function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh one thing I forgot - please append Z to the end of the timestamp so that it looks like this: logs-2018-07-04T08:48:19.0182Z.zip
Thanks! :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @nikolaglumac!

I'll add the 'Z', however, it's not possible to add the colons, as it's an invalid character for filenames.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔︎


export const getFilenameWithTimestamp = (prefix:string = 'logs', filetype:string = 'zip') => (fileName:string) =>
fileName.match(RegExp(`(${prefix}-)([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{6}.0[0-9]{3})(.${filetype})`));
3 changes: 1 addition & 2 deletions source/main/ipc-api/compress-logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import { Logger, stringifyError } from '../../common/logging';
import { COMPRESS_LOGS } from '../../common/ipc-api';

export default () => {
ipcMain.on(COMPRESS_LOGS.REQUEST, (event, logs) => {
ipcMain.on(COMPRESS_LOGS.REQUEST, (event, logs, compressedFileName) => {
const sender = event.sender;
const compressedFileName = 'logs.zip';

const outputPath = path.join(appLogsFolderPath, compressedFileName);
const output = fs.createWriteStream(outputPath);
Expand Down
19 changes: 18 additions & 1 deletion source/main/utils/setupLogging.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import fs from 'fs';
import path from 'path';
import log from 'electron-log';
import moment from 'moment';
import ensureDirectoryExists from './ensureDirectoryExists';
import { pubLogsFolderPath, APP_NAME } from '../config';
import { pubLogsFolderPath, appLogsFolderPath, APP_NAME } from '../config';
import { getFilenameWithTimestamp } from '../../common/fileName';

const isTest = process.env.NODE_ENV === 'test';

Expand All @@ -19,4 +21,19 @@ export const setupLogging = () => {
const formattedDate = moment.utc(msg.date).format('YYYY-MM-DDTHH:mm:ss.0SSS');
return `[${formattedDate}Z] [${msg.level}] ${msg.data}`;
};

// Removes existing logs
fs.readdir(appLogsFolderPath, (err, files) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniloprates this part works great 🎉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙂

files
.filter(getFilenameWithTimestamp())
.forEach((logFileName) => {
const logFile = path.join(appLogsFolderPath, logFileName);
try {
fs.unlinkSync(logFile);
} catch (error) {
console.error(error);
}
});
});

};
3 changes: 2 additions & 1 deletion source/renderer/app/actions/profile-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ export default class ProfileActions {
acceptTermsOfUse: Action<any> = new Action();
compressLogs: Action<{ logs: Object }> = new Action();
getLogs: Action<any> = new Action();
downloadLogs: Action<{ destination: string, fresh?: boolean }> = new Action();
downloadLogs: Action<{ fileName: string, destination: string, fresh?: boolean }> = new Action();
deleteCompressedLogs: Action<any> = new Action();
resetBugReportDialog: Action<any> = new Action();
requestFreshCompressedLogs: Action<any> = new Action();
sendBugReport: Action<{
email: string, subject: string, problem: string, compressedLog: ?string,
}> = new Action();
Expand Down
4 changes: 3 additions & 1 deletion source/renderer/app/api/lib/reportRequest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import http from 'http';
import FormData from 'form-data/lib/form_data';
import fs from 'fs';
import { getFilenameWithTimestamp } from '../../../../common/fileName';

export type RequestOptions = {
hostname: string,
Expand Down Expand Up @@ -40,7 +41,8 @@ function typedHttpRequest<Response>(
// prepare file stream (attachment)
if (payload.compressedLog) {
const stream = fs.createReadStream(payload.compressedLog);
formData.append('logs.zip', stream);
const [fileName] = getFilenameWithTimestamp()(payload.compressedLog);
formData.append(fileName, stream);
}

options.headers = formData.getHeaders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,22 +118,19 @@ const messages = defineMessages({

type Props = {
logFiles: LogFiles,
compressedLog: ?string,
onCancel: Function,
onSubmit: Function,
onSubmitManually: Function,
onDownload: Function,
onGetLogs: Function,
onCompressLogs: Function,
onDeleteCompressedLogs: Function,
isSubmitting: boolean,
isCompressing: boolean,
onRequestFreshCompressedLogs: Function,
isDownloading?: boolean,
error: ?LocalizableError,
};

type State = {
showLogs: boolean,
compressedLog: ?string,
isSubmitting: boolean
};

@observer
Expand All @@ -145,19 +142,23 @@ export default class BugReportDialog extends Component<Props, State> {

state = {
showLogs: true,
compressedLog: null,
isSubmitting: false,
};

componentWillMount() {
this.props.onGetLogs();
this.props.onDeleteCompressedLogs();
}

componentWillReceiveProps(nextProps: Object) {
const commpressionFilesChanged = this.props.compressedLog !== nextProps.compressedLog;

const commpressionFilesChanged = !this.props.compressedLog && !!nextProps.compressedLog;
const { compressedLog } = this.state;

if (compressedLog) {
return false;
}

if (nextProps.compressedLog && commpressionFilesChanged && !nextProps.isDownloading) {
// proceed to submit when ipc rendered successfully return compressed files
this.submit(nextProps.compressedLog);
this.setState({ compressedLog: nextProps.compressedLog }, this.submit);
}

}

form = new ReactToolboxMobxForm({
Expand Down Expand Up @@ -206,24 +207,26 @@ export default class BugReportDialog extends Component<Props, State> {
},
});

submit = (compressedLog: ?string) => {
submit = () => {

this.setState({ isSubmitting: true });

const { showLogs, compressedLog } = this.state;

if (showLogs && !compressedLog) {
this.props.onRequestFreshCompressedLogs();
return false;
}

this.form.submit({
onSuccess: (form) => {
const { logFiles } = this.props;
const logsExist = get(logFiles, ['files'], []).length > 0;

const { email, subject, problem } = form.values();
const data = {
email, subject, problem, compressedLog
};

if (this.state.showLogs && logsExist && !compressedLog) {
// submit request with commpressed logs files
this.props.onCompressLogs(this.props.logFiles);
} else {
// regular submit
this.props.onSubmit(data);
}
this.props.onSubmit(data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniloprates we shouldn't send the log files if the user has set the "attach-logs" switch to off state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔︎

},
onError: () => {},
});
Expand All @@ -235,10 +238,10 @@ export default class BugReportDialog extends Component<Props, State> {

render() {
const { intl } = this.context;
const { showLogs } = this.state;
const { showLogs, isSubmitting } = this.state;
const { form } = this;
const {
onCancel, isSubmitting, isCompressing,
onCancel,
logFiles, error, onDownload, isDownloading,
} = this.props;

Expand All @@ -255,7 +258,7 @@ export default class BugReportDialog extends Component<Props, State> {

const submitButtonClasses = classnames([
'submitButton',
(isSubmitting || isCompressing) ? styles.isSubmitting : null,
isSubmitting ? styles.isSubmitting : null,
]);

const downloadButtonClasses = classnames([
Expand All @@ -273,7 +276,7 @@ export default class BugReportDialog extends Component<Props, State> {
label: this.context.intl.formatMessage(messages.submitButtonLabel),
primary: true,
disabled: isSubmitting,
onClick: this.submit.bind(this, null),
onClick: this.submit,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { get } from 'lodash';
import { observer, inject } from 'mobx-react';
import BugReportDialog from '../../../components/profile/bug-report/BugReportDialog';
import type { InjectedProps } from '../../../types/injectedPropsType';
import { filenameWithTimestamp } from '../../../../../common/fileName';

const shell = require('electron').shell;

Expand All @@ -20,10 +21,13 @@ export default class BugReportDialogContainer extends Component<InjectedProps> {
};

onDownload = () => {
const fileName = filenameWithTimestamp();
const destination = remote.dialog.showSaveDialog({
defaultPath: 'logs.zip',
defaultPath: fileName,
});
if (destination) this.props.actions.profile.downloadLogs.trigger({ destination });
if (destination) {
this.props.actions.profile.downloadLogs.trigger({ fileName, destination, fresh: true });
}
};

onSubmitManually = (link: string) => {
Expand All @@ -36,12 +40,10 @@ export default class BugReportDialogContainer extends Component<InjectedProps> {

render() {
const { actions, stores } = this.props;
const { getLogs, compressLogs, deleteCompressedLogs } = actions.profile;
const { requestFreshCompressedLogs } = actions.profile;
const {
logFiles,
compressedLog,
isCompressing,
sendBugReport,
compressedFileDownload,
error,
} = stores.profile;
Expand All @@ -51,21 +53,13 @@ export default class BugReportDialogContainer extends Component<InjectedProps> {
isDownloading={get(compressedFileDownload, 'inProgress', false)}
logFiles={logFiles}
compressedLog={compressedLog}
isCompressing={isCompressing}
isSubmitting={sendBugReport.isExecuting}
error={error}
onSubmit={this.onSubmit}
onSubmitManually={this.onSubmitManually}
onDownload={this.onDownload}
onCancel={this.resetBugReportDialog}
onGetLogs={() => {
getLogs.trigger();
}}
onCompressLogs={(logs) => {
compressLogs.trigger({ logs });
}}
onDeleteCompressedLogs={() => {
deleteCompressedLogs.trigger();
onRequestFreshCompressedLogs={(logs) => {
requestFreshCompressedLogs.trigger({ logs });
}}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { remote } from 'electron';
import SupportSettings from '../../../components/settings/categories/SupportSettings';
import type { InjectedProps } from '../../../types/injectedPropsType';
import BugReportDialog from '../../../components/profile/bug-report/BugReportDialog';
import { filenameWithTimestamp } from '../../../../../common/fileName';

const shell = require('electron').shell;

Expand All @@ -25,10 +26,13 @@ export default class SupportSettingsPage extends Component<InjectedProps> {
};

handleDownloadLogs = () => {
const fileName = filenameWithTimestamp();
const destination = remote.dialog.showSaveDialog({
defaultPath: 'logs.zip',
defaultPath: fileName,
});
if (destination) this.props.actions.profile.downloadLogs.trigger({ destination, fresh: true });
if (destination) {
this.props.actions.profile.downloadLogs.trigger({ fileName, destination, fresh: true });
}
};

render() {
Expand Down
27 changes: 20 additions & 7 deletions source/renderer/app/stores/ProfileStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import LocalizableError from '../i18n/LocalizableError';
import globalMessages from '../i18n/global-messages';
import { WalletSupportRequestLogsCompressError } from '../i18n/errors';
import type { LogFiles, CompressedFileDownload } from '../types/LogTypes';
import { filenameWithTimestamp } from '../../../common/fileName';

export default class SettingsStore extends Store {

Expand Down Expand Up @@ -57,6 +58,7 @@ export default class SettingsStore extends Store {
this.actions.profile.getLogs.listen(this._getLogs);
this.actions.profile.resetBugReportDialog.listen(this._resetBugReportDialog);
this.actions.profile.downloadLogs.listen(this._downloadLogs);
this.actions.profile.requestFreshCompressedLogs.listen(this._requestFreshCompressedLogs);
this.actions.profile.compressLogs.listen(this._compressLogs);
this.actions.profile.deleteCompressedLogs.listen(this._deleteCompressedFiles);
this.actions.profile.sendBugReport.listen(this._sendBugReport);
Expand Down Expand Up @@ -207,10 +209,11 @@ export default class SettingsStore extends Store {
this.actions.dialogs.closeActiveDialog.trigger();
};

_downloadLogs = action(({ destination, fresh }) => {
_downloadLogs = action(({ fileName, destination, fresh }) => {
this.compressedFileDownload = {
inProgress: true,
destination,
fileName
};

if (this.compressedLog && fresh !== true) {
Expand All @@ -224,25 +227,33 @@ export default class SettingsStore extends Store {

_onGetLogsSuccess = action((event, res) => {
this.logFiles = res;
if (this.compressedFileDownload.inProgress) {
this._compressLogs({ logs: res });
}
this._compressLogs({ logs: res });
});

_onDownloadLogsSuccess = action(() => {
this.compressedFileDownload = {};
});

_requestFreshCompressedLogs = action(() => {
this.compressedFileDownload = {
fileName: filenameWithTimestamp()
};
this.isCompressing = true;
this._getLogs();
});

_compressLogs = action(({ logs }) => {
this.isCompressing = true;
ipcRenderer.send(COMPRESS_LOGS.REQUEST, toJS(logs));
const { fileName = filenameWithTimestamp() } = this.compressedFileDownload;
ipcRenderer.send(COMPRESS_LOGS.REQUEST, toJS(logs), fileName);
});

_onCompressLogsSuccess = action((event, res) => {
this.isCompressing = false;
this.compressedLog = res;
if (this.compressedFileDownload.inProgress) {
this._downloadLogs({ destination: this.compressedFileDownload.destination });
const { inProgress, destination, fileName } = this.compressedFileDownload;
if (inProgress) {
this._downloadLogs({ destination, fileName });
}
});

Expand All @@ -256,6 +267,7 @@ export default class SettingsStore extends Store {
problem: string,
compressedLog: ?string,
}) => {

this.sendBugReport.execute({
email, subject, problem, compressedLog,
})
Expand All @@ -265,6 +277,7 @@ export default class SettingsStore extends Store {
.catch(action((error) => {
this.error = error;
}));

});

_deleteCompressedFiles = action(() => {
Expand Down
3 changes: 2 additions & 1 deletion source/renderer/app/types/LogTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type CompressedLogs = {
} | {};

export type CompressedFileDownload = {
inProgress?: boolean,
fileName?: string,
destination?: string,
inProgress?: boolean,
};