1'use strict';
2
3const {
4  ArrayPrototypeJoin,
5  SafeSet,
6  Symbol,
7} = primordials;
8
9const { hasTracing } = internalBinding('config');
10const kHandle = Symbol('handle');
11const kEnabled = Symbol('enabled');
12const kCategories = Symbol('categories');
13
14const kMaxTracingCount = 10;
15
16const {
17  ERR_TRACE_EVENTS_CATEGORY_REQUIRED,
18  ERR_TRACE_EVENTS_UNAVAILABLE,
19} = require('internal/errors').codes;
20
21const { ownsProcessState } = require('internal/worker');
22if (!hasTracing || !ownsProcessState)
23  throw new ERR_TRACE_EVENTS_UNAVAILABLE();
24
25const { CategorySet, getEnabledCategories } = internalBinding('trace_events');
26const { customInspectSymbol } = require('internal/util');
27const { format } = require('internal/util/inspect');
28const {
29  validateObject,
30  validateStringArray,
31} = require('internal/validators');
32
33const enabledTracingObjects = new SafeSet();
34
35class Tracing {
36  constructor(categories) {
37    this[kHandle] = new CategorySet(categories);
38    this[kCategories] = categories;
39    this[kEnabled] = false;
40  }
41
42  enable() {
43    if (!this[kEnabled]) {
44      this[kEnabled] = true;
45      this[kHandle].enable();
46      enabledTracingObjects.add(this);
47      if (enabledTracingObjects.size > kMaxTracingCount) {
48        process.emitWarning(
49          'Possible trace_events memory leak detected. There are more than ' +
50          `${kMaxTracingCount} enabled Tracing objects.`,
51        );
52      }
53    }
54  }
55
56  disable() {
57    if (this[kEnabled]) {
58      this[kEnabled] = false;
59      this[kHandle].disable();
60      enabledTracingObjects.delete(this);
61    }
62  }
63
64  get enabled() {
65    return this[kEnabled];
66  }
67
68  get categories() {
69    return ArrayPrototypeJoin(this[kCategories], ',');
70  }
71
72  [customInspectSymbol](depth, opts) {
73    if (typeof depth === 'number' && depth < 0)
74      return this;
75
76    const obj = {
77      enabled: this.enabled,
78      categories: this.categories,
79    };
80    return `Tracing ${format(obj)}`;
81  }
82}
83
84function createTracing(options) {
85  validateObject(options, 'options');
86  validateStringArray(options.categories, 'options.categories');
87
88  if (options.categories.length <= 0)
89    throw new ERR_TRACE_EVENTS_CATEGORY_REQUIRED();
90
91  return new Tracing(options.categories);
92}
93
94module.exports = {
95  createTracing,
96  getEnabledCategories,
97};
98