Skip to content
This repository was archived by the owner on Oct 3, 2023. It is now read-only.

Commit 9e71d0f

Browse files
committed
chord: merge commit
2 parents 1e2f049 + 36421be commit 9e71d0f

12 files changed

Lines changed: 474 additions & 190 deletions

File tree

248 KB
Binary file not shown.

examples/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# OpenCensus Node.js Example
2+
3+
4+
Note: This code was tested on the following Node versions:
5+
- v6.10.0 (for console exporter only)
6+
- v9.8.0 (for Stackdriver and Zipkin exporters)
7+
8+
At this momment the automatic instrumetation is only for apps using http and mongo-db.
9+
10+
___
11+
12+
## Setup
13+
14+
1. Clone the OpenCensus Node repository https://github.com/census-instrumentation/opencensus-node.git
15+
```bash
16+
git clone https://github.com/census-instrumentation/opencensus-node.git
17+
cd opencensus-node
18+
```
19+
20+
2. Switch to branch `dev` with:
21+
```bash
22+
git checkout dev
23+
```
24+
25+
3. Install the dependencies with:
26+
```bash
27+
npm install
28+
```
29+
30+
4. Compile the TypeScript code into JavaScript with:
31+
```
32+
node_modules/.bin/tsc
33+
```
34+
35+
5. In a different folder, clone the example application to be instrumented (EasyNotes Application)
36+
```bash
37+
git clone https://github.com/callicoder/node-easy-notes-app
38+
```
39+
40+
6. Navigate to the application folder and install the dependencies with:
41+
```bash
42+
cd node-easy-notes-app
43+
npm install
44+
```
45+
46+
7. Check if the app is running. PS.: a mongodb installation is required
47+
```bash
48+
$ node server.js
49+
Server is listening on port 3000
50+
Successfully connected to the database
51+
```
52+
53+
## Add opencensus instrumentation
54+
55+
To add opencensus instrumetation, follow the steps below:
56+
57+
1. Navigate to the `node_modules` folder inside the EasyNotes application and create a link to OpenCensus Node project folder with:
58+
```bash
59+
cd node_modules
60+
ln -s <your path>/opencensus-node/build/src opencensus-nodejs
61+
cd ..
62+
```
63+
64+
2. Edit server.js and add the following line, as the first line of the file:
65+
```javascript
66+
var tracing = require("opencensus-nodejs").start()
67+
...
68+
var express = require('express');
69+
```
70+
71+
## Running the Instrumented Application
72+
73+
Save the file server.js and run the app with debugging option.
74+
75+
```bash
76+
$ DEBUG=opencensus node server.js
77+
opencensus useAsyncHooks = true +0ms
78+
opencensus patching http@9.8.0 module +75ms
79+
opencensus patching http.Server.prototype.emit function +7ms
80+
....
81+
Server is listening on port 3000
82+
Successfully connected to the database
83+
```
84+
This options uses a default exporter to console.
85+
86+
To test de api you can use the commands:
87+
```bash
88+
#To insert a note:
89+
curl -X POST http://localhost:3000/notes --data '{"title": "Note 1", "content": "this is the note content"}' -H "Content-Type: application/json"
90+
91+
#To get notes:
92+
curl http://localhost:3000/notes
93+
```
94+
95+
## Exporting to Zipkins
96+
97+
1. Download Zipkin choosing one of the three available options on [Quickstart](https://zipkin.io/pages/quickstart.html): through Docker, on Java or manually compiling the source code. Tests were executed running Zipkin with Java, through the following commands on terminal:
98+
```bash
99+
wget -O zipkin.jar 'https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec'
100+
java -jar zipkin.jar
101+
```
102+
103+
2. Open the `server.js` file in the EasyNotes application and insert this code on top:
104+
```javascript
105+
var tracing = require("opencensus-nodejs")
106+
.addZipkin("http://localhost:9411/api/v2/spans", "easy-notes")
107+
.start()
108+
```
109+
110+
111+
## Exporting to Stackdriver
112+
113+
1. Make sure you enabled Stackdriver Tracing on Google Cloud Platform. More info at <https://cloud.google.com/trace/docs/quickstart>
114+
115+
2. Enable Application Default Credentials for authentication with:
116+
```bash
117+
export GOOGLE_APPLICATION_CREDENTIALS=path/to/your/credential.json
118+
```
119+
More information at <https://cloud.google.com/docs/authentication/getting-started>
120+
121+
3. Open the `server.js` file in the EasyNotes application and insert this code on top:
122+
```javascript
123+
var traceMng = require("opencensus-nodejs")
124+
.addStackdriver("your-project-id")
125+
.start();
126+
```
127+
128+
129+
## Exporting to multiple Exporters
130+
131+
It is possible to instrument with more than one code. To achieve this, simply add more than one Exporter in series.
132+
133+
```javascript
134+
var tracing = require("opencensus-nodejs")
135+
.addZipkin(“http://localhost:9411/api/v2/spans“, "easy-notes")
136+
.addStackdriver("your-project")
137+
.start()
138+
```

packages/opencensus-core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"compile-strict": "npm run script compile-auto-strict",
1212
"compile": "npm run script compile-auto compile-auto-strict",
1313
"clean": "rimraf build/*",
14+
"fix": "gts fix",
1415
"script": "ts-node -P ./scripts ./scripts"
1516
},
1617
"keywords": [

packages/opencensus-core/src/trace/model/root-span.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import { Span } from './span'
1818
import { Clock } from '../../internal/clock'
1919
import * as uuid from 'uuid';
2020
import { debug } from '../../internal/util'
21-
import { SpanBaseModel, TraceContext, OnEndSpanEventListener, TraceOptions } from '../types/tracetypes'
22-
import { Tracer } from './tracer';
21+
import { SpanBaseModel, TraceOptions, TraceContext, OnEndSpanEventListener } from '../types/tracetypes'
22+
import { Tracer } from './tracer'
2323

2424
export class RootSpan extends SpanBaseModel implements OnEndSpanEventListener {
2525

packages/opencensus-core/src/trace/model/span.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,20 @@ export class Span extends SpanBaseModel {
6161
}
6262

6363
public end(): void {
64-
super.end();
65-
this.notifyEnd();
66-
debug('ending span %o',
67-
{
68-
spanId: this.id,
69-
traceId: this.traceId,
70-
name: this.name,
71-
startTime: this.startTime,
72-
endTime: this.endTime,
73-
duration: this.duration
74-
}
75-
)
76-
64+
// if(this.sampler.continue(this.traceId)) {
65+
66+
super.end();
67+
this.notifyEnd();
68+
debug('ending span %o',
69+
{
70+
spanId: this.id,
71+
traceId: this.traceId,
72+
name: this.name,
73+
startTime: this.startTime,
74+
endTime: this.endTime,
75+
duration: this.duration
76+
});
77+
// }
7778
}
7879

7980

packages/opencensus-core/src/trace/model/tracer.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Span } from './span'
2020
import { debug } from '../../internal/util'
2121
import { Stackdriver } from '../../exporters/stackdriver/stackdriver'
2222
import { StackdriverOptions } from '../../exporters/stackdriver/options'
23+
import { Sampler } from '../config/sampler'
2324
import { TraceContext, TraceOptions, OnEndSpanEventListener, SpanBaseModel } from '../types/tracetypes';
2425
import { TracerConfig, defaultConfig } from '../tracing';
2526

@@ -36,7 +37,7 @@ export class Tracer implements OnEndSpanEventListener {
3637
private config: TracerConfig;
3738

3839
//TODO: simple solution - to be rewied in future
39-
private eventListeners: OnEndSpanEventListener[] = [];
40+
private eventListeners: OnEndSpanEventListener[] = [];
4041
//TODO: temp solution
4142
private endedTraces: RootSpan[] = [];
4243

@@ -72,26 +73,31 @@ export class Tracer implements OnEndSpanEventListener {
7273
}
7374

7475
public startRootSpan<T>(options: TraceOptions, fn: (root: RootSpan) => T): T {
75-
debug('starting root span: %o', options)
7676
return this.contextManager.runAndReturn((root) => {
7777
let newRoot = new RootSpan(this, options);
7878
this.setCurrentRootSpan(newRoot);
79-
newRoot.start();
80-
return fn(newRoot);
79+
if(options.sampler == null){
80+
options.sampler = new Sampler(newRoot.traceId);
81+
options.sampler.probability(0.6);
82+
}
83+
newRoot.sampler = options.sampler;
84+
if(newRoot.sampler.continue(newRoot.traceId)){
85+
newRoot.start();
86+
return fn(newRoot);
87+
}
88+
return fn(null);
8189
});
8290
}
8391

84-
public onEndSpan(root: RootSpan): void {
85-
if (!this.currentRootSpan) {
86-
return debug('cannot end trace - no active trace found', this.currentRootSpan)
92+
93+
public onEndSpan(root:RootSpan): void {
94+
if (!root) {
95+
return debug('cannot end trace - no active trace found')
8796
}
88-
if (this.currentRootSpan != root) {
89-
debug('currentRootSpan != root on notifyEnd. Possbile implementation bug.')
90-
debug('ROOT SPAN ', root)
91-
return debug('CURRENT ROOT SPAN ', this.currentRootSpan)
92-
//return debug('currentRootSpan != root on notifyEnd. Possbile implementation bug.')
97+
if(this.currentRootSpan != root) {
98+
debug('currentRootSpan != root on notifyEnd. Need more investigation.')
9399
}
94-
this.notifyEndSpan(this.currentRootSpan);
100+
this.notifyEndSpan(root);
95101
//this.clearCurrentTrace();
96102
}
97103

@@ -101,8 +107,8 @@ export class Tracer implements OnEndSpanEventListener {
101107

102108
private notifyEndSpan(root: RootSpan) {
103109
if (this.active) {
104-
//this.buffer.onEndSpan(root);
105-
if (this.eventListeners && this.eventListeners.length > 0) {
110+
debug ('starting to notify listeners the end of rootspans')
111+
if(this.eventListeners&&this.eventListeners.length >0) {
106112
this.eventListeners.forEach((listener) => listener.onEndSpan(root))
107113
}
108114
} else {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* Copyright 2018 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { debug, randomSpanId } from '../../internal/util'
18+
19+
20+
const minNumber = 1e-4;
21+
const maxNumber = 0xffffffffffffffff;
22+
23+
export class Sampler{
24+
traceId: string;
25+
spanId: string;
26+
isRemote: boolean;
27+
idUpperBound: number;
28+
29+
/**
30+
*
31+
* @param traceId
32+
* @param spanId
33+
* @param isRemote
34+
*/
35+
constructor(traceId?:string, spanId?:string, isRemote?:boolean){
36+
debug('Samplre constructor')
37+
if(traceId){
38+
this.traceId = traceId;
39+
}
40+
if(spanId){
41+
this.spanId = spanId;
42+
}
43+
this.isRemote = isRemote || false;
44+
45+
}
46+
47+
public always(): Sampler{
48+
this.idUpperBound = maxNumber;
49+
return this;
50+
}
51+
52+
public never(): Sampler{
53+
this.idUpperBound = minNumber;
54+
return this;
55+
}
56+
57+
public probability(probability:number): Sampler{
58+
if(probability < minNumber){
59+
return this.never();
60+
61+
} else if (probability > maxNumber){
62+
return this.always();
63+
64+
}
65+
66+
this.idUpperBound = probability * maxNumber;
67+
return this;
68+
}
69+
70+
public continue (traceId:string):boolean{
71+
debug('Samplre continue')
72+
let lower_bytes = traceId.substring(16)
73+
let lower_long: number
74+
debug('SAMPLER CONTINUE lower_bytes :',lower_bytes)
75+
76+
lower_long = parseInt(lower_bytes, 16);
77+
78+
debug('SAMPLER CONTINUE lower_long :',lower_long)
79+
debug('SAMPLER CONTINUE this.idUpperBound :',this.idUpperBound)
80+
debug('SAMPLER CONTINUE diff :',lower_long - this.idUpperBound)
81+
82+
if(lower_long <= this.idUpperBound){
83+
debug('trace sampler TRUE')
84+
return true
85+
}else{
86+
debug('trace sampler FALSE')
87+
return false;
88+
}
89+
}
90+
91+
}

0 commit comments

Comments
 (0)