@@ -1192,30 +1192,10 @@ Node.js or Web SDKs.
1192
1192
1193
1193
## Metrics
1194
1194
1195
- To start producing [ metrics] ( /docs/concepts/signals/metrics ) , you'll need to
1196
- have an initialized ` MeterProvider ` that lets you create a ` Meter ` . ` Meter ` s let
1197
- you create ` Instrument ` s that you can use to create different kinds of metrics.
1198
- OpenTelemetry JavaScript currently supports the following ` Instrument ` s:
1199
-
1200
- - Counter, a synchronous instrument that supports non-negative increments
1201
- - Asynchronous Counter, an asynchronous instrument which supports non-negative
1202
- increments
1203
- - Histogram, a synchronous instrument that supports arbitrary values that are
1204
- statistically meaningful, such as histograms, summaries, or percentile
1205
- - Asynchronous Gauge, an asynchronous instrument that supports non-additive
1206
- values, such as room temperature
1207
- - UpDownCounter, a synchronous instrument that supports increments and
1208
- decrements, such as the number of active requests
1209
- - Asynchronous UpDownCounter, an asynchronous instrument that supports
1210
- increments and decrements
1211
-
1212
- For more on synchronous and asynchronous instruments, and which kind is best
1213
- suited for your use case, see
1214
- [ Supplementary Guidelines] ( /docs/specs/otel/metrics/supplementary-guidelines/ ) .
1215
-
1216
- If a ` MeterProvider ` is not created either by an instrumentation library or
1217
- manually, the OpenTelemetry Metrics API will use a no-op implementation and fail
1218
- to generate data.
1195
+ [ Metrics] ( /docs/concepts/signals/metrics ) combine individual measurements into
1196
+ aggregates, and produce data which is constant as a function of system load.
1197
+ Aggregates lack details required to diagnose low level issues, but complement
1198
+ spans by helping to identify trends and providing application runtime telemetry.
1219
1199
1220
1200
### Initialize Metrics
1221
1201
@@ -1275,9 +1255,8 @@ const resource = Resource.default().merge(
1275
1255
1276
1256
const metricReader = new PeriodicExportingMetricReader ({
1277
1257
exporter: new ConsoleMetricExporter (),
1278
-
1279
- // Default is 60000ms (60 seconds). Set to 3 seconds for demonstrative purposes only.
1280
- exportIntervalMillis: 3000 ,
1258
+ // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only.
1259
+ exportIntervalMillis: 10000 ,
1281
1260
});
1282
1261
1283
1262
const myServiceMeterProvider = new MeterProvider ({
@@ -1314,8 +1293,8 @@ const resource = Resource.default().merge(
1314
1293
const metricReader = new PeriodicExportingMetricReader ({
1315
1294
exporter: new ConsoleMetricExporter (),
1316
1295
1317
- // Default is 60000ms (60 seconds). Set to 3 seconds for demonstrative purposes only.
1318
- exportIntervalMillis: 3000 ,
1296
+ // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only.
1297
+ exportIntervalMillis: 10000 ,
1319
1298
});
1320
1299
1321
1300
const myServiceMeterProvider = new MeterProvider ({
@@ -1358,7 +1337,10 @@ call `getMeter` to acquire a meter. For example:
1358
1337
``` ts
1359
1338
import opentelemetry from ' @opentelemetry/api' ;
1360
1339
1361
- const myMeter = opentelemetry .metrics .getMeter (' my-service-meter' );
1340
+ const myMeter = opentelemetry .metrics .getMeter (
1341
+ ' instrumentation-scope-name' ,
1342
+ ' instrumentation-scope-version' ,
1343
+ );
1362
1344
1363
1345
// You can now use a 'meter' to create instruments!
1364
1346
```
@@ -1368,59 +1350,181 @@ const myMeter = opentelemetry.metrics.getMeter('my-service-meter');
1368
1350
``` js
1369
1351
const opentelemetry = require (' @opentelemetry/api' );
1370
1352
1371
- const myMeter = opentelemetry .metrics .getMeter (' my-service-meter' );
1353
+ const myMeter = opentelemetry .metrics .getMeter (
1354
+ ' instrumentation-scope-name' ,
1355
+ ' instrumentation-scope-version' ,
1356
+ );
1372
1357
1373
1358
// You can now use a 'meter' to create instruments!
1374
1359
```
1375
1360
1376
1361
{{% /tab %}} {{< /tabpane >}}
1377
1362
1363
+ The values of ` instrumentation-scope-name ` and ` instrumentation-scope-version `
1364
+ should uniquely identify the
1365
+ [ Instrumentation Scope] ( /docs/concepts/instrumentation-scope/ ) , such as the
1366
+ package, module or class name. While the name is required, the version is still
1367
+ recommended despite being optional.
1368
+
1378
1369
It’s generally recommended to call ` getMeter ` in your app when you need it
1379
1370
rather than exporting the meter instance to the rest of your app. This helps
1380
1371
avoid trickier application load issues when other required dependencies are
1381
1372
involved.
1382
1373
1383
- ### Synchronous and asynchronous instruments
1374
+ In the case of the [ example app] ( #example-app ) , there are two places where a
1375
+ tracer may be acquired with an appropriate Instrumentation Scope:
1384
1376
1385
- OpenTelemetry instruments are either synchronous or asynchronous (observable).
1377
+ First, in the _ application file _ ` app.ts ` (or ` app.js ` ):
1386
1378
1387
- Synchronous instruments take a measurement when they are called. The measurement
1388
- is done as another call during program execution, just like any other function
1389
- call. Periodically, the aggregation of these measurements is exported by a
1390
- configured exporter. Because measurements are decoupled from exporting values,
1391
- an export cycle may contain zero or multiple aggregated measurements.
1379
+ {{< tabpane text=true >}} {{% tab TypeScript %}}
1392
1380
1393
- Asynchronous instruments, on the other hand, provide a measurement at the
1394
- request of the SDK. When the SDK exports, a callback that was provided to the
1395
- instrument on creation is invoked. This callback provides the SDK with a
1396
- measurement that is immediately exported. All measurements on asynchronous
1397
- instruments are performed once per export cycle.
1381
+ ``` ts
1382
+ /* app.ts */
1383
+ import { metrics , trace } from ' @opentelemetry/api ' ;
1384
+ import express , { Express } from ' express ' ;
1385
+ import { rollTheDice } from ' ./dice ' ;
1398
1386
1399
- Asynchronous instruments are useful in several circumstances, such as:
1387
+ const tracer = trace .getTracer (' dice-server' , ' 0.1.0' );
1388
+ const meter = metrics .getMeter (' dice-server' , ' 0.1.0' );
1400
1389
1401
- - When updating a counter is not computationally cheap, and you don't want the
1402
- current executing thread to wait for the measurement
1403
- - Observations need to happen at frequencies unrelated to program execution
1404
- (i.e., they cannot be accurately measured when tied to a request lifecycle)
1405
- - There is no known timestamp for a measurement value
1390
+ const PORT: number = parseInt (process .env .PORT || ' 8080' );
1391
+ const app: Express = express ();
1406
1392
1407
- In cases like these, it's often better to observe a cumulative value directly,
1408
- rather than aggregate a series of deltas in post-processing (the synchronous
1409
- example). Take note of the use of ` observe ` rather than ` add ` in the appropriate
1410
- code examples below.
1393
+ app .get (' /rolldice' , (req , res ) => {
1394
+ const rolls = req .query .rolls ? parseInt (req .query .rolls .toString ()) : NaN ;
1395
+ if (isNaN (rolls )) {
1396
+ res
1397
+ .status (400 )
1398
+ .send (" Request parameter 'rolls' is missing or not a number." );
1399
+ return ;
1400
+ }
1401
+ res .send (JSON .stringify (rollTheDice (rolls , 1 , 6 )));
1402
+ });
1411
1403
1412
- ### Using Counters
1404
+ app .listen (PORT , () => {
1405
+ console .log (` Listening for requests on http://localhost:${PORT } ` );
1406
+ });
1407
+ ```
1413
1408
1414
- Counters can be used to measure a non-negative, increasing value.
1409
+ {{% /tab %}} {{% tab JavaScript %}}
1415
1410
1416
1411
``` js
1417
- const counter = myMeter .createCounter (' events.counter' );
1412
+ /* app.js*/
1413
+ const { trace , metrics } = require (' @opentelemetry/api' );
1414
+ const express = require (' express' );
1415
+ const { rollTheDice } = require (' ./dice.js' );
1418
1416
1419
- // ...
1417
+ const tracer = trace .getTracer (' dice-server' , ' 0.1.0' );
1418
+ const meter = metrics .getMeter (' dice-server' , ' 0.1.0' );
1420
1419
1421
- counter .add (1 );
1420
+ const PORT = parseInt (process .env .PORT || ' 8080' );
1421
+ const app = express ();
1422
+
1423
+ app .get (' /rolldice' , (req , res ) => {
1424
+ const rolls = req .query .rolls ? parseInt (req .query .rolls .toString ()) : NaN ;
1425
+ if (isNaN (rolls)) {
1426
+ res
1427
+ .status (400 )
1428
+ .send (" Request parameter 'rolls' is missing or not a number." );
1429
+ return ;
1430
+ }
1431
+ res .send (JSON .stringify (rollTheDice (rolls, 1 , 6 )));
1432
+ });
1433
+
1434
+ app .listen (PORT , () => {
1435
+ console .log (` Listening for requests on http://localhost:${ PORT } ` );
1436
+ });
1437
+ ```
1438
+
1439
+ {{% /tab %}} {{< /tabpane >}}
1440
+
1441
+ And second, in the _ library file_ ` dice.ts ` (or ` dice.js ` ):
1442
+
1443
+ {{< tabpane text=true >}} {{% tab TypeScript %}}
1444
+
1445
+ ``` ts
1446
+ /* dice.ts*/
1447
+ import { trace , metrics } from ' @opentelemetry/api' ;
1448
+
1449
+ const tracer = trace .getTracer (' dice-lib' );
1450
+ const meter = metrics .getMeter (' dice-lib' );
1451
+
1452
+ function rollOnce(min : number , max : number ) {
1453
+ return Math .floor (Math .random () * (max - min ) + min );
1454
+ }
1455
+
1456
+ export function rollTheDice(rolls : number , min : number , max : number ) {
1457
+ const result: number [] = [];
1458
+ for (let i = 0 ; i < rolls ; i ++ ) {
1459
+ result .push (rollOnce (min , max ));
1460
+ }
1461
+ return result ;
1462
+ }
1422
1463
```
1423
1464
1465
+ {{% /tab %}} {{% tab JavaScript %}}
1466
+
1467
+ ``` js
1468
+ /* dice.js*/
1469
+ const { trace , metrics } = require (' @opentelemetry/api' );
1470
+
1471
+ const tracer = trace .getTracer (' dice-lib' );
1472
+ const meter = metrics .getMeter (' dice-lib' );
1473
+
1474
+ function rollOnce (min , max ) {
1475
+ return Math .floor (Math .random () * (max - min) + min);
1476
+ }
1477
+
1478
+ function rollTheDice (rolls , min , max ) {
1479
+ const result = [];
1480
+ for (let i = 0 ; i < rolls; i++ ) {
1481
+ result .push (rollOnce (min, max));
1482
+ }
1483
+ return result;
1484
+ }
1485
+
1486
+ module .exports = { rollTheDice };
1487
+ ```
1488
+
1489
+ {{% /tab %}} {{< /tabpane >}}
1490
+
1491
+ Now that you have [ meters] ( /docs/concepts/signals/metrics/#meter ) initialized.
1492
+ you can create
1493
+ [ metric instruments] ( /docs/concepts/signals/metrics/#metric-instruments ) .
1494
+
1495
+ ### Create counters
1496
+
1497
+ Counters can be used to measure a non-negative, increasing value.
1498
+
1499
+ In the case of our [ example app] ( #example-app ) we can use this to count how
1500
+ often the dice has been rolled:
1501
+
1502
+ {{< tabpane text=true >}} {{% tab TypeScript %}}
1503
+
1504
+ ``` ts
1505
+ /* dice.ts*/
1506
+ const counter = meter .createCounter (' dice-lib.rolls.counter' );
1507
+
1508
+ function rollOnce(min : number , max : number ) {
1509
+ counter .add (1 );
1510
+ return Math .floor (Math .random () * (max - min ) + min );
1511
+ }
1512
+ ```
1513
+
1514
+ {{% /tab %}} {{% tab JavaScript %}}
1515
+
1516
+ ``` js
1517
+ /* dice.js*/
1518
+ const counter = meter .createCounter (' dice-lib.rolls.counter' );
1519
+
1520
+ function rollOnce (min , max ) {
1521
+ counter .add (1 );
1522
+ return Math .floor (Math .random () * (max - min) + min);
1523
+ }
1524
+ ```
1525
+
1526
+ {{% /tab %}} {{< /tabpane >}}
1527
+
1424
1528
### Using UpDown Counters
1425
1529
1426
1530
UpDown counters can increment and decrement, allowing you to observe a
0 commit comments