Skip to content

Commit

Permalink
feat: rename TraceAgent/TraceApi to Tracer (#815)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `TraceAgent` has been renamed to `Tracer`. In plugins, `Patch` has been renamed `Monkeypatch`, and `Patch` is now `Monkeypatch|Intercept` (this is a rename of `Instrumentation`). There are no user-visible JS changes.

`TraceAgent` is a misnomer since the module as a whole is the "agent", not the object that is returned when the Trace Agent is started. (This is already reflected in the docs, where it has been called `TraceApi`). This change makes things consistent so it is called `Tracer` everywhere.

The one implementation of `TraceAgent` (which was also called `TraceAgent`) is now `StackdriverTracer`. This object is never constructed by the user, so this is a no-op change for JS users.

A couple of unused imports have also been removed.
  • Loading branch information
kjin committed Jul 19, 2018
1 parent 4ac6ded commit dde86d3
Show file tree
Hide file tree
Showing 22 changed files with 126 additions and 131 deletions.
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -43,8 +43,8 @@ require('@google-cloud/trace-agent').start({
The object returned by `start()` may be used to create [custom trace spans](#custom-tracing-api):

```js
const traceApi = require('@google-cloud/trace-agent').start();
traceApi.runInRootSpan({ name: 'my-root-span' }, (rootSpan) => {
const tracer = require('@google-cloud/trace-agent').start();
tracer.runInRootSpan({ name: 'my-root-span' }, (rootSpan) => {
// ...
rootSpan.endSpan();
});
Expand Down Expand Up @@ -99,22 +99,22 @@ For any of the web frameworks for which we provide [built-in plugins](#what-gets

### Accessing the API

Calling the `start` function returns an instance of `TraceApi`, which provides an interface for tracing:
Calling the `start` function returns an instance of `Tracer`, which provides an interface for tracing:

```js
const traceApi = require('@google-cloud/trace-agent').start();
const tracer = require('@google-cloud/trace-agent').start();
```

It can also be retrieved by subsequent calls to `get` elsewhere:

```js
// after start() is called
const traceApi = require('@google-cloud/trace-agent').get();
const tracer = require('@google-cloud/trace-agent').get();
```

A `TraceApi` object is guaranteed to be returned by both of these calls, even if the agent is disabled.
A `Tracer` object is guaranteed to be returned by both of these calls, even if the agent is disabled.

A fully detailed overview of the `TraceApi` object is available [here](doc/trace-api.md).
A fully detailed overview of the `Tracer` object is available [here](doc/trace-api.md).

## How does automatic tracing work?

Expand Down
30 changes: 15 additions & 15 deletions doc/trace-api.md
@@ -1,41 +1,41 @@
# The `TraceApi` Object
# The `Tracer` Object

A `TraceApi` instance provides functions that facilitate the following:
A `Tracer` instance provides functions that facilitate the following:

- Creating trace spans and add labels to them.
- Getting information about how the trace agent was configured in the current application.
- Parsing and serializing trace contexts to support distributed tracing between microservices.
- Binding callbacks and event emitters in order to propagate trace contexts across asynchronous boundaries.

In addition to the above, `TraceApi` also provides a number of well-known label keys and constants through its `labels` and `constants` fields respectively.
In addition to the above, `Tracer` also provides a number of well-known label keys and constants through its `labels` and `constants` fields respectively.

## Trace Spans

These functions provide the capability to create trace spans, add labels to them, and close them.

* `TraceApi#runInRootSpan(options, fn)`
* `Tracer#runInRootSpan(options, fn)`
* `options`: [`TraceOptions`](#trace-span-options)
* `fn`: `function(Span): any`
* Returns `any` (return value of `fn`)
* Creates a root span and runs the given callback, passing it a `Span` object. In some instances, this `Span` object doesn't correspond to an actual trace span; this can be checked by consulting the value of `Span#type`:
* `TraceApi#spanTypes.ROOT`: This object corresponds to a real trace span.
* `TraceApi#spanTypes.UNTRACED`: There isn't a real trace span corresponding to this object, for one of the following reasons:
* `Tracer#spanTypes.ROOT`: This object corresponds to a real trace span.
* `Tracer#spanTypes.UNTRACED`: There isn't a real trace span corresponding to this object, for one of the following reasons:
* The trace policy, as specified by the user-given configuration, disallows a root span from being created under the current circumstances.
* The trace agent is disabled, either because it wasn't started at all, started in disabled mode, or encountered an initialization error.
* The incoming request had headers that explicitly specified that this request shouldn't be traced.
* `TraceApi#spanTypes.UNCORRELATED`: `runInRootSpan` was called for a request that already has a root span. This likely indicates a programmer error, as nested root spans are not allowed.
* `Tracer#spanTypes.UNCORRELATED`: `runInRootSpan` was called for a request that already has a root span. This likely indicates a programmer error, as nested root spans are not allowed.
* **Note:** You must call `endSpan` on the span object provided as an argument for the span to be recorded.
* `TraceApi#createChildSpan(options)`
* `Tracer#createChildSpan(options)`
* `options`: [`TraceOptions`](#trace-span-options)
* Returns `Span`
* Creates a child `Span` object and returns it. In some instances, this `Span` object doesn't correspond to an actual trace span; this can be checked by consulting the value of `Span#type`:
* `TraceApi#spanTypes.CHILD`: This object corresponds to a real trace span.
* `TraceApi#spanTypes.UNTRACED`: There isn't a real trace span corresponding to this object, because this span's parent is also an `UNTRACED` (root) span.
* `TraceApi#spanTypes.UNCORRELATED`: There isn't a real trace span corresponding to this object, for one of the following reasons:
* `Tracer#spanTypes.CHILD`: This object corresponds to a real trace span.
* `Tracer#spanTypes.UNTRACED`: There isn't a real trace span corresponding to this object, because this span's parent is also an `UNTRACED` (root) span.
* `Tracer#spanTypes.UNCORRELATED`: There isn't a real trace span corresponding to this object, for one of the following reasons:
* A root span wasn't created beforehand because `runInRootSpan` was not called at all. This likely indicates a programmer error, because child spans should always be nested within a root span.
* A root span was created beforehand, but context was lost between then and now. This may also be a programmer error, because child spans should always be created within the context of a root span. See [`Context Propagation`](#context-propagation) for details on properly propagating root span context.
* **Note:** You must call `endSpan` on the returned span object for the span to be recorded.
* `TraceApi#spanTypes`
* `Tracer#spanTypes`
* An enumeration of the types of spans: `ROOT`, `CHILD`, `UNTRACED`, `UNCORRELATED`
* `Span#addLabel(key, value)`
* `key`: `string`
Expand Down Expand Up @@ -64,7 +64,7 @@ Some functions above accept a `TraceOptions` object, which has the following fie

## Trace Agent Configuration

* `TraceApi#enhancedDatabaseReportingEnabled()`
* `Tracer#enhancedDatabaseReportingEnabled()`
* Returns `boolean`
* Returns whether the trace agent was started with an enhanced level of reporting. See the [configuration][config-js] object definition for more details.

Expand All @@ -78,11 +78,11 @@ Trace context is sent and received using the [`'x-cloud-trace-context'`][stackdr

Plugins that trace incoming HTTP requests (in other words, web frameworks) should support cross-service tracing by reading serialized trace context from the `'x-cloud-trace-context'` header, and supplying it as the [`traceContext` option](#trace-span-options) when creating a new root span. The trace agent will automatically deserialize the trace context and associate any new spans with it.

The string `'x-cloud-trace-context'` is provided as `TraceApi#constants.TRACE_CONTEXT_HEADER_NAME`.
The string `'x-cloud-trace-context'` is provided as `Tracer#constants.TRACE_CONTEXT_HEADER_NAME`.

It is highly recommended for plugins to set this header field in responses, _if_ the incoming request has this header. The trace context that should be written can be obtained with the following function:

* `TraceApi#getResponseTraceContext(incomingTraceContext, isTraced)`
* `Tracer#getResponseTraceContext(incomingTraceContext, isTraced)`
* `incomingTraceContext`: `string`
* `isTraced`: `boolean`
* Returns `string`
Expand Down
8 changes: 4 additions & 4 deletions src/constants.ts
Expand Up @@ -70,14 +70,14 @@ export enum SpanType {
UNTRACED = 'UNTRACED',

/**
* This span object was created by TraceAgent#runInRootSpan, and represents
* an incoming request.
* This span object was created by StackdriverTracer#runInRootSpan, and
* represents an incoming request.
*/
ROOT = 'ROOT',

/**
* This span object was created by TraceAgent#createChildSpan, and represents
* an outgoing RPC on behalf of an incoming request.
* This span object was created by StackdriverTracer#createChildSpan, and
* represents an outgoing RPC on behalf of an incoming request.
*/
CHILD = 'CHILD'
}
18 changes: 9 additions & 9 deletions src/index.ts
Expand Up @@ -23,14 +23,14 @@ import {Config, defaultConfig} from './config';
import * as extend from 'extend';
import * as path from 'path';
import * as PluginTypes from './plugin-types';
import {tracing, Tracing, NormalizedConfig} from './tracing';
import {Singleton, FORCE_NEW, Forceable} from './util';
import {Tracing, NormalizedConfig} from './tracing';
import {FORCE_NEW, Forceable} from './util';
import {Constants} from './constants';
import {TraceAgent} from './trace-api';
import {StackdriverTracer} from './trace-api';

export {Config, PluginTypes};

let traceAgent: TraceAgent;
let traceAgent: StackdriverTracer;

/**
* Normalizes the user-provided configuration object by adding default values
Expand Down Expand Up @@ -100,7 +100,7 @@ function initConfig(projectConfig: Forceable<Config>):
* @example
* trace.start();
*/
export function start(config?: Config): PluginTypes.TraceAgent {
export function start(config?: Config): PluginTypes.Tracer {
const normalizedConfig = initConfig(config || {});
// Determine the preferred context propagation mechanism, as
// continuation-local-storage should be loaded before any modules that do I/O.
Expand All @@ -111,7 +111,7 @@ export function start(config?: Config): PluginTypes.TraceAgent {
}

if (!traceAgent) {
traceAgent = new (require('./trace-api').TraceAgent)();
traceAgent = new (require('./trace-api').StackdriverTracer)();
}

try {
Expand All @@ -135,12 +135,12 @@ export function start(config?: Config): PluginTypes.TraceAgent {
}

/**
* Get the previously created TraceAgent object.
* Get the previously created StackdriverTracer object.
* @returns An object exposing functions for creating custom spans.
*/
export function get(): PluginTypes.TraceAgent {
export function get(): PluginTypes.Tracer {
if (!traceAgent) {
traceAgent = new (require('./trace-api').TraceAgent)();
traceAgent = new (require('./trace-api').StackdriverTracer)();
}
return traceAgent;
}
Expand Down
13 changes: 7 additions & 6 deletions src/plugin-types.ts
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

// This file only describes public-facing interfaces.
// tslint:disable:no-any

import {Constants, SpanType} from './constants';
Expand Down Expand Up @@ -106,7 +107,7 @@ export interface RootSpanOptions extends SpanOptions {
traceContext?: string|null;
}

export interface TraceAgent {
export interface Tracer {
/**
* Gets the value of enhancedDatabaseReporting in the trace agent's
* configuration object.
Expand Down Expand Up @@ -228,19 +229,19 @@ export interface TraceAgent {
};
}

export interface Patch<T> {
export interface Monkeypatch<T> {
file?: string;
versions?: string;
patch: (module: T, agent: TraceAgent) => void;
patch: (module: T, agent: Tracer) => void;
unpatch?: (module: T) => void;
}

export interface Intercept<T> {
file?: string;
versions?: string;
intercept: (module: T, agent: TraceAgent) => T;
intercept: (module: T, agent: Tracer) => T;
}

export type Instrumentation<T> = Patch<T>|Intercept<T>;
export type Patch<T> = Monkeypatch<T>|Intercept<T>;

export type Plugin = Array<Instrumentation<any>>;
export type Plugin = Array<Patch<any>>;
3 changes: 1 addition & 2 deletions src/plugins/plugin-connect.ts
Expand Up @@ -15,7 +15,6 @@
*/

import {IncomingMessage, ServerResponse} from 'http';
import * as shimmer from 'shimmer';
import {parse as urlParse} from 'url';

import {PluginTypes} from '..';
Expand All @@ -37,7 +36,7 @@ function getFirstHeader(req: IncomingMessage, key: string): string|null {
return headerValue;
}

function createMiddleware(api: PluginTypes.TraceAgent):
function createMiddleware(api: PluginTypes.Tracer):
connect_3.NextHandleFunction {
return function middleware(req: Request, res, next) {
const options = {
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/plugin-express.ts
Expand Up @@ -30,7 +30,7 @@ const methods: Array<keyof express_4.Application> =

const SUPPORTED_VERSIONS = '4.x';

function patchModuleRoot(express: Express4Module, api: PluginTypes.TraceAgent) {
function patchModuleRoot(express: Express4Module, api: PluginTypes.Tracer) {
const labels = api.labels;
function middleware(
req: express_4.Request, res: express_4.Response,
Expand Down Expand Up @@ -106,6 +106,6 @@ const plugin: PluginTypes.Plugin = [{
versions: SUPPORTED_VERSIONS,
patch: patchModuleRoot,
unpatch: unpatchModuleRoot
} as PluginTypes.Patch<Express4Module>];
} as PluginTypes.Monkeypatch<Express4Module>];

export = plugin;
8 changes: 4 additions & 4 deletions src/plugins/plugin-grpc.ts
Expand Up @@ -19,7 +19,7 @@ import * as grpcModule from 'grpc'; // for types only.
import {Client, MethodDefinition, ServerReadableStream, ServerUnaryCall, StatusObject} from 'grpc';
import * as shimmer from 'shimmer';

import {Plugin, RootSpan, RootSpanOptions, Span, TraceAgent} from '../plugin-types';
import {Plugin, RootSpan, RootSpanOptions, Span, Tracer} from '../plugin-types';

// Re-definition of Metadata with private fields
type Metadata = grpcModule.Metadata&{
Expand Down Expand Up @@ -97,7 +97,7 @@ const SKIP_FRAMES = 1;
// tslint:disable-next-line:variable-name
let MetadataModuleValue: MetadataModule;

function patchMetadata(metadata: MetadataModule, api: TraceAgent) {
function patchMetadata(metadata: MetadataModule, api: Tracer) {
// metadata is the value of module.exports of src/node/src/metadata.js
MetadataModuleValue = metadata;
}
Expand All @@ -107,7 +107,7 @@ function unpatchMetadata() {
// So it's safe to provide a no-op unpatch function.
}

function patchClient(client: ClientModule, api: TraceAgent) {
function patchClient(client: ClientModule, api: Tracer) {
/**
* Set trace context on a Metadata object if it exists.
* @param metadata The Metadata object to which a trace context should be
Expand Down Expand Up @@ -281,7 +281,7 @@ function unpatchClient(client: ClientModule) {
shimmer.unwrap(client, 'makeClientConstructor');
}

function patchServer(server: ServerModule, api: TraceAgent) {
function patchServer(server: ServerModule, api: Tracer) {
/**
* Returns a trace context on a Metadata object if it exists and is
* well-formed, or null otherwise. The result will be encoded as a string.
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/plugin-hapi.ts
Expand Up @@ -43,7 +43,7 @@ function getFirstHeader(req: IncomingMessage, key: string): string|null {
}

function instrument<T>(
api: PluginTypes.TraceAgent, request: hapi_16.Request|hapi_17.Request,
api: PluginTypes.Tracer, request: hapi_16.Request|hapi_17.Request,
continueCb: () => T): T {
const req = request.raw.req;
const res = request.raw.res;
Expand Down Expand Up @@ -124,7 +124,7 @@ const plugin: PluginTypes.Plugin = [
unpatch: (hapi) => {
shimmer.unwrap(hapi.Server.prototype, 'connection');
}
} as PluginTypes.Patch<Hapi16Module>,
} as PluginTypes.Monkeypatch<Hapi16Module>,
/**
* In Hapi 17, the work that is done on behalf of a request stems from
* Request#_execute. We patch that function to ensure that context is
Expand Down Expand Up @@ -153,6 +153,6 @@ const plugin: PluginTypes.Plugin = [
Request.prototype._execute = Request.prototype._execute[ORIGINAL]!;
}
}
} as PluginTypes.Patch<{prototype: Hapi17Request}>
} as PluginTypes.Monkeypatch<{prototype: Hapi17Request}>
];
export = plugin;
11 changes: 5 additions & 6 deletions src/plugins/plugin-http.ts
Expand Up @@ -22,7 +22,7 @@ import * as semver from 'semver';
import * as shimmer from 'shimmer';
import * as url from 'url';

import {Plugin, TraceAgent} from '../plugin-types';
import {Plugin, Tracer} from '../plugin-types';

type HttpModule = typeof httpModule;
type HttpsModule = typeof httpsModule;
Expand Down Expand Up @@ -78,14 +78,13 @@ function extractUrl(
}

// tslint:disable-next-line:no-any
function isTraceAgentRequest(options: any, api: TraceAgent) {
function isTraceAgentRequest(options: any, api: Tracer) {
return options && options.headers &&
!!options.headers[api.constants.TRACE_AGENT_REQUEST_HEADER];
}

function makeRequestTrace(
protocol: string, request: RequestFunction,
api: TraceAgent): RequestFunction {
protocol: string, request: RequestFunction, api: Tracer): RequestFunction {
// On Node 8+ we use the following function to patch both request and get.
// Here `request` may also happen to be `get`.
return function requestTrace(options, callback): ClientRequest {
Expand Down Expand Up @@ -187,7 +186,7 @@ function makeRequestTrace(
};
}

function patchHttp(http: HttpModule, api: TraceAgent) {
function patchHttp(http: HttpModule, api: Tracer) {
shimmer.wrap(http, 'request', (request) => {
return makeRequestTrace('http:', request, api);
});
Expand Down Expand Up @@ -217,7 +216,7 @@ function patchHttp(http: HttpModule, api: TraceAgent) {

// https.get depends on Node http internals in 8.9.0 and 9+ instead of the
// public http module.
function patchHttps(https: HttpsModule, api: TraceAgent) {
function patchHttps(https: HttpsModule, api: Tracer) {
shimmer.wrap(https, 'request', (request) => {
return makeRequestTrace('https:', request, api);
});
Expand Down

0 comments on commit dde86d3

Please sign in to comment.