Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added http ignore by method #49

Merged
merged 2 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Environment Variable | Description | Default
| `SW_AGENT_DISABLE_PLUGINS` | Comma-delimited list of plugins to disable in the plugins directory (e.g. "mysql", "express"). | `` |
| `SW_IGNORE_SUFFIX` | The suffices of endpoints that will be ignored (not traced), comma separated | `.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg` |
| `SW_TRACE_IGNORE_PATH` | The paths of endpoints that will be ignored (not traced), comma separated | `` |
| `SW_HTTP_IGNORE_METHOD` | Comma-delimited list of http methods to ignore (GET, POST, HEAD, OPTIONS, etc...) | `` |
| `SW_SQL_TRACE_PARAMETERS` | If set to 'true' then SQL query parameters will be included | `false` |
| `SW_SQL_PARAMETERS_MAX_LENGTH` | The maximum string length of SQL parameters to log | `512` |
| `SW_MONGO_TRACE_PARAMETERS` | If set to 'true' then mongodb query parameters will be included | `false` |
Expand Down
13 changes: 12 additions & 1 deletion src/config/AgentConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ export type AgentConfig = {
disablePlugins?: string;
ignoreSuffix?: string;
traceIgnorePath?: string;
httpIgnoreMethod?: string;
sqlTraceParameters?: boolean;
sqlParametersMaxLength?: number;
mongoTraceParameters?: boolean;
mongoParametersMaxLength?: number;
// the following is internal state computed from config values
reDisablePlugins?: RegExp;
reIgnoreOperation?: RegExp;
reHttpIgnoreMethod?: RegExp;
};

export function finalizeConfig(config: AgentConfig): void {
Expand All @@ -53,9 +55,10 @@ export function finalizeConfig(config: AgentConfig): void {
).join('|') + ')$'; // replaces ","

config.reIgnoreOperation = RegExp(`${ignoreSuffix}|${ignorePath}`);
config.reHttpIgnoreMethod = RegExp(`^(?:${config.httpIgnoreMethod!.split(',').map((s) => s.trim()).join('|')})$`, 'i');
}

export default {
const _config = {
serviceName: process.env.SW_AGENT_NAME || 'your-nodejs-service',
serviceInstance:
process.env.SW_AGENT_INSTANCE ||
Expand All @@ -70,10 +73,18 @@ export default {
disablePlugins: process.env.SW_AGENT_DISABLE_PLUGINS || '',
ignoreSuffix: process.env.SW_IGNORE_SUFFIX ?? '.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg',
traceIgnorePath: process.env.SW_TRACE_IGNORE_PATH || '',
httpIgnoreMethod: process.env.SW_HTTP_IGNORE_METHOD || '',
sqlTraceParameters: (process.env.SW_SQL_TRACE_PARAMETERS || '').toLowerCase() === 'true',
sqlParametersMaxLength: Math.trunc(Math.max(0, Number(process.env.SW_SQL_PARAMETERS_MAX_LENGTH))) || 512,
mongoTraceParameters: (process.env.SW_MONGO_TRACE_PARAMETERS || '').toLowerCase() === 'true',
mongoParametersMaxLength: Math.trunc(Math.max(0, Number(process.env.SW_MONGO_PARAMETERS_MAX_LENGTH))) || 512,
reDisablePlugins: RegExp(''), // temporary placeholder so Typescript doesn't throw a fit
reIgnoreOperation: RegExp(''),
reHttpIgnoreMethod: RegExp(''),
};

export default _config;

export function ignoreHttpMethodCheck(method: string): boolean {
return Boolean(method.match(_config.reHttpIgnoreMethod));
}
8 changes: 5 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ class Agent {
return;
}

if (this.started) {
logger.warn('SkyWalking agent started more than once, subsequent options to start ignored.');
return;
}

Object.assign(config, options);
finalizeConfig(config);

if (this.started) {
throw new Error('SkyWalking agent is already started and can only be started once.');
}
logger.debug('Starting SkyWalking agent');

this.started = true;
Expand Down
11 changes: 8 additions & 3 deletions src/plugins/AxiosPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
*
*/

import SwPlugin, {wrapPromise} from '../core/SwPlugin';
import SwPlugin from '../core/SwPlugin';
import { URL } from 'url';
import ContextManager from '../trace/context/ContextManager';
import { Component } from '../trace/Component';
import Tag from '../Tag';
import { SpanLayer } from '../proto/language-agent/Tracing_pb';
import DummySpan from '../trace/span/DummySpan';
import { ignoreHttpMethodCheck } from '../config/AgentConfig';
import PluginInstaller from '../core/PluginInstaller';

class AxiosPlugin implements SwPlugin {
Expand All @@ -44,7 +46,10 @@ class AxiosPlugin implements SwPlugin {
config = url ? {...url} : {};

const {origin, host, pathname: operation} = new URL(config.url); // TODO: this may throw invalid URL
const span = ContextManager.current.newExitSpan(operation, host, Component.AXIOS, Component.HTTP);
const method = (config.method || 'GET').toUpperCase();
const span = ignoreHttpMethodCheck(method)
? DummySpan.create()
: ContextManager.current.newExitSpan(operation, host, Component.AXIOS, Component.HTTP);

span.start();

Expand All @@ -56,7 +61,7 @@ class AxiosPlugin implements SwPlugin {
span.peer = host;

span.tag(Tag.httpURL(origin + operation));
span.tag(Tag.httpMethod((config.method || 'GET').toUpperCase()));
span.tag(Tag.httpMethod(method));

span.inject().items.forEach((item) => config.headers[item.key] = item.value);

Expand Down
7 changes: 5 additions & 2 deletions src/plugins/ExpressPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import { IncomingMessage, ServerResponse } from 'http';
import ContextManager from '../trace/context/ContextManager';
import { Component } from '../trace/Component';
import Tag from '../Tag';
import EntrySpan from '../trace/span/EntrySpan';
import { ContextCarrier } from '../trace/context/ContextCarrier';
import DummySpan from '../trace/span/DummySpan';
import { ignoreHttpMethodCheck } from '../config/AgentConfig';
import PluginInstaller from '../core/PluginInstaller';
import HttpPlugin from './HttpPlugin';

Expand All @@ -42,7 +43,9 @@ class ExpressPlugin implements SwPlugin {
router.handle = function(req: IncomingMessage, res: ServerResponse, next: any) {
const carrier = ContextCarrier.from((req as any).headers || {});
const operation = (req.url || '/').replace(/\?.*/g, '');
const span: EntrySpan = ContextManager.current.newEntrySpan(operation, carrier, Component.HTTP_SERVER) as EntrySpan;
const span = ignoreHttpMethodCheck(req.method ?? 'GET')
? DummySpan.create()
: ContextManager.current.newEntrySpan(operation, carrier, Component.HTTP_SERVER);

span.component = Component.EXPRESS;

Expand Down
16 changes: 11 additions & 5 deletions src/plugins/HttpPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ import ContextManager from '../trace/context/ContextManager';
import { Component } from '../trace/Component';
import Tag from '../Tag';
import Span from '../trace/span/Span';
import ExitSpan from '../trace/span/ExitSpan';
import { SpanLayer } from '../proto/language-agent/Tracing_pb';
import { ContextCarrier } from '../trace/context/ContextCarrier';
import DummySpan from '../trace/span/DummySpan';
import { ignoreHttpMethodCheck } from '../config/AgentConfig';

class HttpPlugin implements SwPlugin {
readonly module = 'http';
Expand Down Expand Up @@ -59,7 +60,10 @@ class HttpPlugin implements SwPlugin {
};

const operation = pathname.replace(/\?.*$/g, '');
const span: ExitSpan = ContextManager.current.newExitSpan(operation, host, Component.HTTP) as ExitSpan;
const method = arguments[url instanceof URL || typeof url === 'string' ? 1 : 0]?.method || 'GET';
const span = ignoreHttpMethodCheck(method)
? DummySpan.create()
: ContextManager.current.newExitSpan(operation, host, Component.HTTP);

if (span.depth) // if we inherited from a higher level plugin then do nothing, higher level should do all the work and we don't duplicate here
return _request.apply(this, arguments);
Expand All @@ -72,7 +76,7 @@ class HttpPlugin implements SwPlugin {
span.peer = host;

span.tag(Tag.httpURL(protocol + '://' + host + pathname));
span.tag(Tag.httpMethod(arguments[url instanceof URL || typeof url === 'string' ? 1 : 0]?.method || 'GET'));
span.tag(Tag.httpMethod(method));

const copyStatusAndWrapEmit = (res: any) => {
span.tag(Tag.httpStatusCode(res.statusCode));
Expand Down Expand Up @@ -146,7 +150,9 @@ class HttpPlugin implements SwPlugin {
function _sw_request(this: any, req: IncomingMessage, res: ServerResponse, ...reqArgs: any[]) {
const carrier = ContextCarrier.from((req as any).headers || {});
const operation = (req.url || '/').replace(/\?.*/g, '');
const span = ContextManager.current.newEntrySpan(operation, carrier);
const span = ignoreHttpMethodCheck(req.method ?? 'GET')
? DummySpan.create()
: ContextManager.current.newEntrySpan(operation, carrier);

span.component = Component.HTTP_SERVER;

Expand All @@ -168,7 +174,7 @@ class HttpPlugin implements SwPlugin {
? `[${req.connection.remoteAddress}]:${req.connection.remotePort}`
: `${req.connection.remoteAddress}:${req.connection.remotePort}`);

span.tag(Tag.httpMethod(req.method));
span.tag(Tag.httpMethod(req.method ?? 'GET'));

const ret = handler();

Expand Down
7 changes: 1 addition & 6 deletions src/trace/context/DummyContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,10 @@ import Span from '../../trace/span/Span';
import DummySpan from '../../trace/span/DummySpan';
import Segment from '../../trace/context/Segment';
import { Component } from '../../trace/Component';
import { SpanType } from '../../proto/language-agent/Tracing_pb';
import { ContextCarrier } from './ContextCarrier';

export default class DummyContext implements Context {
span: Span = new DummySpan({
context: this,
operation: '',
type: SpanType.LOCAL,
});
span: Span = DummySpan.create(this);
segment: Segment = new Segment();
nSpans = 0;

Expand Down
10 changes: 2 additions & 8 deletions src/trace/context/SpanContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import config from '../../config/AgentConfig';
import Context from '../../trace/context/Context';
import DummyContext from '../../trace/context/DummyContext';
import Span from '../../trace/span/Span';
import DummySpan from '../../trace/span/DummySpan';
import Segment from '../../trace/context/Segment';
Expand Down Expand Up @@ -53,13 +52,8 @@ export default class SpanContext implements Context {
}

ignoreCheck(operation: string, type: SpanType): Span | undefined {
if (operation.match(config.reIgnoreOperation)) {
return new DummySpan({
context: new DummyContext(),
operation: '',
type,
});
}
if (operation.match(config.reIgnoreOperation))
return DummySpan.create();

return undefined;
}
Expand Down
11 changes: 11 additions & 0 deletions src/trace/span/DummySpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,19 @@

import Span from '../../trace/span/Span';
import { ContextCarrier } from '../context/ContextCarrier';
import Context from '../context/Context';
import { SpanType } from '../../proto/language-agent/Tracing_pb';
import DummyContext from '../context/DummyContext';

export default class DummySpan extends Span {
static create(context?: Context): DummySpan {
return new DummySpan({
context: context ?? new DummyContext(),
operation: '',
type: SpanType.LOCAL,
});
}

inject(): ContextCarrier {
return new ContextCarrier();
}
Expand Down
4 changes: 2 additions & 2 deletions src/trace/span/EntrySpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
*
*/

import StackedSpan from '../../trace/span/StackedSpan';
import Span from '../../trace/span/Span';
import { SpanCtorOptions } from './Span';
import SegmentRef from '../../trace/context/SegmentRef';
import { SpanType } from '../../proto/language-agent/Tracing_pb';
import { ContextCarrier } from '../context/ContextCarrier';

export default class EntrySpan extends StackedSpan {
export default class EntrySpan extends Span {
constructor(options: SpanCtorOptions) {
super(
Object.assign(options, {
Expand Down
4 changes: 2 additions & 2 deletions src/trace/span/ExitSpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
*
*/

import StackedSpan from '../../trace/span/StackedSpan';
import Span from '../../trace/span/Span';
import { SpanCtorOptions } from './Span';
import config from '../../config/AgentConfig';
import { SpanType } from '../../proto/language-agent/Tracing_pb';
import { ContextCarrier } from '../context/ContextCarrier';
import ContextManager from '../context/ContextManager';

export default class ExitSpan extends StackedSpan {
export default class ExitSpan extends Span {
constructor(options: SpanCtorOptions) {
super(
Object.assign(options, {
Expand Down
10 changes: 7 additions & 3 deletions src/trace/span/Span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export default abstract class Span {
operation: string;
layer = SpanLayer.UNKNOWN;
component = Component.UNKNOWN;
depth = 0;
inherit?: Component;

readonly tags: Tag[] = [];
Expand All @@ -74,12 +75,15 @@ export default abstract class Span {
}

start(): void {
this.startTime = new Date().getTime();
this.context.start(this);
if (++this.depth === 1) {
this.startTime = new Date().getTime();
this.context.start(this);
}
}

stop(): void {
this.context.stop(this);
if (--this.depth === 0)
this.context.stop(this);
}

async(): void {
Expand Down
41 changes: 0 additions & 41 deletions src/trace/span/StackedSpan.ts

This file was deleted.