@sentry/profiling-node 8.8.0 → 8.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/bindings/cpu_profiler.cc +155 -60
  2. package/lib/cjs/index.js +479 -154
  3. package/lib/cjs/index.js.map +1 -1
  4. package/lib/esm/index.js +478 -154
  5. package/lib/esm/index.js.map +1 -1
  6. package/lib/sentry_cpu_profiler-darwin-arm64-108.node +0 -0
  7. package/lib/sentry_cpu_profiler-darwin-arm64-115.node +0 -0
  8. package/lib/sentry_cpu_profiler-darwin-arm64-127.node +0 -0
  9. package/lib/sentry_cpu_profiler-darwin-arm64-93.node +0 -0
  10. package/lib/sentry_cpu_profiler-darwin-x64-108.node +0 -0
  11. package/lib/sentry_cpu_profiler-darwin-x64-115.node +0 -0
  12. package/lib/sentry_cpu_profiler-darwin-x64-127.node +0 -0
  13. package/lib/sentry_cpu_profiler-darwin-x64-93.node +0 -0
  14. package/lib/sentry_cpu_profiler-linux-arm64-glibc-108.node +0 -0
  15. package/lib/sentry_cpu_profiler-linux-arm64-glibc-115.node +0 -0
  16. package/lib/sentry_cpu_profiler-linux-arm64-glibc-127.node +0 -0
  17. package/lib/sentry_cpu_profiler-linux-arm64-glibc-93.node +0 -0
  18. package/lib/sentry_cpu_profiler-linux-arm64-musl-108.node +0 -0
  19. package/lib/sentry_cpu_profiler-linux-arm64-musl-115.node +0 -0
  20. package/lib/sentry_cpu_profiler-linux-arm64-musl-127.node +0 -0
  21. package/lib/sentry_cpu_profiler-linux-arm64-musl-93.node +0 -0
  22. package/lib/sentry_cpu_profiler-linux-x64-glibc-108.node +0 -0
  23. package/lib/sentry_cpu_profiler-linux-x64-glibc-115.node +0 -0
  24. package/lib/sentry_cpu_profiler-linux-x64-glibc-127.node +0 -0
  25. package/lib/sentry_cpu_profiler-linux-x64-glibc-93.node +0 -0
  26. package/lib/sentry_cpu_profiler-linux-x64-musl-108.node +0 -0
  27. package/lib/sentry_cpu_profiler-linux-x64-musl-115.node +0 -0
  28. package/lib/sentry_cpu_profiler-linux-x64-musl-127.node +0 -0
  29. package/lib/sentry_cpu_profiler-linux-x64-musl-93.node +0 -0
  30. package/lib/sentry_cpu_profiler-win32-x64-108.node +0 -0
  31. package/lib/sentry_cpu_profiler-win32-x64-115.node +0 -0
  32. package/lib/sentry_cpu_profiler-win32-x64-127.node +0 -0
  33. package/lib/sentry_cpu_profiler-win32-x64-93.node +0 -0
  34. package/lib/types/profiling-node/src/cpu_profiler.d.ts +16 -0
  35. package/lib/types/profiling-node/src/cpu_profiler.d.ts.map +1 -0
  36. package/lib/types/profiling-node/src/debug-build.d.ts.map +1 -0
  37. package/lib/types/profiling-node/src/index.d.ts.map +1 -0
  38. package/lib/types/profiling-node/src/integration.d.ts +57 -0
  39. package/lib/types/profiling-node/src/integration.d.ts.map +1 -0
  40. package/lib/types/profiling-node/src/nodeVersion.d.ts.map +1 -0
  41. package/lib/types/{spanProfileUtils.d.ts → profiling-node/src/spanProfileUtils.d.ts} +2 -2
  42. package/lib/types/profiling-node/src/spanProfileUtils.d.ts.map +1 -0
  43. package/lib/types/profiling-node/src/types.d.ts +60 -0
  44. package/lib/types/profiling-node/src/types.d.ts.map +1 -0
  45. package/lib/types/{utils.d.ts → profiling-node/src/utils.d.ts} +30 -4
  46. package/lib/types/profiling-node/src/utils.d.ts.map +1 -0
  47. package/lib/types/types/src/debugMeta.d.ts +28 -0
  48. package/lib/types/types/src/debugMeta.d.ts.map +1 -0
  49. package/lib/types/types/src/measurement.d.ts +24 -0
  50. package/lib/types/types/src/measurement.d.ts.map +1 -0
  51. package/lib/types/types/src/profiling.d.ts +126 -0
  52. package/lib/types/types/src/profiling.d.ts.map +1 -0
  53. package/lib/types-ts3.8/profiling-node/src/cpu_profiler.d.ts +16 -0
  54. package/lib/types-ts3.8/profiling-node/src/integration.d.ts +57 -0
  55. package/lib/types-ts3.8/{spanProfileUtils.d.ts → profiling-node/src/spanProfileUtils.d.ts} +2 -2
  56. package/lib/types-ts3.8/profiling-node/src/types.d.ts +60 -0
  57. package/lib/types-ts3.8/{utils.d.ts → profiling-node/src/utils.d.ts} +30 -4
  58. package/lib/types-ts3.8/types/src/debugMeta.d.ts +28 -0
  59. package/lib/types-ts3.8/types/src/measurement.d.ts +24 -0
  60. package/lib/types-ts3.8/types/src/profiling.d.ts +126 -0
  61. package/package.json +5 -5
  62. package/lib/types/cpu_profiler.d.ts +0 -10
  63. package/lib/types/cpu_profiler.d.ts.map +0 -1
  64. package/lib/types/debug-build.d.ts.map +0 -1
  65. package/lib/types/index.d.ts.map +0 -1
  66. package/lib/types/integration.d.ts +0 -14
  67. package/lib/types/integration.d.ts.map +0 -1
  68. package/lib/types/nodeVersion.d.ts.map +0 -1
  69. package/lib/types/spanProfileUtils.d.ts.map +0 -1
  70. package/lib/types/types.d.ts +0 -100
  71. package/lib/types/types.d.ts.map +0 -1
  72. package/lib/types/utils.d.ts.map +0 -1
  73. package/lib/types-ts3.8/cpu_profiler.d.ts +0 -10
  74. package/lib/types-ts3.8/integration.d.ts +0 -14
  75. package/lib/types-ts3.8/types.d.ts +0 -100
  76. /package/lib/types/{debug-build.d.ts → profiling-node/src/debug-build.d.ts} +0 -0
  77. /package/lib/types/{index.d.ts → profiling-node/src/index.d.ts} +0 -0
  78. /package/lib/types/{nodeVersion.d.ts → profiling-node/src/nodeVersion.d.ts} +0 -0
  79. /package/lib/types-ts3.8/{debug-build.d.ts → profiling-node/src/debug-build.d.ts} +0 -0
  80. /package/lib/types-ts3.8/{index.d.ts → profiling-node/src/index.d.ts} +0 -0
  81. /package/lib/types-ts3.8/{nodeVersion.d.ts → profiling-node/src/nodeVersion.d.ts} +0 -0
@@ -10,6 +10,7 @@
10
10
  #include <v8-profiler.h>
11
11
  #include <v8.h>
12
12
 
13
+ #include <chrono>
13
14
  #include <functional>
14
15
  #include <string>
15
16
  #include <unordered_map>
@@ -23,6 +24,10 @@ static const v8::CpuProfilingNamingMode
23
24
  static const v8::CpuProfilingLoggingMode
24
25
  kDefaultLoggingMode(v8::CpuProfilingLoggingMode::kEagerLogging);
25
26
 
27
+ enum ProfileFormat {
28
+ kFormatThread = 0,
29
+ kFormatChunk = 1,
30
+ };
26
31
  // Allow users to override the default logging mode via env variable. This is
27
32
  // useful because sometimes the flow of the profiled program can be to execute
28
33
  // many sequential transaction - in that case, it may be preferable to set eager
@@ -50,6 +55,12 @@ v8::CpuProfilingLoggingMode GetLoggingMode() {
50
55
  return kDefaultLoggingMode;
51
56
  }
52
57
 
58
+ uint64_t timestamp_milliseconds() {
59
+ return std::chrono::duration_cast<std::chrono::milliseconds>(
60
+ std::chrono::system_clock::now().time_since_epoch())
61
+ .count();
62
+ }
63
+
53
64
  class SentryProfile;
54
65
  class Profiler;
55
66
 
@@ -241,6 +252,7 @@ public:
241
252
  class SentryProfile {
242
253
  private:
243
254
  uint64_t started_at;
255
+ uint64_t timestamp;
244
256
  uint16_t heap_write_index = 0;
245
257
  uint16_t cpu_write_index = 0;
246
258
 
@@ -258,7 +270,7 @@ private:
258
270
 
259
271
  public:
260
272
  explicit SentryProfile(const char *id)
261
- : started_at(uv_hrtime()),
273
+ : started_at(uv_hrtime()), timestamp(timestamp_milliseconds()),
262
274
  memory_sampler_cb([this](uint64_t ts, v8::HeapStatistics &stats) {
263
275
  if ((heap_write_index >= heap_stats_ts.capacity()) ||
264
276
  heap_write_index >= heap_stats_usage.capacity()) {
@@ -302,6 +314,7 @@ public:
302
314
  const std::vector<uint64_t> &cpu_usage_timestamps() const;
303
315
  const std::vector<double> &cpu_usage_values() const;
304
316
  const uint16_t &cpu_usage_write_index() const;
317
+ const uint64_t &profile_start_timestamp() const;
305
318
 
306
319
  void Start(Profiler *profiler);
307
320
  v8::CpuProfile *Stop(Profiler *profiler);
@@ -314,6 +327,7 @@ void SentryProfile::Start(Profiler *profiler) {
314
327
  .ToLocalChecked();
315
328
 
316
329
  started_at = uv_hrtime();
330
+ timestamp = timestamp_milliseconds();
317
331
 
318
332
  // Initialize the CPU Profiler
319
333
  profiler->cpu_profiler->StartProfiling(
@@ -368,6 +382,9 @@ const std::vector<double> &SentryProfile::cpu_usage_values() const {
368
382
  const uint16_t &SentryProfile::cpu_usage_write_index() const {
369
383
  return cpu_write_index;
370
384
  };
385
+ const uint64_t &SentryProfile::profile_start_timestamp() const {
386
+ return timestamp;
387
+ }
371
388
 
372
389
  static void CleanupSentryProfile(Profiler *profiler,
373
390
  SentryProfile *sentry_profile,
@@ -528,8 +545,9 @@ CreateFrameNode(const napi_env &env, const v8::CpuProfileNode &node,
528
545
  return js_node;
529
546
  };
530
547
 
531
- napi_value CreateSample(const napi_env &env, const uint32_t stack_id,
532
- const int64_t sample_timestamp_us,
548
+ napi_value CreateSample(const napi_env &env, const enum ProfileFormat format,
549
+ const uint32_t stack_id, const int64_t sample_timestamp,
550
+ const double chunk_timestamp,
533
551
  const uint32_t thread_id) {
534
552
  napi_value js_node;
535
553
  napi_create_object(env, &js_node);
@@ -543,11 +561,20 @@ napi_value CreateSample(const napi_env &env, const uint32_t stack_id,
543
561
  NAPI_AUTO_LENGTH, &thread_id_prop);
544
562
  napi_set_named_property(env, js_node, "thread_id", thread_id_prop);
545
563
 
546
- napi_value elapsed_since_start_ns_prop;
547
- napi_create_int64(env, sample_timestamp_us * 1000,
548
- &elapsed_since_start_ns_prop);
549
- napi_set_named_property(env, js_node, "elapsed_since_start_ns",
550
- elapsed_since_start_ns_prop);
564
+ switch (format) {
565
+ case ProfileFormat::kFormatThread: {
566
+ napi_value timestamp;
567
+ napi_create_int64(env, sample_timestamp, &timestamp);
568
+ napi_set_named_property(env, js_node, "elapsed_since_start_ns", timestamp);
569
+ } break;
570
+ case ProfileFormat::kFormatChunk: {
571
+ napi_value timestamp;
572
+ napi_create_double(env, chunk_timestamp, &timestamp);
573
+ napi_set_named_property(env, js_node, "timestamp", timestamp);
574
+ } break;
575
+ default:
576
+ break;
577
+ }
551
578
 
552
579
  return js_node;
553
580
  };
@@ -566,11 +593,13 @@ std::string hashCpuProfilerNodeByPath(const v8::CpuProfileNode *node,
566
593
  }
567
594
 
568
595
  static void GetSamples(const napi_env &env, const v8::CpuProfile *profile,
596
+ ProfileFormat format,
597
+ const uint64_t profile_start_timestamp_ms,
569
598
  const uint32_t thread_id, napi_value &samples,
570
599
  napi_value &stacks, napi_value &frames,
571
600
  napi_value &resources) {
572
601
  const int64_t profile_start_time_us = profile->GetStartTime();
573
- const int sampleCount = profile->GetSamplesCount();
602
+ const int64_t sampleCount = profile->GetSamplesCount();
574
603
 
575
604
  uint32_t unique_stack_id = 0;
576
605
  uint32_t unique_frame_id = 0;
@@ -590,7 +619,7 @@ static void GetSamples(const napi_env &env, const v8::CpuProfile *profile,
590
619
  uint32_t stack_index = unique_stack_id;
591
620
 
592
621
  const v8::CpuProfileNode *node = profile->GetSample(i);
593
- const int64_t sample_timestamp = profile->GetSampleTimestamp(i);
622
+ const int64_t sample_timestamp_us = profile->GetSampleTimestamp(i);
594
623
 
595
624
  // If a node was only on top of the stack once, then it will only ever
596
625
  // be inserted once and there is no need for hashing.
@@ -609,8 +638,16 @@ static void GetSamples(const napi_env &env, const v8::CpuProfile *profile,
609
638
  }
610
639
  }
611
640
 
612
- napi_value sample = CreateSample(
613
- env, stack_index, sample_timestamp - profile_start_time_us, thread_id);
641
+ uint64_t sample_delta_us = sample_timestamp_us - profile_start_time_us;
642
+ uint64_t sample_timestamp_ns = sample_delta_us * 1e3;
643
+ uint64_t sample_offset_from_profile_start_ms =
644
+ (sample_timestamp_us - profile_start_time_us) * 1e-3;
645
+ double seconds_since_start =
646
+ profile_start_timestamp_ms + sample_offset_from_profile_start_ms;
647
+
648
+ napi_value sample = nullptr;
649
+ sample = CreateSample(env, format, stack_index, sample_timestamp_ns,
650
+ seconds_since_start, thread_id);
614
651
 
615
652
  if (stack_index != unique_stack_id) {
616
653
  napi_value index;
@@ -671,19 +708,19 @@ static void GetSamples(const napi_env &env, const v8::CpuProfile *profile,
671
708
  }
672
709
  }
673
710
 
674
- static napi_value
675
- TranslateMeasurementsDouble(const napi_env &env, const char *unit,
676
- const uint16_t size,
677
- const std::vector<double> &values,
678
- const std::vector<uint64_t> &timestamps) {
679
- if (size > values.size() || size > timestamps.size()) {
711
+ static napi_value TranslateMeasurementsDouble(
712
+ const napi_env &env, const enum ProfileFormat format, const char *unit,
713
+ const uint64_t profile_start_timestamp_ms, const uint16_t size,
714
+ const std::vector<double> &values,
715
+ const std::vector<uint64_t> &timestamps_ns) {
716
+ if (size > values.size() || size > timestamps_ns.size()) {
680
717
  napi_throw_range_error(env, "NAPI_ERROR",
681
718
  "CPU measurement size is larger than the number of "
682
719
  "values or timestamps");
683
720
  return nullptr;
684
721
  }
685
722
 
686
- if (values.size() != timestamps.size()) {
723
+ if (values.size() != timestamps_ns.size()) {
687
724
  napi_throw_range_error(env, "NAPI_ERROR",
688
725
  "CPU measurement entries are corrupt, expected "
689
726
  "values and timestamps to be of equal length");
@@ -713,11 +750,19 @@ TranslateMeasurementsDouble(const napi_env &env, const char *unit,
713
750
  }
714
751
  }
715
752
 
716
- napi_value ts;
717
- napi_create_int64(env, timestamps[i], &ts);
718
-
719
753
  napi_set_named_property(env, entry, "value", value);
720
- napi_set_named_property(env, entry, "elapsed_since_start_ns", ts);
754
+
755
+ if (format == ProfileFormat::kFormatThread) {
756
+ napi_value ts;
757
+ napi_create_int64(env, timestamps_ns[i], &ts);
758
+ napi_set_named_property(env, entry, "elapsed_since_start_ns", ts);
759
+ } else if (format == ProfileFormat::kFormatChunk) {
760
+ napi_value ts;
761
+ napi_create_double(
762
+ env, profile_start_timestamp_ms + (timestamps_ns[i] * 1e-6), &ts);
763
+ napi_set_named_property(env, entry, "timestamp", ts);
764
+ }
765
+
721
766
  napi_set_element(env, values_array, i, entry);
722
767
  }
723
768
 
@@ -727,17 +772,19 @@ TranslateMeasurementsDouble(const napi_env &env, const char *unit,
727
772
  }
728
773
 
729
774
  static napi_value
730
- TranslateMeasurements(const napi_env &env, const char *unit,
775
+ TranslateMeasurements(const napi_env &env, const enum ProfileFormat format,
776
+ const char *unit,
777
+ const uint64_t profile_start_timestamp_ms,
731
778
  const uint16_t size, const std::vector<uint64_t> &values,
732
- const std::vector<uint64_t> &timestamps) {
733
- if (size > values.size() || size > timestamps.size()) {
779
+ const std::vector<uint64_t> &timestamps_ns) {
780
+ if (size > values.size() || size > timestamps_ns.size()) {
734
781
  napi_throw_range_error(env, "NAPI_ERROR",
735
782
  "Memory measurement size is larger than the number "
736
783
  "of values or timestamps");
737
784
  return nullptr;
738
785
  }
739
786
 
740
- if (values.size() != timestamps.size()) {
787
+ if (values.size() != timestamps_ns.size()) {
741
788
  napi_throw_range_error(env, "NAPI_ERROR",
742
789
  "Memory measurement entries are corrupt, expected "
743
790
  "values and timestamps to be of equal length");
@@ -761,11 +808,22 @@ TranslateMeasurements(const napi_env &env, const char *unit,
761
808
  napi_value value;
762
809
  napi_create_int64(env, values[i], &value);
763
810
 
764
- napi_value ts;
765
- napi_create_int64(env, timestamps[i], &ts);
766
-
767
811
  napi_set_named_property(env, entry, "value", value);
768
- napi_set_named_property(env, entry, "elapsed_since_start_ns", ts);
812
+ switch (format) {
813
+ case ProfileFormat::kFormatThread: {
814
+ napi_value ts;
815
+ napi_create_int64(env, timestamps_ns[i], &ts);
816
+ napi_set_named_property(env, entry, "elapsed_since_start_ns", ts);
817
+ } break;
818
+ case ProfileFormat::kFormatChunk: {
819
+ napi_value ts;
820
+ napi_create_double(
821
+ env, profile_start_timestamp_ms + (timestamps_ns[i] * 1e-6), &ts);
822
+ napi_set_named_property(env, entry, "timestamp", ts);
823
+ } break;
824
+ default:
825
+ break;
826
+ }
769
827
  napi_set_element(env, values_array, i, entry);
770
828
  }
771
829
 
@@ -776,6 +834,8 @@ TranslateMeasurements(const napi_env &env, const char *unit,
776
834
 
777
835
  static napi_value TranslateProfile(const napi_env &env,
778
836
  const v8::CpuProfile *profile,
837
+ const enum ProfileFormat format,
838
+ const uint64_t profile_start_timestamp_ms,
779
839
  const uint32_t thread_id,
780
840
  bool collect_resources) {
781
841
  napi_value js_profile;
@@ -805,7 +865,8 @@ static napi_value TranslateProfile(const napi_env &env,
805
865
  napi_set_named_property(env, js_profile, "profiler_logging_mode",
806
866
  logging_mode);
807
867
 
808
- GetSamples(env, profile, thread_id, samples, stacks, frames, resources);
868
+ GetSamples(env, profile, format, profile_start_timestamp_ms, thread_id,
869
+ samples, stacks, frames, resources);
809
870
 
810
871
  if (collect_resources) {
811
872
  napi_set_named_property(env, js_profile, "resources", resources);
@@ -892,14 +953,14 @@ static napi_value StartProfiling(napi_env env, napi_callback_info info) {
892
953
  // StopProfiling(string title)
893
954
  // https://v8docs.nodesource.com/node-18.2/d2/d34/classv8_1_1_cpu_profiler.html#a40ca4c8a8aa4c9233aa2a2706457cc80
894
955
  static napi_value StopProfiling(napi_env env, napi_callback_info info) {
895
- size_t argc = 3;
896
- napi_value argv[3];
956
+ size_t argc = 4;
957
+ napi_value argv[4];
897
958
 
898
959
  assert(napi_get_cb_info(env, info, &argc, argv, NULL, NULL) == napi_ok);
899
960
 
900
- if (argc < 2) {
961
+ if (argc < 3) {
901
962
  napi_throw_error(env, "NAPI_ERROR",
902
- "StopProfiling expects at least two arguments.");
963
+ "StopProfiling expects at least three arguments.");
903
964
 
904
965
  napi_value napi_null;
905
966
  assert(napi_get_null(env, &napi_null) == napi_ok);
@@ -921,14 +982,17 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
921
982
  return napi_null;
922
983
  }
923
984
 
924
- // Verify the second argument is a number
925
- napi_valuetype callbacktype1;
926
- assert(napi_typeof(env, argv[1], &callbacktype1) == napi_ok);
985
+ size_t len;
986
+ assert(napi_get_value_string_utf8(env, argv[0], NULL, 0, &len) == napi_ok);
927
987
 
928
- if (callbacktype1 != napi_number) {
988
+ char *title = (char *)malloc(len + 1);
989
+ assert(napi_get_value_string_utf8(env, argv[0], title, len + 1, &len) ==
990
+ napi_ok);
991
+
992
+ if (len < 1) {
929
993
  napi_throw_error(
930
994
  env, "NAPI_ERROR",
931
- "StopProfiling expects a thread_id integer as second argument.");
995
+ "StopProfiling expects a non empty string as first argument.");
932
996
 
933
997
  napi_value napi_null;
934
998
  assert(napi_get_null(env, &napi_null) == napi_ok);
@@ -936,16 +1000,13 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
936
1000
  return napi_null;
937
1001
  }
938
1002
 
939
- size_t len;
940
- assert(napi_get_value_string_utf8(env, argv[0], NULL, 0, &len) == napi_ok);
941
-
942
- char *title = (char *)malloc(len + 1);
943
- assert(napi_get_value_string_utf8(env, argv[0], title, len + 1, &len) ==
944
- napi_ok);
1003
+ // Verify the second argument is a number
1004
+ napi_valuetype callbacktype1;
1005
+ assert(napi_typeof(env, argv[1], &callbacktype1) == napi_ok);
945
1006
 
946
- if (len < 1) {
1007
+ if (callbacktype1 != napi_number) {
947
1008
  napi_throw_error(env, "NAPI_ERROR",
948
- "StopProfiling expects a string as first argument.");
1009
+ "StopProfiling expects a format type as second argument.");
949
1010
 
950
1011
  napi_value napi_null;
951
1012
  assert(napi_get_null(env, &napi_null) == napi_ok);
@@ -953,9 +1014,27 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
953
1014
  return napi_null;
954
1015
  }
955
1016
 
1017
+ // Verify the second argument is a number
1018
+ napi_valuetype callbacktype2;
1019
+ assert(napi_typeof(env, argv[2], &callbacktype2) == napi_ok);
1020
+
1021
+ if (callbacktype2 != napi_number) {
1022
+ napi_throw_error(
1023
+ env, "NAPI_ERROR",
1024
+ "StopProfiling expects a thread_id integer as third argument.");
1025
+
1026
+ napi_value napi_null;
1027
+ assert(napi_get_null(env, &napi_null) == napi_ok);
1028
+ return napi_null;
1029
+ }
1030
+
1031
+ // Get the value of the second argument and convert it to uint8
1032
+ int32_t format;
1033
+ assert(napi_get_value_int32(env, argv[1], &format) == napi_ok);
1034
+
956
1035
  // Get the value of the second argument and convert it to uint64
957
1036
  int64_t thread_id;
958
- assert(napi_get_value_int64(env, argv[1], &thread_id) == napi_ok);
1037
+ assert(napi_get_value_int64(env, argv[2], &thread_id) == napi_ok);
959
1038
 
960
1039
  // Get profiler from instance data
961
1040
  Profiler *profiler;
@@ -967,7 +1046,6 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
967
1046
 
968
1047
  napi_value napi_null;
969
1048
  assert(napi_get_null(env, &napi_null) == napi_ok);
970
-
971
1049
  return napi_null;
972
1050
  }
973
1051
 
@@ -994,23 +1072,39 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
994
1072
  };
995
1073
 
996
1074
  napi_valuetype callbacktype3;
997
- assert(napi_typeof(env, argv[2], &callbacktype3) == napi_ok);
1075
+ assert(napi_typeof(env, argv[3], &callbacktype3) == napi_ok);
998
1076
 
999
1077
  bool collect_resources;
1000
- napi_get_value_bool(env, argv[2], &collect_resources);
1078
+ napi_get_value_bool(env, argv[3], &collect_resources);
1079
+
1080
+ const ProfileFormat format_type = static_cast<ProfileFormat>(format);
1081
+
1082
+ if (format_type != ProfileFormat::kFormatThread &&
1083
+ format_type != ProfileFormat::kFormatChunk) {
1084
+ napi_throw_error(
1085
+ env, "NAPI_ERROR",
1086
+ "StopProfiling expects a valid format type as second argument.");
1087
+
1088
+ napi_value napi_null;
1089
+ assert(napi_get_null(env, &napi_null) == napi_ok);
1090
+ return napi_null;
1091
+ }
1001
1092
 
1002
- napi_value js_profile =
1003
- TranslateProfile(env, cpu_profile, thread_id, collect_resources);
1093
+ napi_value js_profile = TranslateProfile(
1094
+ env, cpu_profile, format_type, profile->second->profile_start_timestamp(),
1095
+ thread_id, collect_resources);
1004
1096
 
1005
1097
  napi_value measurements;
1006
1098
  napi_create_object(env, &measurements);
1007
1099
 
1008
1100
  if (profile->second->heap_usage_write_index() > 0) {
1009
1101
  static const char *memory_unit = "byte";
1010
- napi_value heap_usage_measurements = TranslateMeasurements(
1011
- env, memory_unit, profile->second->heap_usage_write_index(),
1012
- profile->second->heap_usage_values(),
1013
- profile->second->heap_usage_timestamps());
1102
+ napi_value heap_usage_measurements =
1103
+ TranslateMeasurements(env, format_type, memory_unit,
1104
+ profile->second->profile_start_timestamp(),
1105
+ profile->second->heap_usage_write_index(),
1106
+ profile->second->heap_usage_values(),
1107
+ profile->second->heap_usage_timestamps());
1014
1108
 
1015
1109
  if (heap_usage_measurements != nullptr) {
1016
1110
  napi_set_named_property(env, measurements, "memory_footprint",
@@ -1021,7 +1115,8 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
1021
1115
  if (profile->second->cpu_usage_write_index() > 0) {
1022
1116
  static const char *cpu_unit = "percent";
1023
1117
  napi_value cpu_usage_measurements = TranslateMeasurementsDouble(
1024
- env, cpu_unit, profile->second->cpu_usage_write_index(),
1118
+ env, format_type, cpu_unit, profile->second->profile_start_timestamp(),
1119
+ profile->second->cpu_usage_write_index(),
1025
1120
  profile->second->cpu_usage_values(),
1026
1121
  profile->second->cpu_usage_timestamps());
1027
1122