mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
[WEB] Add analytics events for importing and exporting to different file types (#33614)
* adding events for success and failure for import and export from latex * adding the operation property to capture the import/export keyword GitOrigin-RevId: 2e5482b3c7517b402fc151966975ca8718729683
This commit is contained in:
@@ -7,6 +7,7 @@ import { prepareZipAttachment } from '../../infrastructure/Response.mjs'
|
||||
import SessionManager from '../Authentication/SessionManager.mjs'
|
||||
import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.mjs'
|
||||
import DocumentConversionManager from '../Uploads/DocumentConversionManager.mjs'
|
||||
import AnalyticsManager from '../Analytics/AnalyticsManager.mjs'
|
||||
import Validation from '../../infrastructure/Validation.mjs'
|
||||
import { expressify } from '@overleaf/promise-utils'
|
||||
import { pipeline } from 'node:stream/promises'
|
||||
@@ -78,12 +79,30 @@ async function exportProjectConversion(req, res) {
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
Metrics.inc('document-exports', 1, { type })
|
||||
|
||||
const { conversionId, buildId, clsiServerId, file } =
|
||||
await DocumentConversionManager.promises.convertProjectToDocument(
|
||||
projectId,
|
||||
userId,
|
||||
type
|
||||
)
|
||||
let conversionResult
|
||||
try {
|
||||
conversionResult =
|
||||
await DocumentConversionManager.promises.convertProjectToDocument(
|
||||
projectId,
|
||||
userId,
|
||||
type
|
||||
)
|
||||
AnalyticsManager.recordEventForUserInBackground(userId, 'convert-format', {
|
||||
sourceFormat: 'latex',
|
||||
targetFormat: type,
|
||||
status: 'success',
|
||||
operation: 'export',
|
||||
})
|
||||
} catch (error) {
|
||||
AnalyticsManager.recordEventForUserInBackground(userId, 'convert-format', {
|
||||
sourceFormat: 'latex',
|
||||
targetFormat: type,
|
||||
status: 'failure',
|
||||
operation: 'export',
|
||||
})
|
||||
throw error
|
||||
}
|
||||
const { conversionId, buildId, clsiServerId, file } = conversionResult
|
||||
ProjectAuditLogHandler.addEntryInBackground(
|
||||
projectId,
|
||||
`project-exported-${type}`,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { expressify } from '@overleaf/promise-utils'
|
||||
import { DuplicateNameError, FileTooLargeError } from '../Errors/Errors.js'
|
||||
import DocumentConversionManager from './DocumentConversionManager.mjs'
|
||||
import ProjectOptionsHandler from '../Project/ProjectOptionsHandler.mjs'
|
||||
import AnalyticsManager from '../Analytics/AnalyticsManager.mjs'
|
||||
|
||||
const defaultsDeep = lodash.defaultsDeep
|
||||
|
||||
@@ -202,6 +203,16 @@ async function importDocument(req, res, next) {
|
||||
archivePath
|
||||
)
|
||||
await ProjectOptionsHandler.promises.setCompiler(project._id, 'lualatex')
|
||||
AnalyticsManager.recordEventForUserInBackground(
|
||||
userId,
|
||||
'convert-format',
|
||||
{
|
||||
sourceFormat: conversionType,
|
||||
targetFormat: 'latex',
|
||||
status: 'success',
|
||||
operation: 'import',
|
||||
}
|
||||
)
|
||||
res.json({ success: true, project_id: project._id })
|
||||
} finally {
|
||||
await fsPromises.unlink(archivePath).catch(unlinkErr => {
|
||||
@@ -213,6 +224,12 @@ async function importDocument(req, res, next) {
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error({ error }, 'error importing document file')
|
||||
AnalyticsManager.recordEventForUserInBackground(userId, 'convert-format', {
|
||||
sourceFormat: conversionType,
|
||||
targetFormat: 'latex',
|
||||
status: 'failure',
|
||||
operation: 'import',
|
||||
})
|
||||
if (
|
||||
error instanceof FileTooLargeError ||
|
||||
error?.name === 'FileTooLargeError'
|
||||
|
||||
@@ -92,6 +92,15 @@ describe('ProjectDownloadsController', function () {
|
||||
pipeline: (ctx.pipeline = sinon.stub().resolves()),
|
||||
}))
|
||||
|
||||
vi.doMock(
|
||||
'../../../../app/src/Features/Analytics/AnalyticsManager.mjs',
|
||||
() => ({
|
||||
default: (ctx.AnalyticsManager = {
|
||||
recordEventForUserInBackground: sinon.stub(),
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
ctx.ProjectDownloadsController = (await import(modulePath)).default
|
||||
})
|
||||
|
||||
@@ -349,6 +358,20 @@ describe('ProjectDownloadsController', function () {
|
||||
it('should stream the document to the response', function (ctx) {
|
||||
sinon.assert.calledWith(ctx.pipeline, ctx.exportStream, ctx.res)
|
||||
})
|
||||
|
||||
it('should record a successful convert-format analytics event', function (ctx) {
|
||||
sinon.assert.calledWith(
|
||||
ctx.AnalyticsManager.recordEventForUserInBackground,
|
||||
ctx.userId,
|
||||
'convert-format',
|
||||
{
|
||||
sourceFormat: 'latex',
|
||||
targetFormat: 'docx',
|
||||
status: 'success',
|
||||
operation: 'export',
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with responseFormat=json', function () {
|
||||
|
||||
@@ -112,6 +112,16 @@ describe('ProjectUploadController', function () {
|
||||
})
|
||||
)
|
||||
|
||||
ctx.AnalyticsManager = {
|
||||
recordEventForUserInBackground: sinon.stub(),
|
||||
}
|
||||
vi.doMock(
|
||||
'../../../../app/src/Features/Analytics/AnalyticsManager.mjs',
|
||||
() => ({
|
||||
default: ctx.AnalyticsManager,
|
||||
})
|
||||
)
|
||||
|
||||
vi.doMock('node:fs', () => ({
|
||||
default: (ctx.fs = {}),
|
||||
}))
|
||||
@@ -525,6 +535,20 @@ describe('ProjectUploadController', function () {
|
||||
ctx.req.file.path
|
||||
)
|
||||
})
|
||||
|
||||
it('should record a successful convert-format analytics event', function (ctx) {
|
||||
sinon.assert.calledWith(
|
||||
ctx.AnalyticsManager.recordEventForUserInBackground,
|
||||
ctx.user_id,
|
||||
'convert-format',
|
||||
{
|
||||
sourceFormat: 'docx',
|
||||
targetFormat: 'latex',
|
||||
status: 'success',
|
||||
operation: 'import',
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -581,6 +605,20 @@ describe('ProjectUploadController', function () {
|
||||
it('should unlink the uploaded file', function (ctx) {
|
||||
expect(ctx.fsPromises.unlink).to.have.been.calledWith(ctx.req.file.path)
|
||||
})
|
||||
|
||||
it('should record a successful convert-format analytics event', function (ctx) {
|
||||
sinon.assert.calledWith(
|
||||
ctx.AnalyticsManager.recordEventForUserInBackground,
|
||||
ctx.user_id,
|
||||
'convert-format',
|
||||
{
|
||||
sourceFormat: 'markdown',
|
||||
targetFormat: 'latex',
|
||||
status: 'success',
|
||||
operation: 'import',
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an invalid conversionType', async function () {
|
||||
@@ -639,6 +677,20 @@ describe('ProjectUploadController', function () {
|
||||
it('should return http 500', function (ctx) {
|
||||
expect(ctx.res.statusCode).to.equal(500)
|
||||
})
|
||||
|
||||
it('should record a failed convert-format analytics event', function (ctx) {
|
||||
sinon.assert.calledWith(
|
||||
ctx.AnalyticsManager.recordEventForUserInBackground,
|
||||
ctx.user_id,
|
||||
'convert-format',
|
||||
{
|
||||
sourceFormat: 'docx',
|
||||
targetFormat: 'latex',
|
||||
status: 'failure',
|
||||
operation: 'import',
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the converted archive is too large', async function () {
|
||||
|
||||
Reference in New Issue
Block a user