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

Cold start detection and marking #52

Merged
merged 1 commit into from
May 20, 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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ Environment Variable | Description | Default
| `SW_AGENT_SECURE` | Whether to use secure connection to backend OAP server | `false` |
| `SW_AGENT_AUTHENTICATION` | The authentication token to verify that the agent is trusted by the backend OAP, as for how to configure the backend, refer to [the yaml](https://github.com/apache/skywalking/blob/4f0f39ffccdc9b41049903cc540b8904f7c9728e/oap-server/server-bootstrap/src/main/resources/application.yml#L155-L158). | not set |
| `SW_AGENT_LOGGING_LEVEL` | The logging level, could be one of `error`, `warn`, `info`, `debug` | `info` |
| `SW_AGENT_DISABLE_PLUGINS` | Comma-delimited list of plugins to disable in the plugins directory (e.g. "mysql", "express"). | `` |
| `SW_AGENT_DISABLE_PLUGINS` | Comma-delimited list of plugins to disable in the plugins directory (e.g. "mysql", "express") | `` |
| `SW_COLD_ENDPOINT` | Cold start detection is as follows: First span to run within 1 second of skywalking init is considered a cold start. This span gets the tag `coldStart` set to 'true'. This span also optionally gets the text '\<cold\>' appended to the endpoint name if SW_COLD_ENDPOINT is set to 'true'. | `false` |
| `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...) | `` |
Expand Down
8 changes: 8 additions & 0 deletions src/Tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface Tag {
}

export default {
coldStartKey: 'coldStart',
httpStatusCodeKey: 'http.status.code', // TODO: maybe find a better place to put these?
httpStatusMsgKey: 'http.status.msg',
httpURLKey: 'http.url',
Expand All @@ -37,6 +38,13 @@ export default {
mqTopicKey: 'mq.topic',
mqQueueKey: 'mq.queue',

coldStart(val: boolean = true): Tag {
return {
key: this.coldStartKey,
overridable: true,
val: `${val}`,
} as Tag;
},
httpStatusCode(val: string | number | undefined): Tag {
return {
key: this.httpStatusCodeKey,
Expand Down
2 changes: 1 addition & 1 deletion src/azure/AzureHttpTriggerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class AzureHttpTriggerPlugin {
: ContextManager.current.newEntrySpan(operation, carrier);

span.layer = SpanLayer.HTTP;
span.component = Component.AZURE_HTTPTRIGGER ;
span.component = Component.AZURE_HTTPTRIGGER;
span.peer = (req.headers['x-forwarded-for'] || '???').split(',').shift();

span.tag(Tag.httpMethod(req.method));
Expand Down
4 changes: 3 additions & 1 deletion src/config/AgentConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type AgentConfig = {
secure?: boolean;
authorization?: string;
maxBufferSize?: number;
coldEndpoint?: boolean;
disablePlugins?: string;
ignoreSuffix?: string;
traceIgnorePath?: string;
Expand Down Expand Up @@ -66,10 +67,11 @@ const _config = {
return os.hostname();
})(),
collectorAddress: process.env.SW_AGENT_COLLECTOR_BACKEND_SERVICES || '127.0.0.1:11800',
secure: process.env.SW_AGENT_SECURE?.toLocaleLowerCase() === 'true',
secure: process.env.SW_AGENT_SECURE?.toLowerCase() === 'true',
authorization: process.env.SW_AGENT_AUTHENTICATION,
maxBufferSize: Number.isSafeInteger(process.env.SW_AGENT_MAX_BUFFER_SIZE) ?
Number.parseInt(process.env.SW_AGENT_MAX_BUFFER_SIZE as string, 10) : 1000,
coldEndpoint: process.env.SW_COLD_ENDPOINT?.toLowerCase() === 'true',
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 || '',
Expand Down
13 changes: 13 additions & 0 deletions src/trace/context/ContextManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ if (async_hooks.AsyncLocalStorage) {
}

class ContextManager {
isCold = true;

cosntructor() {
setTimeout(() => this.isCold = false, 1000).unref();
}

checkCold(): boolean {
const isCold = this.isCold;
this.isCold = false;

return isCold;
}

get asyncState(): AsyncState {
let asyncState = store.getStore();

Expand Down
10 changes: 6 additions & 4 deletions src/trace/context/DummyContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,20 @@ export default class DummyContext implements Context {
return DummySpan.create(this);
}

start(span: Span): Context {
start(span: DummySpan): Context {
const spans = ContextManager.spansDup();

if (!this.nSpans++) {
ContextManager.checkCold(); // set cold to false

if (spans.indexOf(span) === -1)
spans.push(span);
}

return this;
}

stop(span: Span): boolean {
stop(span: DummySpan): boolean {
if (--this.nSpans)
return false;

Expand All @@ -62,11 +64,11 @@ export default class DummyContext implements Context {
return true;
}

async(span: Span) {
async(span: DummySpan) {
ContextManager.clear(span);
}

resync(span: Span) {
resync(span: DummySpan) {
ContextManager.restore(span);
}
}
8 changes: 7 additions & 1 deletion src/trace/context/SpanContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import ExitSpan from '../../trace/span/ExitSpan';
import LocalSpan from '../../trace/span/LocalSpan';
import SegmentRef from './SegmentRef';
import ContextManager from './ContextManager';
import Tag from '../../Tag';
import { Component } from '../../trace/Component';
import { createLogger } from '../../logging';
import { ContextCarrier } from './ContextCarrier';
Expand Down Expand Up @@ -173,8 +174,13 @@ export default class SpanContext implements Context {
nSpans: this.nSpans,
});

if (!this.nSpans++)
if (!this.nSpans++) {
SpanContext.nActiveSegments += 1;
span.isCold = ContextManager.checkCold();

if (span.isCold)
span.tag(Tag.coldStart(), true);
}

if (spans.indexOf(span) === -1)
spans.push(span);
Expand Down
28 changes: 19 additions & 9 deletions src/trace/span/Span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*
*/

import config from '../../config/AgentConfig';
import Context from '../../trace/context/Context';
import { Component } from '../Component';
import { Tag } from '../../Tag';
Expand Down Expand Up @@ -51,6 +52,7 @@ export default abstract class Span {
layer = SpanLayer.UNKNOWN;
component = Component.UNKNOWN;
depth = 0;
isCold = false;
inherit?: Component;

readonly tags: Tag[] = [];
Expand Down Expand Up @@ -95,6 +97,9 @@ export default abstract class Span {
}

finish(segment: Segment): boolean {
if (this.isCold && config.coldEndpoint)
this.operation = this.operation + '<cold>';

this.endTime = new Date().getTime();
segment.archive(this);
return true;
Expand All @@ -118,19 +123,24 @@ export default abstract class Span {
return !this.tags.every((t) => t.key !== key);
}

tag(tag: Tag): this {
if (!tag.overridable) {
this.tags.push(Object.assign({}, tag));
}
tag(tag: Tag, insert?: boolean): this {
if (tag.overridable) {
const sameTags = this.tags.filter((it) => it.key === tag.key);

const sameTags = this.tags.filter((it) => it.key === tag.key);
if (sameTags.length) {
sameTags.forEach((it) => (it.val = tag.val));

if (sameTags.length) {
sameTags.forEach((it) => (it.val = tag.val));
} else {
this.tags.push(Object.assign({}, tag));
return this;
}
}

const tagObj = Object.assign({}, tag);

if (!insert)
this.tags.push(tagObj);
else
this.tags.unshift(tagObj)

return this;
}

Expand Down
4 changes: 4 additions & 0 deletions tests/plugins/axios/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://server:5000/axios
- key: http.method
Expand Down Expand Up @@ -101,6 +103,8 @@ segmentItems:
spanId: 0
spanLayer: Http
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://localhost:5001/axios
- key: http.method
Expand Down
4 changes: 4 additions & 0 deletions tests/plugins/express/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ segmentItems:
spanId: 0
spanLayer: Http
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://server:5000/express
- key: http.method
Expand Down Expand Up @@ -81,6 +83,8 @@ segmentItems:
spanId: 0
spanLayer: Http
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://localhost:5001/express
- key: http.method
Expand Down
4 changes: 4 additions & 0 deletions tests/plugins/http/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://server:5000/test
- key: http.method
Expand Down Expand Up @@ -87,6 +89,8 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://localhost:5001/test
- key: http.method
Expand Down
2 changes: 2 additions & 0 deletions tests/plugins/mongodb/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- { key: coldStart, value: 'true' }
- { key: http.url, value: 'http://server:5000/mongo' }
- { key: http.method, value: GET }
- { key: http.status.code, value: '200' }
Expand Down Expand Up @@ -93,6 +94,7 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- { key: coldStart, value: 'true' }
- { key: http.url, value: 'http://localhost:5001/mongo' }
- { key: http.method, value: GET }
- { key: http.status.code, value: '200' }
Expand Down
2 changes: 2 additions & 0 deletions tests/plugins/mongoose/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- { key: coldStart, value: 'true' }
- { key: http.url, value: 'http://server:5000/mongoose' }
- { key: http.method, value: GET }
- { key: http.status.code, value: '200' }
Expand Down Expand Up @@ -107,6 +108,7 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- { key: coldStart, value: 'true' }
- { key: http.url, value: 'http://localhost:5001/mongoose' }
- { key: http.method, value: GET }
- { key: http.status.code, value: '200' }
Expand Down
4 changes: 4 additions & 0 deletions tests/plugins/mysql/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://server:5000/mysql
- key: http.method
Expand Down Expand Up @@ -85,6 +87,8 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- key: coldStart
value: 'true'
- key: http.url
value: http://localhost:5001/mysql
- key: http.method
Expand Down
2 changes: 2 additions & 0 deletions tests/plugins/pg/expected.data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- { key: coldStart, value: 'true' }
- { key: http.url, value: 'http://server:5000/postgres' }
- { key: http.method, value: GET }
- { key: http.status.code, value: '200' }
Expand Down Expand Up @@ -78,6 +79,7 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- { key: coldStart, value: 'true' }
- { key: http.url, value: 'http://localhost:5001/postgres' }
- { key: http.method, value: GET }
- { key: http.status.code, value: '200' }
Expand Down