feat: add opencensus-core package #2
Conversation
…ving class files Span.ts, Trace.ts and Tracer.ts to trace/model
…ving class files Span.ts, Trace.ts and Tracer.ts to trace/model
… interface, add TraceContext interface
…odel to span-base
|
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
kjin
left a comment
There was a problem hiding this comment.
If you feel that any of these comments should be done in a separate PR, please make a note of that in the form of a TODO comment (so that we can keep track).
Feel free to start a discussion on any comment that you might be confused on or disagree with. If it's not worth creating a full reply, you can comment "done" or use the 👍 reaction to help keep track of which comments have been addressed.
| "author": "Google Inc.", | ||
| "license": "Apache-2.0", | ||
| "engines": { | ||
| "node": ">=6.00" |
There was a problem hiding this comment.
Nit: Remove the extra 0 here.
|
|
||
| OpenCensus is a toolkit for collecting application performance and behavior data. It currently | ||
| includes 3 apis: stats, tracing and tags. | ||
| 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 mongodb. |
There was a problem hiding this comment.
A few nits:
- We should be consistent between
OpenCensus Node.jsandOpenCensus for Node.js(I prefer the latter) Right now->Currently- Codify
httpandmongodbto suggest that these are modules
There was a problem hiding this comment.
For this PR I've simplified even more the README.md text. Even though I didn't add an explicit TODO, obviously it is a TODO for a next PR. Ok?
| - v6.10.0 (for console exporter only) | ||
| - v9.8.0 (for Stackdriver and Zipkin exporters) | ||
|
|
||
| ___ |
| "version": "0.0.1", | ||
| "description": "OpenCensus is a toolkit for collecting application performance and behavior data.", | ||
| "main": "build/src/index.js", | ||
| "types": "build/src/index.d.js", |
| @@ -0,0 +1 @@ | |||
| Google Inc. No newline at end of file | |||
There was a problem hiding this comment.
Should this be OpenCensus Authors?
There was a problem hiding this comment.
Others opencensus implementations are in the same state:
https://github.com/census-instrumentation/opencensus-java/blob/master/AUTHORS
https://github.com/census-instrumentation/opencensus-go/blob/master/AUTHORS
There was a problem hiding this comment.
You should add CESAR to this list and/or individual contributors
There was a problem hiding this comment.
You should add CESAR to this list and/or individual contributors
|
|
||
| const tracer = new Tracer(); | ||
|
|
||
| describe('Span', () => { |
There was a problem hiding this comment.
Would it be possible to merge similar tests between RootSpan and Span? You can do so in a follow-up PR if needed.
There was a problem hiding this comment.
TODO. We gonna evaluate that.
| describe('get active()', () => { | ||
| let tracer: Tracer; | ||
| before(() => { | ||
| tracer = new Tracer(); |
There was a problem hiding this comment.
Add an assertion here to ensure that it wasn't active beforehand.
| }); | ||
|
|
||
| /** Should return a started tracer instance */ | ||
| describe('start()', () => { |
There was a problem hiding this comment.
This test seems nearly identical to get active().
There was a problem hiding this comment.
Test case for get active() was removed.
| }); | ||
|
|
||
|
|
||
| /** Testing void functions */ |
There was a problem hiding this comment.
What are these cases testing?
There was a problem hiding this comment.
Test cases for tracer were updated.
| "sourceMap": false | ||
| }, | ||
| "include": [ | ||
| "src/*.ts", |
There was a problem hiding this comment.
This needs to be "src/**/*.ts" or npm run fix will not work.
1efd7e5 to
5ba700f
Compare
| logger['logger'] = defaultLogger; | ||
| return defaultLogger; | ||
| }; | ||
| const logger = (options?: types.LoggerOptions|string|number) => { |
There was a problem hiding this comment.
Is it necessary to allow options to be a number? LoggerOptions only accepts the logging level as a string.
There was a problem hiding this comment.
logLevel is a number in Config interface. So, we decide to keep the logic to convert logLevel numbers to string in that class. I will add a TODO for reevaluation.
|
|
||
| logger(); | ||
| const aLogger = new ConsoleLogger(opt); | ||
| logger['logger'] = aLogger; |
There was a problem hiding this comment.
If you call logger() multiple times, you get different loggers. If that is desired, I don't see why you need to store the logger on the ['logger'] property. If that is not desired, you should add something like if (logger['logger']) {...} to avoid re-creating the object each time.
There was a problem hiding this comment.
If we always return the same logger instance, will not be possible to have loggers with different log levels at the same time, what can limit some test capability. I will add a TODO for reevaluation.
| * @param name The function name. | ||
| * @param wrapper The wrapper. | ||
| */ | ||
| protected wrap(nodule, name, wrapper) { |
There was a problem hiding this comment.
It's OK for instrumentations to depend on shimmer since npm will install a single module for all of them anyway, so there is no dependency size penalty. I would still prefer to keep the API as minimal as possible, especially functions like these that are little more than call-throughs to an underlying dependency module.
| * @param parentSpanId The parent span ID. | ||
| */ | ||
| startSpan(name?: string, type?: string, parentSpanId?: string): types.Span { | ||
| startChildSpan(name?: string, type?: string, parentSpanId?: string): |
There was a problem hiding this comment.
I believe parentSpanId doesn't need to be here? It's guaranteed to be this.spanId.
|
|
||
| /** Gives the TraceContext of the span. */ | ||
| get traceContext(): types.TraceContext { | ||
| get spanContext(): types.SpanContext { |
There was a problem hiding this comment.
Why was the type/field changed to SpanContext? I thought TraceContext was fine. (If you decide to keep SpanContext, please change the code comment above.)
Actually, also looking at this more closely -- does the parentSpanId need to be there? It's not part of the SpanContext interface. Also, it would be great to have options here as well.
There was a problem hiding this comment.
Why was the type/field changed to SpanContext?
It was changed to be consistent with opencensus that uses the term SpanContext:
https://github.com/census-instrumentation/opencensus-java/blob/master/api/src/main/java/io/opencensus/trace/SpanContext.java
Actually, also looking at this more closely -- does the parentSpanId need to be there?
There is no parentSpanId in opencensus SpanContext interface. As I understand the spanId should represent a parendSpanID when the context is propagated.
| /** | ||
| * This class represent a tracer. | ||
| */ | ||
| export class Tracer implements types.Tracer { |
There was a problem hiding this comment.
I like the idea to keep types depending on types and not on concrete implementations.
Generally, I agree. However it depends on the use case. In my mind there are two reasons for a dependent module to use a type definition -- either to extend it, or to instantiate/handle objects of that type. Interfaces like Exporter, Plugin, Logger, and so on are meant to extended by other modules, while Tracer falls in the latter category of being used by other modules, but not extended. That's why I believe that exporters, plugins, etc should be interfaces while Tracer should be a single class.
As we discussed in person, we should consider in the future whether there needs to be a specific interface for Tracer. Keep in mind that type definitions exported by this module don't contain any implementations whatsoever anyway, so other modules will always depend on types only and not implementations. The difference is whether the type definitions will say interface Tracer ... class Tracer or just class Tracer.
| import {Logger} from '../src/common/types'; | ||
| import {Buffer} from '../src/exporters/buffer'; | ||
| import {ConsoleExporter} from '../src/exporters/console-exporter'; | ||
| import {ExporterBuffer} from '../src/exporters/exporter-buffer'; |
| describe('setBufferSize', () => { | ||
| it('should set BufferSize', () => { | ||
| const buffer = new ExporterBuffer(exporter, defaultBufferConfig); | ||
| const bufferResize = buffer.setBufferSize(DEFAULT_BUFFER_SIZE); |
There was a problem hiding this comment.
I would suggest using a value here other than DEFAULT_BUFFER_SIZE.
| assert.strictEqual(sampler.description, 'always'); | ||
| assert.ok(samplerShouldSampler); | ||
| }); | ||
| it('should return a always sampler', () => { |
There was a problem hiding this comment.
Use different test case messages for these two tests (same for never sampler)
| } as types.SpanContext; | ||
|
|
||
|
|
||
| it('should reate the new RootSpan with propagation', () => { |
kjin
left a comment
There was a problem hiding this comment.
Looks mostly good to me -- I added a few final comments. Once you've addressed them we should be good to merge.
| "nyc": "11.6.0" | ||
| }, | ||
| "dependencies": { | ||
| "async_hooks": "^1.0.0", |
There was a problem hiding this comment.
It looks like it wasn't removed? Did I miss something?
| } | ||
| } | ||
| const aRoot = new RootSpan(this, options); | ||
| const sampleDecisition: boolean = propagatedSample ? |
There was a problem hiding this comment.
sampleDecisition -> sampleDecision
| @@ -0,0 +1,100 @@ | |||
| /** | |||
| * Copyright 2018 Google LLC. All Rights Reserved. | |||
The JaegerTraceExporterOptions accepts `tags` as a Tag array, but was processing those tags for the process information as if they were an object / Record instead of a Tag array. This was leading to the process key-value inside Jaeger to be the array index as key and the value as the key-value object. We now use the proper key-value information from the input to place into the process tags. There were two approaches we could have taken here: 1. To leave the input as a Tag array and process the input properly in the code or 2. To change the input to a key-value record / object (Record<string, TagValue), which would be handled properly by the existing code. We have chosen approach census-instrumentation#1 because a Jaeger process tag CAN support multiple tags with the same key name, which would not be supported in approach census-instrumentation#2. There is a chance that (because we were not previously exporting typescript types) users were passing in a Record format instead of Array, and thus this might be seen as a breaking change. A test has been added to validate the process information to ensure proper format. Also included are sticter typing for all thrift types, removing all `any` references and replacing with valid types.
The JaegerTraceExporterOptions accepts `tags` as a Tag array, but was processing those tags for the process information as if they were an object / Record instead of a Tag array. This was leading to the process key-value inside Jaeger to be the array index as key and the value as the key-value object. We now use the proper key-value information from the input to place into the process tags. There were two approaches we could have taken here: 1. To leave the input as a Tag array and process the input properly in the code or 2. To change the input to a key-value record / object (Record<string, TagValue), which would be handled properly by the existing code. We have chosen approach #1 because a Jaeger process tag CAN support multiple tags with the same key name, which would not be supported in approach #2. There is a chance that (because we were not previously exporting typescript types) users were passing in a Record format instead of Array, and thus this might be seen as a breaking change. A test has been added to validate the process information to ensure proper format. Also included are sticter typing for all thrift types, removing all `any` references and replacing with valid types.
…on#93) The JaegerTraceExporterOptions accepts `tags` as a Tag array, but was processing those tags for the process information as if they were an object / Record instead of a Tag array. This was leading to the process key-value inside Jaeger to be the array index as key and the value as the key-value object. We now use the proper key-value information from the input to place into the process tags. There were two approaches we could have taken here: 1. To leave the input as a Tag array and process the input properly in the code or 2. To change the input to a key-value record / object (Record<string, TagValue), which would be handled properly by the existing code. We have chosen approach census-instrumentation#1 because a Jaeger process tag CAN support multiple tags with the same key name, which would not be supported in approach census-instrumentation#2. There is a chance that (because we were not previously exporting typescript types) users were passing in a Record format instead of Array, and thus this might be seen as a breaking change. A test has been added to validate the process information to ensure proper format. Also included are sticter typing for all thrift types, removing all `any` references and replacing with valid types.
…on#93) The JaegerTraceExporterOptions accepts `tags` as a Tag array, but was processing those tags for the process information as if they were an object / Record instead of a Tag array. This was leading to the process key-value inside Jaeger to be the array index as key and the value as the key-value object. We now use the proper key-value information from the input to place into the process tags. There were two approaches we could have taken here: 1. To leave the input as a Tag array and process the input properly in the code or 2. To change the input to a key-value record / object (Record<string, TagValue), which would be handled properly by the existing code. We have chosen approach census-instrumentation#1 because a Jaeger process tag CAN support multiple tags with the same key name, which would not be supported in approach census-instrumentation#2. There is a chance that (because we were not previously exporting typescript types) users were passing in a Record format instead of Array, and thus this might be seen as a breaking change. A test has been added to validate the process information to ensure proper format. Also included are sticter typing for all thrift types, removing all `any` references and replacing with valid types.
…on#93) The JaegerTraceExporterOptions accepts `tags` as a Tag array, but was processing those tags for the process information as if they were an object / Record instead of a Tag array. This was leading to the process key-value inside Jaeger to be the array index as key and the value as the key-value object. We now use the proper key-value information from the input to place into the process tags. There were two approaches we could have taken here: 1. To leave the input as a Tag array and process the input properly in the code or 2. To change the input to a key-value record / object (Record<string, TagValue), which would be handled properly by the existing code. We have chosen approach census-instrumentation#1 because a Jaeger process tag CAN support multiple tags with the same key name, which would not be supported in approach census-instrumentation#2. There is a chance that (because we were not previously exporting typescript types) users were passing in a Record format instead of Array, and thus this might be seen as a breaking change. A test has been added to validate the process information to ensure proper format. Also included are sticter typing for all thrift types, removing all `any` references and replacing with valid types.
This PR contains opencensus nodejs core package.
The core package includes types and classes for opencensus domain model, exporters, and instrumentations: Span, RootSpan, Tracer, Sampler, Exporters, and Plugins (for instrumentation). Including also the Tracing interface and a default implementation for a logger and a console exporter. Unit tests included.
Opencensus-node packages are managed by Lerna.