Skip to content

Commit

Permalink
automatically disable full profiling after some time to avoid perform…
Browse files Browse the repository at this point in the history
…ance degradation
  • Loading branch information
pofider committed Apr 13, 2023
1 parent 15ba61d commit aa3f7bc
Show file tree
Hide file tree
Showing 32 changed files with 129 additions and 47 deletions.
10 changes: 10 additions & 0 deletions packages/jsreport-core/lib/main/optionsSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ module.exports.getRootSchemaOptions = () => ({
type: 'string',
default: 'standard'
},
fullModeDurationCheckInterval: {
type: ['string', 'number'],
'$jsreport-acceptsDuration': true,
default: '10m'
},
fullModeDuration: {
type: ['string', 'number'],
'$jsreport-acceptsDuration': true,
default: '4h'
},
maxProfilesHistory: {
type: 'number',
default: 1000
Expand Down
36 changes: 36 additions & 0 deletions packages/jsreport-core/lib/main/profiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ module.exports = (reporter) => {
}

let profilesCleanupInterval
let fullModeDurationCheckInterval

reporter.initializeListeners.add('profiler', async () => {
reporter.documentStore.collection('profiles').beforeRemoveListeners.add('profiles', async (query, req) => {
Expand All @@ -384,13 +385,21 @@ module.exports = (reporter) => {
}
})

// exposing it to jo for override
function profilesCleanupExec () {
return reporter._profilesCleanup()
}

function fullModeDurationCheckExec () {
return reporter._profilesFullModeDurationCheck()
}

profilesCleanupInterval = setInterval(profilesCleanupExec, reporter.options.profiler.cleanupInterval)
profilesCleanupInterval.unref()

fullModeDurationCheckInterval = setInterval(fullModeDurationCheckExec, reporter.options.profiler.fullModeDurationCheckInterval)
fullModeDurationCheckInterval.unref()

await reporter._profilesCleanup()
})

Expand All @@ -399,6 +408,10 @@ module.exports = (reporter) => {
clearInterval(profilesCleanupInterval)
}

if (fullModeDurationCheckInterval) {
clearInterval(fullModeDurationCheckInterval)
}

for (const key of profilerOperationsChainsMap.keys()) {
const profileAppendPromise = profilerOperationsChainsMap.get(key)
if (profileAppendPromise) {
Expand Down Expand Up @@ -502,6 +515,29 @@ module.exports = (reporter) => {
}
}

reporter._profilesFullModeDurationCheck = async function () {
try {
if (reporter.options.profiler.defaultMode === 'full') {
return
}
const profiler = await reporter.documentStore.collection('settings').findOne({ key: 'profiler' })
if (profiler == null || (profiler.modificationDate.getTime() + reporter.options.profiler.fullModeDuration) > new Date().getTime()) {
return
}

const profilerValue = JSON.parse(profiler.value)

if (profilerValue.mode !== 'full') {
return
}

reporter.logger.info('Switching full mode profiling back to standard to avoid performance degradation.')
await reporter.settings.addOrSet('profiler', { mode: 'standard' })
} catch (e) {
reporter.logger.warn('Failed to change profiling mode', e)
}
}

return function cleanProfileInRequest (req) {
// - req.context.profiling is empty only on an early error
// that happens before setting the profiler.
Expand Down
33 changes: 33 additions & 0 deletions packages/jsreport-core/test/profiler/profilerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,36 @@ describe('profiler cleanup', () => {
profile.error.should.containEql('The request wasn\'t parsed before')
})
})

describe('profiler full mode duration check', () => {
let reporter

beforeEach(() => {
reporter = jsreport({
profiler: {
fullModeDurationCheckInterval: '10ms',
fullModeDuration: '20ms'
}
})
reporter.use(jsreport.tests.listeners())
return reporter.init()
})

afterEach(() => reporter.close())

it('shouldnt change profiling mode when fullModeDuration didnt elapsed', async () => {
await reporter.documentStore.collection('settings').insert({ key: 'profiler', value: JSON.stringify({ mode: 'full' }) })
await new Promise((resolve) => setTimeout(resolve, 10))
const profiler = await reporter.documentStore.collection('settings').findOne({ key: 'profiler' })
const profilerVal = JSON.parse(profiler.value)
profilerVal.mode.should.be.eql('full')
})

it('should change profiling mode when fullModeDuration didnt elapsed', async () => {
await reporter.documentStore.collection('settings').insert({ key: 'profiler', value: JSON.stringify({ mode: 'full' }) })
await new Promise((resolve) => setTimeout(resolve, 30))
const profiler = await reporter.documentStore.collection('settings').findOne({ key: 'profiler' })
const profilerVal = JSON.parse(profiler.value)
profilerVal.mode.should.be.eql('standard')
})
})
4 changes: 3 additions & 1 deletion packages/jsreport-studio/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const compression = require('compression')
const ThemeManager = require('./themeManager')
const createTextSearch = require('./textSearch')
const distPath = path.join(__dirname, '../static/dist')
const ms = require('ms')

module.exports = (reporter, definition) => {
const diff2htmlStyle = fs.readFileSync(path.join(__dirname, '../static/diff.css')).toString()
Expand Down Expand Up @@ -553,7 +554,8 @@ module.exports = (reporter, definition) => {
entityTreeOrder: definition.options.entityTreeOrder,
linkButtonVisibility: definition.options.linkButtonVisibility,
profiler: {
defaultMode: reporter.options.profiler.defaultMode
defaultMode: reporter.options.profiler.defaultMode,
fullModeDurationStr: ms(reporter.options.profiler.fullModeDuration)
}
})
}
Expand Down
3 changes: 2 additions & 1 deletion packages/jsreport-studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"highlight-words-core": "1.2.2",
"isbinaryfile": "5.0.0",
"lodash": "4.17.21",
"ms": "2.1.3",
"race-as-promised": "0.0.1",
"semaphore-async-await": "1.5.1",
"serve-favicon": "2.5.0",
Expand Down Expand Up @@ -133,4 +134,4 @@
"browser": true
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class Profiler extends Component {
ev.target.checked && this.startFullRequestProfiling()
}}
/>
<span>Full profiling</span>
<span>Full profiling (limited for {configuration.extensions.studio.options.profiler.fullModeDurationStr})</span>
</label>
<label style={{ paddingLeft: '1rem' }}>
<input
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

0 comments on commit aa3f7bc

Please sign in to comment.