Skip to content
This repository was archived by the owner on Jan 21, 2026. It is now read-only.

Commit 67ddb8f

Browse files
b-flightlykjin
authored andcommitted
feat: add ignoreMethods option (#920)
1 parent 72b074d commit 67ddb8f

15 files changed

Lines changed: 108 additions & 21 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Optionally, you can pass a [configuration object](src/config.ts) to the `start()
3636
require('@google-cloud/trace-agent').start({
3737
samplingRate: 5, // sample 5 traces per second, or at most 1 every 200 milliseconds.
3838
ignoreUrls: [ /^\/ignore-me#/ ] // ignore the "/ignore-me" endpoint.
39+
ignoreMethods: [ 'options' ] // ignore requests with OPTIONS method (case-insensitive).
3940
});
4041
// ...
4142
```

src/config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ export interface Config {
134134
*/
135135
ignoreUrls?: Array<string|RegExp>;
136136

137+
/**
138+
* Request methods that match any string in ignoreMethods will not be traced.
139+
* matching is *not* case-sensitive (OPTIONS == options == OptiONs)
140+
*
141+
* No methods are ignored by default.
142+
*/
143+
ignoreMethods?: string[];
144+
137145
/**
138146
* An upper bound on the number of traces to gather each second. If set to 0,
139147
* sampling is disabled and all traces are recorded. Sampling rates greater
@@ -265,6 +273,7 @@ export const defaultConfig = {
265273
stackTraceLimit: 10,
266274
flushDelaySeconds: 30,
267275
ignoreUrls: ['/_ah/health'],
276+
ignoreMethods: [],
268277
samplingRate: 10,
269278
contextHeaderBehavior: 'default',
270279
bufferSize: 1000,

src/plugin-types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ export interface SpanOptions {
103103
export interface RootSpanOptions extends SpanOptions {
104104
/* A URL associated with the root span, if applicable. */
105105
url?: string;
106+
/* A Method associated with the root span, if applicable. */
107+
method?: string;
106108
/**
107109
* The serialized form of an object that contains information about an
108110
* existing trace context, if it exists.

src/plugins/plugin-connect.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function createMiddleware(api: PluginTypes.Tracer):
4242
const options = {
4343
name: req.originalUrl ? (urlParse(req.originalUrl).pathname || '') : '',
4444
url: req.originalUrl,
45+
method: req.method,
4546
traceContext:
4647
getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME),
4748
skipFrames: 1

src/plugins/plugin-express.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ function patchModuleRoot(express: Express4Module, api: PluginTypes.Tracer) {
3939
name: req.path,
4040
traceContext: req.get(api.constants.TRACE_CONTEXT_HEADER_NAME),
4141
url: req.originalUrl,
42+
method: req.method,
4243
skipFrames: 1
4344
};
4445
api.runInRootSpan(options, (rootSpan) => {

src/plugins/plugin-hapi.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ function instrument<T>(
5151
const options: PluginTypes.RootSpanOptions = {
5252
name: req.url ? (urlParse(req.url).pathname || '') : '',
5353
url: req.url,
54+
method: req.method,
5455
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME),
5556
skipFrames: 2
5657
};

src/plugins/plugin-koa.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ function startSpanForRequest<T>(
5656
const options = {
5757
name: req.url ? (urlParse(req.url).pathname || '') : '',
5858
url: req.url,
59+
method: req.method,
5960
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME),
6061
skipFrames: 2
6162
};

src/plugins/plugin-restify.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ function patchRestify(restify: Restify5, api: PluginTypes.Tracer) {
5151
// as a label later.
5252
name: req.path(),
5353
url: req.url,
54+
method: req.method,
5455
traceContext: req.header(api.constants.TRACE_CONTEXT_HEADER_NAME),
5556
skipFrames: 1
5657
};

src/trace-api.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,11 @@ export class StackdriverTracer implements Tracer {
192192
}
193193

194194
// Consult the trace policy.
195-
const locallyAllowed = this.policy!.shouldTrace(
196-
{timestamp: Date.now(), url: options.url || ''});
195+
const locallyAllowed = this.policy!.shouldTrace({
196+
timestamp: Date.now(),
197+
url: options.url || '',
198+
method: options.method || ''
199+
});
197200
const remotelyAllowed = !!(
198201
incomingTraceContext.options & Constants.TRACE_OPTIONS_TRACE_ENABLED);
199202

src/tracing-policy.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ class URLFilter implements TracePolicyPredicate<string> {
5050
}
5151
}
5252

53+
class MethodsFilter implements TracePolicyPredicate<string> {
54+
constructor(private readonly filterMethods: string[]) {}
55+
56+
shouldTrace(method: string) {
57+
return !this.filterMethods.some((candidate) => {
58+
return (candidate.toLowerCase() === method.toLowerCase());
59+
});
60+
}
61+
}
62+
5363
/**
5464
* Options for constructing a TracePolicy instance.
5565
*/
@@ -62,6 +72,10 @@ export interface TracePolicyConfig {
6272
* A field that controls a url-based filter.
6373
*/
6474
ignoreUrls: Array<string|RegExp>;
75+
/**
76+
* A field that controls a method filter.
77+
*/
78+
ignoreMethods: string[];
6579
}
6680

6781
/**
@@ -70,6 +84,7 @@ export interface TracePolicyConfig {
7084
export class TracePolicy {
7185
private readonly sampler: TracePolicyPredicate<number>;
7286
private readonly urlFilter: TracePolicyPredicate<string>;
87+
private readonly methodsFilter: TracePolicyPredicate<string>;
7388

7489
/**
7590
* Constructs a new TracePolicy instance.
@@ -88,23 +103,32 @@ export class TracePolicy {
88103
} else {
89104
this.urlFilter = new URLFilter(config.ignoreUrls);
90105
}
106+
if (config.ignoreMethods.length === 0) {
107+
this.methodsFilter = {shouldTrace: () => true};
108+
} else {
109+
this.methodsFilter = new MethodsFilter(config.ignoreMethods);
110+
}
91111
}
92112

93113
/**
94114
* Given a timestamp and URL, decides if a trace should be created.
95115
* @param options Fields that help determine whether a trace should be
96116
* created.
97117
*/
98-
shouldTrace(options: {timestamp: number, url: string}): boolean {
118+
shouldTrace(options: {timestamp: number, url: string, method: string}):
119+
boolean {
99120
return this.sampler.shouldTrace(options.timestamp) &&
100-
this.urlFilter.shouldTrace(options.url);
121+
this.urlFilter.shouldTrace(options.url) &&
122+
this.methodsFilter.shouldTrace(options.method);
101123
}
102124

103125
static always(): TracePolicy {
104-
return new TracePolicy({samplingRate: 0, ignoreUrls: []});
126+
return new TracePolicy(
127+
{samplingRate: 0, ignoreUrls: [], ignoreMethods: []});
105128
}
106129

107130
static never(): TracePolicy {
108-
return new TracePolicy({samplingRate: -1, ignoreUrls: []});
131+
return new TracePolicy(
132+
{samplingRate: -1, ignoreUrls: [], ignoreMethods: []});
109133
}
110134
}

0 commit comments

Comments
 (0)