tracebeam-sdk 0.2.1 → 0.4.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.
package/dist/index.mjs CHANGED
@@ -432,6 +432,8 @@ var SimpleSpanProcessor = class {
432
432
  // src/sdk.ts
433
433
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
434
434
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
435
+ import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
436
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
435
437
  import { resourceFromAttributes } from "@opentelemetry/resources";
436
438
  import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
437
439
 
@@ -708,10 +710,135 @@ function parseBoolEnv(name, defaultValue) {
708
710
  return value.toLowerCase() === "true" || value === "1";
709
711
  }
710
712
 
713
+ // src/metrics/runtime.ts
714
+ function registerRuntimeMetrics(meterProvider) {
715
+ const meter = meterProvider.getMeter("tracebeam-runtime");
716
+ const memoryUsage = meter.createObservableGauge("process.runtime.nodejs.memory.heap_used", {
717
+ description: "Heap memory used in bytes",
718
+ unit: "By"
719
+ });
720
+ const memoryTotal = meter.createObservableGauge("process.runtime.nodejs.memory.heap_total", {
721
+ description: "Total heap memory in bytes",
722
+ unit: "By"
723
+ });
724
+ const memoryRss = meter.createObservableGauge("process.runtime.nodejs.memory.rss", {
725
+ description: "Resident set size in bytes",
726
+ unit: "By"
727
+ });
728
+ const memoryExternal = meter.createObservableGauge("process.runtime.nodejs.memory.external", {
729
+ description: "External memory in bytes",
730
+ unit: "By"
731
+ });
732
+ meter.addBatchObservableCallback(
733
+ (observableResult) => {
734
+ const mem = process.memoryUsage();
735
+ observableResult.observe(memoryUsage, mem.heapUsed);
736
+ observableResult.observe(memoryTotal, mem.heapTotal);
737
+ observableResult.observe(memoryRss, mem.rss);
738
+ observableResult.observe(memoryExternal, mem.external);
739
+ },
740
+ [memoryUsage, memoryTotal, memoryRss, memoryExternal]
741
+ );
742
+ const cpuUser = meter.createObservableGauge("process.runtime.nodejs.cpu.user", {
743
+ description: "CPU user time in microseconds",
744
+ unit: "us"
745
+ });
746
+ const cpuSystem = meter.createObservableGauge("process.runtime.nodejs.cpu.system", {
747
+ description: "CPU system time in microseconds",
748
+ unit: "us"
749
+ });
750
+ meter.addBatchObservableCallback(
751
+ (observableResult) => {
752
+ const cpu = process.cpuUsage();
753
+ observableResult.observe(cpuUser, cpu.user);
754
+ observableResult.observe(cpuSystem, cpu.system);
755
+ },
756
+ [cpuUser, cpuSystem]
757
+ );
758
+ const eventLoopLag = meter.createObservableGauge("process.runtime.nodejs.event_loop.lag", {
759
+ description: "Event loop lag in milliseconds",
760
+ unit: "ms"
761
+ });
762
+ let lastCheck = process.hrtime.bigint();
763
+ let currentLag = 0;
764
+ const measureLag = () => {
765
+ const now = process.hrtime.bigint();
766
+ const expected = 1000n;
767
+ const actual = Number(now - lastCheck) / 1e6;
768
+ currentLag = Math.max(0, actual - 1);
769
+ lastCheck = now;
770
+ setImmediate(measureLag);
771
+ };
772
+ setImmediate(measureLag);
773
+ eventLoopLag.addCallback((observableResult) => {
774
+ observableResult.observe(currentLag);
775
+ });
776
+ const activeHandles = meter.createObservableGauge("process.runtime.nodejs.active_handles", {
777
+ description: "Number of active handles",
778
+ unit: "{handles}"
779
+ });
780
+ const activeRequests = meter.createObservableGauge("process.runtime.nodejs.active_requests", {
781
+ description: "Number of active requests",
782
+ unit: "{requests}"
783
+ });
784
+ meter.addBatchObservableCallback(
785
+ (observableResult) => {
786
+ const handles = process._getActiveHandles?.()?.length ?? 0;
787
+ const requests = process._getActiveRequests?.()?.length ?? 0;
788
+ observableResult.observe(activeHandles, handles);
789
+ observableResult.observe(activeRequests, requests);
790
+ },
791
+ [activeHandles, activeRequests]
792
+ );
793
+ const uptime = meter.createObservableGauge("process.runtime.nodejs.uptime", {
794
+ description: "Process uptime in seconds",
795
+ unit: "s"
796
+ });
797
+ uptime.addCallback((observableResult) => {
798
+ observableResult.observe(process.uptime());
799
+ });
800
+ }
801
+
802
+ // src/metrics/http.ts
803
+ function createHttpMetrics(meterProvider, prefix = "http.server") {
804
+ const meter = meterProvider.getMeter("tracebeam-http");
805
+ return {
806
+ duration: meter.createHistogram(`${prefix}.request.duration`, {
807
+ description: "Duration of HTTP requests",
808
+ unit: "ms"
809
+ }),
810
+ requestCount: meter.createCounter(`${prefix}.request.count`, {
811
+ description: "Total number of HTTP requests",
812
+ unit: "{requests}"
813
+ }),
814
+ errorCount: meter.createCounter(`${prefix}.error.count`, {
815
+ description: "Total number of HTTP errors (5xx)",
816
+ unit: "{errors}"
817
+ }),
818
+ activeRequests: meter.createUpDownCounter(`${prefix}.active_requests`, {
819
+ description: "Number of active HTTP requests",
820
+ unit: "{requests}"
821
+ })
822
+ };
823
+ }
824
+ function recordHttpRequest(metrics3, durationMs, attributes) {
825
+ const labels = {
826
+ "http.method": attributes["http.method"],
827
+ "http.route": attributes["http.route"],
828
+ "http.status_code": String(attributes["http.status_code"])
829
+ };
830
+ metrics3.duration.record(durationMs, labels);
831
+ metrics3.requestCount.add(1, labels);
832
+ if (attributes["http.status_code"] >= 500) {
833
+ metrics3.errorCount.add(1, labels);
834
+ }
835
+ }
836
+
711
837
  // src/sdk.ts
712
838
  var TraceBeamSDK = class _TraceBeamSDK {
713
839
  config;
714
840
  provider;
841
+ meterProvider;
715
842
  tracer;
716
843
  isInitialized = true;
717
844
  globalTags = {};
@@ -724,39 +851,65 @@ var TraceBeamSDK = class _TraceBeamSDK {
724
851
  validateConfig(config);
725
852
  this.config = mergeConfig(config);
726
853
  const baseUrl = this.config.endpoint.replace(/\/$/, "");
727
- const exporterUrl = `${baseUrl}/v1/traces`;
728
- const exporter = new OTLPTraceExporter({
729
- url: exporterUrl,
854
+ const traceExporterUrl = `${baseUrl}/v1/traces`;
855
+ const metricExporterUrl = `${baseUrl}/v1/metrics`;
856
+ const traceExporter = new OTLPTraceExporter({
857
+ url: traceExporterUrl,
730
858
  headers: {
731
859
  "Authorization": `Bearer ${this.config.apiKey}`
732
860
  }
733
861
  });
734
862
  const spanProcessors = [];
735
- spanProcessors.push(new BatchSpanProcessor(exporter, {
863
+ spanProcessors.push(new BatchSpanProcessor(traceExporter, {
736
864
  maxExportBatchSize: this.config.batchSize,
737
865
  scheduledDelayMillis: this.config.flushInterval
738
866
  }));
739
867
  if (this.config.debug) {
740
868
  spanProcessors.push(new SimpleSpanProcessor(new ConsoleSpanExporter()));
741
- console.debug("[tracebeam] Initialized OTLP", {
742
- url: exporterUrl,
869
+ console.debug("[tracebeam] Initialized OTLP Traces", {
870
+ url: traceExporterUrl,
743
871
  projectId: this.config.projectId
744
872
  });
745
873
  }
874
+ const resource = resourceFromAttributes({
875
+ [SemanticResourceAttributes.SERVICE_NAME]: this.config.projectId,
876
+ [SemanticResourceAttributes.SERVICE_VERSION]: this.config.environment,
877
+ [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: this.config.environment,
878
+ "telemetry.sdk.language": "nodejs",
879
+ "telemetry.sdk.name": "tracebeam-sdk",
880
+ "telemetry.sdk.version": "0.2.1"
881
+ });
746
882
  this.provider = new NodeTracerProvider({
747
- resource: resourceFromAttributes({
748
- [SemanticResourceAttributes.SERVICE_NAME]: this.config.projectId,
749
- [SemanticResourceAttributes.SERVICE_VERSION]: this.config.environment,
750
- [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: this.config.environment,
751
- "telemetry.sdk.language": "nodejs",
752
- "telemetry.sdk.name": "tracebeam-sdk",
753
- "telemetry.sdk.version": "0.2.1"
754
- }),
883
+ resource,
755
884
  spanProcessors
756
885
  });
757
886
  this.provider.register();
887
+ const metricExporter = new OTLPMetricExporter({
888
+ url: metricExporterUrl,
889
+ headers: {
890
+ "Authorization": `Bearer ${this.config.apiKey}`
891
+ }
892
+ });
893
+ this.meterProvider = new MeterProvider({
894
+ resource,
895
+ readers: [
896
+ new PeriodicExportingMetricReader({
897
+ exporter: metricExporter,
898
+ exportIntervalMillis: this.config.flushInterval
899
+ // Match config
900
+ })
901
+ ]
902
+ });
903
+ api.metrics.setGlobalMeterProvider(this.meterProvider);
904
+ registerRuntimeMetrics(this.meterProvider);
905
+ if (this.config.debug) {
906
+ console.debug("[tracebeam] Initialized OTLP Metrics with runtime metrics", {
907
+ url: metricExporterUrl
908
+ });
909
+ }
758
910
  registerInstrumentations({
759
911
  tracerProvider: this.provider,
912
+ meterProvider: this.meterProvider,
760
913
  instrumentations: [
761
914
  getNodeAutoInstrumentations({
762
915
  // Disable some noisy instrumentations
@@ -771,6 +924,18 @@ var TraceBeamSDK = class _TraceBeamSDK {
771
924
  const config = loadConfigFromEnv();
772
925
  return new _TraceBeamSDK(config);
773
926
  }
927
+ /**
928
+ * Get the OpenTelemetry Meter for creating custom metrics
929
+ */
930
+ getMeter(name, version) {
931
+ return this.meterProvider.getMeter(name, version);
932
+ }
933
+ /**
934
+ * Get the MeterProvider for advanced metric creation
935
+ */
936
+ getMeterProvider() {
937
+ return this.meterProvider;
938
+ }
774
939
  /**
775
940
  * Capture an exception/error
776
941
  */
@@ -867,10 +1032,12 @@ var TraceBeamSDK = class _TraceBeamSDK {
867
1032
  }
868
1033
  async flush() {
869
1034
  await this.provider.forceFlush();
1035
+ await this.meterProvider.forceFlush();
870
1036
  }
871
1037
  async close() {
872
1038
  this.isInitialized = false;
873
1039
  await this.provider.shutdown();
1040
+ await this.meterProvider.shutdown();
874
1041
  }
875
1042
  isActive() {
876
1043
  return this.isInitialized;
@@ -889,8 +1056,10 @@ export {
889
1056
  ConfigError,
890
1057
  DEFAULT_CONFIG,
891
1058
  TraceBeamSDK,
1059
+ createHttpMetrics,
892
1060
  loadConfigFromEnv,
893
1061
  mergeConfig,
1062
+ recordHttpRequest,
894
1063
  validateConfig
895
1064
  };
896
1065
  //# sourceMappingURL=index.mjs.map