diff --git a/README.md b/README.md
index ff5d8456d..fa2b095d1 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# OpenCensus Libraries for Node.js
-[![Gitter chat][gitter-image]][gitter-url] ![Node Version][node-img] [![NPM Published Version][npm-img]][npm-url] ![Apache License][license-image]
+[![Gitter chat][gitter-image]][gitter-url] ![Node Version][node-img] [![NPM Published Version][npm-img]][npm-url] [![codecov][codecov-image]][codecov-url] ![Apache License][license-image]
OpenCensus Node.js is an implementation of OpenCensus, a toolkit for collecting application performance and behavior monitoring data. Right now OpenCensus for Node.js supports custom tracing and automatic tracing for HTTP and HTTPS. Please visit the [OpenCensus Node.js package](https://github.com/census-instrumentation/opencensus-node/tree/master/packages/opencensus-nodejs) for usage.
@@ -73,6 +73,8 @@ months before removing it, if possible.
- For more information on OpenCensus, visit:
- For help or feedback on this project, join us on [gitter](https://gitter.im/census-instrumentation/Lobby)
+[codecov-image]: https://codecov.io/gh/census-instrumentation/opencensus-node/branch/master/graph/badge.svg
+[codecov-url]: https://codecov.io/gh/census-instrumentation/opencensus-node
[gitter-image]: https://badges.gitter.im/census-instrumentation/lobby.svg
[gitter-url]: https://gitter.im/census-instrumentation/lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[npm-url]: https://www.npmjs.com/package/@opencensus/exporter-prometheus
diff --git a/examples/stats/exporter/prometheus.js b/examples/stats/exporter/prometheus.js
index b0c522d09..0af0bf4ca 100644
--- a/examples/stats/exporter/prometheus.js
+++ b/examples/stats/exporter/prometheus.js
@@ -19,15 +19,12 @@
* OpenCensus to Prometheus.
*/
-const { Stats, MeasureUnit, AggregationType } = require("@opencensus/core");
+const { globalStats, MeasureUnit, AggregationType, TagMap } = require("@opencensus/core");
const { PrometheusStatsExporter } = require("@opencensus/exporter-prometheus");
const fs = require("fs");
const readline = require("readline");
-// Create the Stats manager
-const stats = new Stats();
-
// [START setup_exporter]
// Enable OpenCensus exporters to export metrics to Prometheus Monitoring.
const exporter = new PrometheusStatsExporter({
@@ -36,19 +33,19 @@ const exporter = new PrometheusStatsExporter({
startServer: true
});
-// Pass the created exporter to Stats
-stats.registerExporter(exporter);
+// Pass the created exporter to global Stats
+globalStats.registerExporter(exporter);
// [END setup_exporter]
// The latency in milliseconds
-const mLatencyMs = stats.createMeasureDouble(
+const mLatencyMs = globalStats.createMeasureDouble(
"repl/latency",
MeasureUnit.MS,
"The latency in milliseconds per REPL loop"
);
// Counts/groups the lengths of lines read in.
-const mLineLengths = stats.createMeasureInt64(
+const mLineLengths = globalStats.createMeasureInt64(
"repl/line_lengths",
MeasureUnit.BYTE,
"The distribution of line lengths"
@@ -60,10 +57,12 @@ const stream = fs.createReadStream("./test.txt");
// Create an interface to read and process our file line by line
const lineReader = readline.createInterface({ input: stream });
-const tagKeys = ["method", "status"];
+const methodKey = { name: "method" };
+const statusKey = { name: "status" };
+const tagKeys = [methodKey, statusKey];
// Create & Register the view.
-/*const latencyView = */stats.createView(
+const latencyView = globalStats.createView(
"demo/latency",
mLatencyMs,
AggregationType.DISTRIBUTION,
@@ -73,20 +72,20 @@ const tagKeys = ["method", "status"];
// [>=0ms, >=25ms, >=50ms, >=75ms, >=100ms, >=200ms, >=400ms, >=600ms, >=800ms, >=1s, >=2s, >=4s, >=6s]
[0, 25, 50, 75, 100, 200, 400, 600, 800, 1000, 2000, 4000, 6000]
);
-//stats.registerView(latencyView);
+globalStats.registerView(latencyView);
// Create & Register the view.
-/*const lineCountView = */stats.createView(
+const lineCountView = globalStats.createView(
"demo/lines_in",
mLineLengths,
AggregationType.COUNT,
tagKeys,
"The number of lines from standard input"
);
-//stats.registerView(lineCountView);
+globalStats.registerView(lineCountView);
// Create & Register the view.
-/*const lineLengthView = */stats.createView(
+const lineLengthView = globalStats.createView(
"demo/line_lengths",
mLineLengths,
AggregationType.DISTRIBUTION,
@@ -96,7 +95,7 @@ const tagKeys = ["method", "status"];
// [>=0B, >=5B, >=10B, >=15B, >=20B, >=40B, >=60B, >=80, >=100B, >=200B, >=400, >=600, >=800, >=1000]
[0, 5, 10, 15, 20, 40, 60, 80, 100, 200, 400, 600, 800, 1000]
);
-//stats.registerView(lineLengthView);
+globalStats.registerView(lineLengthView);
// The begining of our REPL loop
let [_, startNanoseconds] = process.hrtime();
@@ -112,26 +111,31 @@ lineReader.on("line", function(line) {
// Registers the end of our REPL
[_, endNanoseconds] = process.hrtime();
- const tags = { method: "repl", status: "OK" };
+ const tags = new TagMap();
+ tags.set(methodKey, { value: "REPL" });
+ tags.set(statusKey, { value: "OK" });
- stats.record({
+ globalStats.record([{
measure: mLineLengths,
tags,
value: processedLine.length
- });
+ }], tags);
- stats.record({
+ globalStats.record([{
measure: mLatencyMs,
tags,
value: sinceInMilliseconds(endNanoseconds, startNanoseconds)
- });
+ }], tags);
} catch (err) {
- const errTags = { method: "repl", status: "ERROR", error: err.message };
- stats.record({
+ console.log(err);
+
+ const errTags = new TagMap();
+ errTags.set(methodKey, { value: "repl" });
+ errTags.set(statusKey, { value: "ERROR" });
+ globalStats.record([{
measure: mLatencyMs,
- errTags,
value: sinceInMilliseconds(endNanoseconds, startNanoseconds)
- });
+ }], errTags);
}
// Restarts the start time for the REPL
@@ -155,4 +159,3 @@ function processLine(line) {
function sinceInMilliseconds(endNanoseconds, startNanoseconds) {
return (endNanoseconds - startNanoseconds) / 1e6;
}
-
diff --git a/examples/stats/exporter/stackdriver.js b/examples/stats/exporter/stackdriver.js
index fbb7e2eeb..eaec99c9e 100644
--- a/examples/stats/exporter/stackdriver.js
+++ b/examples/stats/exporter/stackdriver.js
@@ -19,17 +19,13 @@
* OpenCensus to Stackdriver.
*/
-const { Stats, MeasureUnit, AggregationType } = require("@opencensus/core");
-const {
- StackdriverStatsExporter
-} = require("@opencensus/exporter-stackdriver");
+const { globalStats, MeasureUnit, AggregationType, TagMap } = require("@opencensus/core");
+const { StackdriverStatsExporter } =
+require("@opencensus/exporter-stackdriver");
const fs = require("fs");
const readline = require("readline");
-// Create the Stats manager
-const stats = new Stats();
-
// [START setup_exporter]
// Enable OpenCensus exporters to export metrics to Stackdriver Monitoring.
// Exporters use Application Default Credentials (ADCs) to authenticate.
@@ -47,19 +43,19 @@ if (!projectId || !process.env.GOOGLE_APPLICATION_CREDENTIALS) {
}
const exporter = new StackdriverStatsExporter({ projectId: projectId });
-// Pass the created exporter to Stats
-stats.registerExporter(exporter);
+// Pass the created exporter to global Stats
+globalStats.registerExporter(exporter);
// [END setup_exporter]
// The latency in milliseconds
-const mLatencyMs = stats.createMeasureDouble(
+const mLatencyMs = globalStats.createMeasureDouble(
"repl/latency",
MeasureUnit.MS,
"The latency in milliseconds per REPL loop"
);
// Counts/groups the lengths of lines read in.
-const mLineLengths = stats.createMeasureInt64(
+const mLineLengths = globalStats.createMeasureInt64(
"repl/line_lengths",
MeasureUnit.BYTE,
"The distribution of line lengths"
@@ -71,10 +67,12 @@ const stream = fs.createReadStream("./test.txt");
// Create an interface to read and process our file line by line
const lineReader = readline.createInterface({ input: stream });
-const tagKeys = ["method", "status"];
+const methodKey = { name: "method" };
+const statusKey = { name: "status" };
+const tagKeys = [methodKey, statusKey];
-// Create the view.
-stats.createView(
+// Create & Register the view.
+const latencyView = globalStats.createView(
"demo/latency",
mLatencyMs,
AggregationType.DISTRIBUTION,
@@ -84,18 +82,20 @@ stats.createView(
// [>=0ms, >=25ms, >=50ms, >=75ms, >=100ms, >=200ms, >=400ms, >=600ms, >=800ms, >=1s, >=2s, >=4s, >=6s]
[0, 25, 50, 75, 100, 200, 400, 600, 800, 1000, 2000, 4000, 6000]
);
+globalStats.registerView(latencyView);
-// Create the view.
-stats.createView(
+// Create & Register the view.
+const lineCountView = globalStats.createView(
"demo/lines_in",
mLineLengths,
AggregationType.COUNT,
tagKeys,
"The number of lines from standard input"
);
+globalStats.registerView(lineCountView);
-// Create the view.
-stats.createView(
+// Create & Register the view.
+const lineLengthView = globalStats.createView(
"demo/line_lengths",
mLineLengths,
AggregationType.DISTRIBUTION,
@@ -105,6 +105,7 @@ stats.createView(
// [>=0B, >=5B, >=10B, >=15B, >=20B, >=40B, >=60B, >=80, >=100B, >=200B, >=400, >=600, >=800, >=1000]
[0, 5, 10, 15, 20, 40, 60, 80, 100, 200, 400, 600, 800, 1000]
);
+globalStats.registerView(lineLengthView);
// The begining of our REPL loop
let [_, startNanoseconds] = process.hrtime();
@@ -120,26 +121,30 @@ lineReader.on("line", function(line) {
// Registers the end of our REPL
[_, endNanoseconds] = process.hrtime();
- const tags = { method: "repl", status: "OK" };
+ const tags = new TagMap();
+ tags.set(methodKey, { value: "REPL" });
+ tags.set(statusKey, { value: "OK" });
- stats.record({
+ globalStats.record([{
measure: mLineLengths,
- tags,
value: processedLine.length
- });
+ }], tags);
- stats.record({
+ globalStats.record([{
measure: mLatencyMs,
- tags,
value: sinceInMilliseconds(endNanoseconds, startNanoseconds)
- });
+ }], tags);
+
} catch (err) {
- const errTags = { method: "repl", status: "ERROR", error: err.message };
- stats.record({
+ console.log(err);
+
+ const errTags = new TagMap();
+ errTags.set(methodKey, { value: "repl" });
+ errTags.set(statusKey, { value: "ERROR" });
+ globalStats.record([{
measure: mLatencyMs,
- errTags,
value: sinceInMilliseconds(endNanoseconds, startNanoseconds)
- });
+ }], errTags);
}
// Restarts the start time for the REPL
diff --git a/examples/stats/web_client_monitoring/app.js b/examples/stats/web_client_monitoring/app.js
index 1f170005a..ea247bca6 100644
--- a/examples/stats/web_client_monitoring/app.js
+++ b/examples/stats/web_client_monitoring/app.js
@@ -25,7 +25,7 @@ const assert = require('assert');
const process = require("process");
const bodyParser = require('body-parser');
// [START web_client_monitoring_imports]
-const { Stats, MeasureUnit, AggregationType } = require('@opencensus/core');
+const { globalStats, MeasureUnit, AggregationType, TagMap } = require('@opencensus/core');
const { StackdriverStatsExporter } = require('@opencensus/exporter-stackdriver');
// [END web_client_monitoring_imports]
@@ -41,21 +41,22 @@ console.log(`Sending metrics data to project: ${project}`);
// OpenCensus setup
// [START web_client_monitoring_ocsetup]
-const stats = new Stats();
const exporter = new StackdriverStatsExporter({projectId: project});
-stats.registerExporter(exporter);
-const mLatencyMs = stats.createMeasureDouble("webmetrics/latency",
+globalStats.registerExporter(exporter);
+const mLatencyMs = globalStats.createMeasureDouble("webmetrics/latency",
MeasureUnit.MS,
"Latency related to page loading");
-const mClickCount = stats.createMeasureInt64("webmetrics/click_count",
+const mClickCount = globalStats.createMeasureInt64("webmetrics/click_count",
MeasureUnit.UNIT,
"Number of clicks");
const buckets = [0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80,
100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000,
5000, 10000, 20000, 50000, 100000];
-const tagPhase = "phase";
-const tagClient = "client";
-const latencyView = stats.createView(
+
+const tagPhase = { name: "phase" };
+const tagClient = { name: "client" };
+
+const latencyView = globalStats.createView(
"webmetrics/latency",
mLatencyMs,
AggregationType.DISTRIBUTION,
@@ -63,13 +64,15 @@ const latencyView = stats.createView(
"Distribution of latencies",
buckets
);
-const clickCountView = stats.createView(
+globalStats.registerView(latencyView);
+const clickCountView = globalStats.createView(
"webmetrics/click_count",
mClickCount,
AggregationType.COUNT,
[tagClient],
"The number of button clicks"
);
+globalStats.registerView(clickCountView);
// [END web_client_monitoring_ocsetup]
// Process the metrics data posted to the server
@@ -86,32 +89,35 @@ app.post("/metrics", (req, res) => {
const valueDNSLookup = "dns_lookup";
const valueLoad = "load";
const valueWeb = "web";
- let tags = { phase: valueDNSLookup, client: valueWeb };
+
+ const tags = new TagMap();
+ tags.set(tagPhase, { value: valueDNSLookup });
+ tags.set(tagClient, { value: valueWeb });
// [START web_client_monitoring_record]
try {
- stats.record({
+ globalStats.record([{
measure: mLatencyMs,
- tags,
- value: dnsTime
- });
- tags = { phase: valueTLSNegotiation, client: valueWeb };
- stats.record({
+ value: 1
+ }], tags);
+
+ tags.set(tagPhase, { value: valueTLSNegotiation });
+ globalStats.record([{
measure: mLatencyMs,
- tags,
- value: connectTime
- });
- tags = { phase: valueLoad, client: valueWeb };
- stats.record({
+ value: 1
+ }], tags);
+
+ tags.set(tagPhase, { value: valueLoad });
+ globalStats.record([{
measure: mLatencyMs,
- tags,
- value: totalTime
- });
- tags = { client: valueWeb };
- stats.record({
+ value: 1
+ }], tags);
+
+ const tags1 = new TagMap();
+ tags1.set(tagClient, { value: valueWeb });
+ globalStats.record([{
measure: mClickCount,
- tags,
- value: clickCount
- });
+ value: 1
+ }], tags1);
res.status(200).send("Received").end();
console.log('Competed recording metrics');
} catch (err) {
diff --git a/package.json b/package.json
index bb784b6d8..fad8e55fb 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,9 @@
"opencensus",
"nodejs",
"tracing",
- "profiling"
+ "profiling",
+ "metrics",
+ "stats"
],
"author": "Google Inc.",
"license": "Apache-2.0",
diff --git a/packages/opencensus-core/README.md b/packages/opencensus-core/README.md
index 36cc89bd2..192f4aa11 100644
--- a/packages/opencensus-core/README.md
+++ b/packages/opencensus-core/README.md
@@ -14,18 +14,15 @@ npm install @opencensus/core
## Usage
-#### Set up a new Stats manager instance.
+#### Get the global Stats manager instance.
To enable metrics, we’ll import a few items from OpenCensus Core package.
```javascript
-const { Stats, MeasureUnit, AggregationType } = require('@opencensus/core');
-
-// Create the Stats manager
-const stats = new Stats();
+const { globalStats, MeasureUnit, AggregationType, TagMap } = require('@opencensus/core');
// The latency in milliseconds
-const mLatencyMs = stats.createMeasureDouble(
+const mLatencyMs = globalStats.createMeasureDouble(
"repl/latency",
MeasureUnit.MS,
"The latency in milliseconds"
@@ -37,11 +34,12 @@ const mLatencyMs = stats.createMeasureDouble(
We now determine how our metrics will be organized by creating ```Views```. We will also create the variable needed to add extra text meta-data to our metrics – ```methodTagKey```, ```statusTagKey```, and ```errorTagKey```.
```javascript
-const methodTagKey = "method";
-const statusTagKey = "status";
-const errorTagKey = "error";
+const methodTagKey = { name: "method" };
+const statusTagKey = { name: "status" };
+const errorTagKey = { name: "error" };
-const latencyView = stats.createView(
+// Create & Register the view.
+const latencyView = globalStats.createView(
"demo/latency",
mLatencyMs,
AggregationType.DISTRIBUTION,
@@ -51,22 +49,23 @@ const latencyView = stats.createView(
// [>=0ms, >=25ms, >=50ms, >=75ms, >=100ms, >=200ms, >=400ms, >=600ms, >=800ms, >=1s, >=2s, >=4s, >=6s]
[0, 25, 50, 75, 100, 200, 400, 600, 800, 1000, 2000, 4000, 6000]
);
+globalStats.registerView(latencyView);
```
#### Recording Metrics:
-Now we will record the desired metrics. To do so, we will use ```stats.record()``` and pass in measurements.
+Now we will record the desired metrics. To do so, we will use ```globalStats.record()``` and pass in measurements.
```javascript
const [_, startNanoseconds] = process.hrtime();
-const tags = {method: "repl", status: "OK"};
+const tags = new TagMap();
+tags.set(methodTagKey, { value: "REPL" });
+tags.set(statusTagKey, { value: "OK" });
-stats.record({
+globalStats.record([{
measure: mLatencyMs,
- tags,
value: sinceInMilliseconds(startNanoseconds)
-});
-
+}], tags);
function sinceInMilliseconds(startNanoseconds) {
const [_, endNanoseconds] = process.hrtime();
@@ -74,6 +73,19 @@ function sinceInMilliseconds(startNanoseconds) {
}
```
+Measures can be of type `Int64` or `DOUBLE`, created by calling `createMeasureInt64` and `createMeasureDouble` respectively. Its units can be:
+
+| MeasureUnit | Usage |
+| ----------- | ----- |
+| `UNIT` | for general counts |
+| `BYTE` | bytes |
+| `KBYTE` | Kbytes |
+| `SEC` | seconds |
+| `MS` | millisecond |
+| `NS` | nanosecond |
+
+Views can have agregations of type `SUM`, `LAST_VALUE`, `COUNT` and `DISTRIBUTION`. To know more about Stats core concepts, please visit: [https://opencensus.io/core-concepts/metrics/](https://opencensus.io/core-concepts/metrics/)
+
See [Quickstart/Metrics](https://opencensus.io/quickstart/nodejs/metrics/) for a full example of registering and collecting metrics.
## Useful links
diff --git a/packages/opencensus-core/package.json b/packages/opencensus-core/package.json
index 6ae552c73..bb659de45 100644
--- a/packages/opencensus-core/package.json
+++ b/packages/opencensus-core/package.json
@@ -21,7 +21,9 @@
"opencensus",
"nodejs",
"tracing",
- "profiling"
+ "profiling",
+ "metrics",
+ "stats"
],
"author": "Google Inc.",
"license": "Apache-2.0",
diff --git a/packages/opencensus-exporter-prometheus/README.md b/packages/opencensus-exporter-prometheus/README.md
index 524d9c707..e0808c52e 100644
--- a/packages/opencensus-exporter-prometheus/README.md
+++ b/packages/opencensus-exporter-prometheus/README.md
@@ -1,7 +1,7 @@
# OpenCensus Prometheus Exporter for Node.js
[![Gitter chat][gitter-image]][gitter-url] ![Node Version][node-img] [![NPM Published Version][npm-img]][npm-url] ![dependencies Status][dependencies-status] ![devDependencies Status][devdependencies-status] ![Apache License][license-image]
-The OpenCensus Prometheus Exporter allows the user to send collected stats with [OpenCensus Node.js](https://github.com/census-instrumentation/opencensus-node) to Prometheus.
+The OpenCensus Prometheus Exporter allows the user to send collected stats with [OpenCensus Core](https://github.com/census-instrumentation/opencensus-core) to Prometheus.
This package is still at an early stage of development, and is subject to change.
@@ -15,49 +15,38 @@ npm install @opencensus/exporter-prometheus
## Usage
-Instance the exporter on your application.
+Create & register the exporter on your application.
-For javascript:
+For Javascript:
```javascript
-const { Stats } = require('@opencensus/core');
+const { globalStats } = require('@opencensus/core');
const { PrometheusStatsExporter } = require('@opencensus/exporter-prometheus');
// Add your port and startServer to the Prometheus options
const exporter = new PrometheusStatsExporter({
port: 9464,
- startServer: false
+ startServer: true
});
```
Now, register the exporter.
```javascript
-// Our Stats manager
-const stats = new Stats();
-
// Pass the created exporter to Stats
-stats.registerExporter(exporter);
-
-// Run the server
-exporter.startServer(function callback() {
- // Callback
-});
+globalStats.registerExporter(exporter);
```
-Similarly for Typescript (Since the source is written in TypeScript):
+Similarly for TypeScript (Since the source is written in TypeScript):
```typescript
import { PrometheusStatsExporter } from '@opencensus/exporter-prometheus';
-import { Stats } from '@opencensus/core';
+import { globalStats } from '@opencensus/core';
// Add your port and startServer to the Prometheus options
-const options = {port: 9464, startServer: false};
+const options = {port: 9464, startServer: true};
const exporter = new PrometheusStatsExporter(options);
-// Our Stats manager
-const stats = new Stats();
-
// Pass the created exporter to Stats
-stats.registerExporter(exporter);
+globalStats.registerExporter(exporter);
```
Viewing your metrics:
@@ -80,6 +69,6 @@ With the above you should now be able to navigate to the Prometheus UI at:
+
+# OpenCensus Stackdriver Stats(Metrics) Exporter
+## Installation
+
+Install OpenCensus Stackdriver Exporter with:
+```bash
+npm install @opencensus/core
+npm install @opencensus/exporter-stackdriver
+```
+
+## Usage
+
+To use Stackdriver as your exporter, make sure you have enabled [Stackdriver Monitoring](https://cloud.google.com/monitoring/docs/quickstart) on Google Cloud Platform. Enable your [Application Default Credentials](https://cloud.google.com/docs/authentication/getting-started) for authentication with:
+
+```bash
+export GOOGLE_APPLICATION_CREDENTIALS=path/to/your/credential.json
+```
+
+Create and register the exporter on your application.
+
+For Javascript:
+```javascript
+const { globalStats } = require('@opencensus/core');
+const { StackdriverStatsExporter } = require('@opencensus/exporter-stackdriver');
+
+// Add your project id to the Stackdriver options
+const exporter = new StackdriverStatsExporter({ projectId: "your-project-id" });
+
+// Pass the created exporter to Stats
+globalStats.registerExporter(exporter);
+```
+
+Similarly for TypeScript:
+```typescript
+import { globalStats } from '@opencensus/core';
+import { StackdriverStatsExporter } from '@opencensus/exporter-stackdriver';
+
+// Add your project id to the Stackdriver options
+const exporter = new StackdriverStatsExporter({ projectId: "your-project-id" });
+
+// Pass the created exporter to Stats
+globalStats.registerExporter(exporter);
+```
+
+Viewing your metrics:
+
+With the above you should now be able to navigate to the Stackdriver UI at:
+
+
## Useful links
- To know more about Stackdriver, visit:
- For more information on OpenCensus, visit:
diff --git a/packages/opencensus-exporter-stackdriver/package.json b/packages/opencensus-exporter-stackdriver/package.json
index d71489cee..9cb9acff4 100644
--- a/packages/opencensus-exporter-stackdriver/package.json
+++ b/packages/opencensus-exporter-stackdriver/package.json
@@ -20,7 +20,9 @@
"opencensus",
"nodejs",
"tracing",
- "profiling"
+ "profiling",
+ "metrics",
+ "stats"
],
"author": "Google Inc.",
"license": "Apache-2.0",