1+ 'use strict' ;
2+
3+ const { DiagConsoleLogger, DiagLogLevel, ValueType, diag} = require ( '@opentelemetry/api' ) ;
4+ const { OTLPMetricExporter} = require ( '@opentelemetry/exporter-metrics-otlp-proto' ) ;
5+
6+ const {
7+ ExponentialHistogramAggregation, MeterProvider, PeriodicExportingMetricReader, View,
8+ } = require ( '@opentelemetry/sdk-metrics' ) ;
9+ const { Resource} = require ( '@opentelemetry/resources' ) ;
10+ const {
11+ SemanticResourceAttributes,
12+ } = require ( '@opentelemetry/semantic-conventions' ) ;
13+ const os = require ( 'os' ) ;
14+ const { v4 : uuidv4 } = require ( 'uuid' ) ;
15+ const metricPrefix = process . env . METRIC_PREFIX
16+ const workflowIDCount = parseInt ( process . env . WORKFLOW_ID_COUNT ) ;
17+ const customerIDCount = parseInt ( process . env . CUSTOMER_ID_COUNT ) ;
18+ const otlpEndpoint = process . env . OTLP_ENDPOINT ;
19+ const serviceName = process . env . SERVICE_NAME ;
20+ const otelMetricExporterFrequency = parseInt ( process . env . OTLP_METRIC_EXPORTER_FREQUENCY ) ;
21+ const otelMeterName = process . env . OTLP_METER_NAME ;
22+ const environment = process . env . ENVIRONMENT ;
23+
24+ // Global variables
25+ // Toggle this number below to explode cardinality.
26+ const workflowIDs = Array . from ( { length : workflowIDCount } , ( ) => uuidv4 ( ) ) ;
27+ const customerIDs = Array . from ( { length : customerIDCount } , ( ) => uuidv4 ( ) ) ;
28+
29+
30+ // Optional and only needed to see the internal diagnostic logging (during development)
31+ diag . setLogger ( new DiagConsoleLogger ( ) , DiagLogLevel . DEBUG ) ;
32+
33+ const metricExporter = new OTLPMetricExporter ( {
34+ url : otlpEndpoint
35+ } ) ;
36+
37+ // Create an instance of the metric provider
38+ const meterProvider = new MeterProvider ( {
39+ resource : new Resource ( {
40+ [ SemanticResourceAttributes . SERVICE_NAME ] : serviceName ,
41+ } )
42+ } ) ;
43+
44+ meterProvider . addMetricReader ( new PeriodicExportingMetricReader ( {
45+ exporter : metricExporter , // exporter: new ConsoleMetricExporter(),
46+ exportIntervalMillis : otelMetricExporterFrequency ,
47+ } ) ) ;
48+
49+ const meter = meterProvider . getMeter ( otelMeterName ) ;
50+
51+ // Create Observable Gauges
52+ const memoryUsageGauge = meter . createObservableGauge ( `${ metricPrefix } _memory_usage` , {
53+ description : 'Tracks the memory usage of the application' , valueType : ValueType . DOUBLE
54+ } ) ;
55+
56+ const concurrencyGauge = meter . createObservableGauge ( `${ metricPrefix } _concurrency` , {
57+ description : 'Current concurrency level' , valueType : ValueType . INT
58+ } ) ;
59+
60+ const cpuUsageGauge = meter . createObservableGauge ( `${ metricPrefix } _cpu_usage` , {
61+ description : 'CPU usage percentage' , valueType : ValueType . DOUBLE
62+ } ) ;
63+
64+ const runInTimeGauge = meter . createObservableGauge ( `${ metricPrefix } _run_time` , {
65+ description : 'Run time in seconds' , valueType : ValueType . INT
66+ } ) ;
67+
68+ // Base Label Sets
69+ const attributes = { pid : process . pid , environment : environment } ;
70+
71+ // Callbacks for Observable Gauges
72+ concurrencyGauge . addCallback ( ( observableResult ) => {
73+ workflowIDs . forEach ( workflow_id => {
74+ customerIDs . forEach ( customer_id => {
75+ let concurrency = Math . floor ( Math . random ( ) * 10 ) + 1 ;
76+ observableResult . observe ( concurrency , {
77+ ...attributes , 'workflow_id' : workflow_id , 'customer_id' : customer_id
78+ } ) ;
79+ } ) ;
80+ } ) ;
81+ } ) ;
82+
83+ cpuUsageGauge . addCallback ( ( observableResult ) => {
84+ workflowIDs . forEach ( workflow_id => {
85+ customerIDs . forEach ( customer_id => {
86+ let cpuUsage = os . loadavg ( ) [ 0 ] ; // Load average for 1 minute; adjust as needed
87+ observableResult . observe ( cpuUsage , {
88+ ...attributes , 'workflow_id' : workflow_id , 'customer_id' : customer_id
89+ } ) ;
90+ } ) ;
91+ } ) ;
92+ } ) ;
93+
94+ runInTimeGauge . addCallback ( ( observableResult ) => {
95+ workflowIDs . forEach ( workflow_id => {
96+ customerIDs . forEach ( customer_id => {
97+ let run_time = Math . floor ( Math . random ( ) * 60 ) ;
98+ observableResult . observe ( run_time , {
99+ ...attributes , 'workflow_id' : workflow_id , 'customer_id' : customer_id
100+ } ) ;
101+ } ) ;
102+ } ) ;
103+ } ) ;
104+
105+ memoryUsageGauge . addCallback ( ( observableResult ) => {
106+ workflowIDs . forEach ( workflow_id => {
107+ customerIDs . forEach ( customer_id => {
108+ let usedMemory = process . memoryUsage ( ) . heapUsed / 1024 / 1024 ; // Convert bytes to megabytes
109+ observableResult . observe ( usedMemory , {
110+ ...attributes , 'workflow_id' : workflow_id , 'customer_id' : customer_id , 'unit' : 'MB'
111+ } ) ;
112+ } ) ;
113+ } ) ;
114+ } ) ;
115+
116+
117+ // Periodically update global variables if needed
118+ setInterval ( ( ) => {
119+ console . log ( "Job Executed" )
120+ } , 15000 ) ; // Adjust as needed
0 commit comments