{"size": 1922, "ext": "js", "max_stars_repo_path": "packages/dd-trace/src/profiling/profiler.js", "max_stars_repo_name": "bodinsamuel/dd-trace-js", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "packages/dd-trace/src/profiling/profiler.js", "max_issues_repo_name": "bodinsamuel/dd-trace-js", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "packages/dd-trace/src/profiling/profiler.js", "max_forks_repo_name": "bodinsamuel/dd-trace-js", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 21.1208791209, "max_line_length": 91, "alphanum_fraction": 0.6118626431}
'use strict'

const semver = require('semver')
const { EventEmitter } = require('events')
const { Config } = require('./config')
const { SourceMapper } = require('./mapper')

class Profiler extends EventEmitter {
  start (options) {
    if (this._enabled) return

    this._config = new Config(options)

    if (!this._config.enabled) return

    this._logger = this._config.logger

    if (!semver.satisfies(process.version, '>=10.12')) {
      this._logger.error('Profiling could not be started because it requires Node >=10.12')
      return this
    }

    this._enabled = true

    try {
      const mapper = new SourceMapper()

      for (const profiler of this._config.profilers) {
        profiler.start({ mapper }) // TODO: move this outside of profilers
      }
    } catch (e) {
      this._logger.error(e)
      this.stop()
    }

    this._capture(this._config.flushInterval)

    return this
  }

  stop () {
    if (!this._enabled) return

    this._enabled = false

    for (const profiler of this._config.profilers) {
      profiler.stop()
    }

    clearTimeout(this._timer)

    return this
  }

  _capture (timeout) {
    const start = new Date()

    this._timer = setTimeout(() => this._collect(start), timeout)
    this._timer.unref()
  }

  async _collect (start) {
    try {
      const end = new Date()
      const profiles = {}

      for (const profiler of this._config.profilers) {
        profiles[profiler.type] = await profiler.profile()
      }

      this._capture(this._config.flushInterval)
      this._submit(profiles, start, end)
    } catch (e) {
      this._logger.error(e)
      this.stop()
    }
  }

  _submit (profiles, start, end) {
    const { tags } = this._config

    this._config.exporters
      .map(exporter => {
        return exporter.export({ profiles, start, end, tags })
          .catch((e) => this._logger.error(e))
      })
  }
}

module.exports = { Profiler }
