-
Notifications
You must be signed in to change notification settings - Fork 96
/
Copy pathplugin-restify.ts
118 lines (100 loc) · 3.47 KB
/
plugin-restify.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 2015 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {ServerResponse} from 'http';
import * as shimmer from 'shimmer';
import {PluginTypes} from '..';
import {restify_5} from './types';
type Restify5 = typeof restify_5;
type Request = restify_5.Request & {route?: {path: string | RegExp}};
type Response = restify_5.Response;
type Next = restify_5.Next;
type CreateServerFn = (options?: restify_5.ServerOptions) => restify_5.Server;
const SUPPORTED_VERSIONS = '<=11.x';
function unpatchRestify(restify: Restify5) {
shimmer.unwrap(restify, 'createServer');
}
function patchRestify(restify: Restify5, api: PluginTypes.Tracer) {
shimmer.wrap(restify, 'createServer', createServerWrap);
function createServerWrap(createServer: CreateServerFn): CreateServerFn {
return function createServerTrace(this: {}) {
// eslint-disable-next-line prefer-rest-params
const server = createServer.apply(this, arguments) as restify_5.Server;
server.use(middleware);
return server;
};
}
function middleware(req: Request, res: Response, next: Next): void {
const options = {
// we use the path part of the url as the span name and add the full url
// as a label later.
name: req.path(),
url: req.url,
method: req.method,
traceContext: api.propagation.extract(key => req.header(key)),
skipFrames: 1,
};
api.runInRootSpan(options, rootSpan => {
// Set response trace context.
const responseTraceContext = api.getResponseTraceContext(
options.traceContext,
api.isRealSpan(rootSpan)
);
if (responseTraceContext) {
api.propagation.inject(
(k, v) => res.setHeader(k, v),
responseTraceContext
);
}
if (!api.isRealSpan(rootSpan)) {
return next();
}
api.wrapEmitter(req);
api.wrapEmitter(res);
const fullUrl = `${req.header(
'X-Forwarded-Proto',
'http'
)}://${req.header('host')}${req.url}`;
rootSpan.addLabel(api.labels.HTTP_METHOD_LABEL_KEY, req.method);
rootSpan.addLabel(api.labels.HTTP_URL_LABEL_KEY, fullUrl);
rootSpan.addLabel(
api.labels.HTTP_SOURCE_IP,
req.connection.remoteAddress
);
const originalEnd = res.end;
res.end = function (this: ServerResponse) {
res.end = originalEnd;
// eslint-disable-next-line prefer-rest-params
const returned = res.end.apply(this, arguments);
if (req.route && req.route.path) {
rootSpan.addLabel('restify/request.route.path', req.route.path);
}
rootSpan.addLabel(
api.labels.HTTP_RESPONSE_CODE_LABEL_KEY,
res.statusCode
);
rootSpan.endSpan();
return returned;
};
next();
});
}
}
const plugin: PluginTypes.Plugin = [
{
versions: SUPPORTED_VERSIONS,
patch: patchRestify,
unpatch: unpatchRestify,
} as PluginTypes.Monkeypatch<Restify5>,
];
export = plugin;