Skip to content

Commit deea150

Browse files
committed
chore(api): implement span-v2
1 parent 14ec014 commit deea150

File tree

9 files changed

+408
-201
lines changed

9 files changed

+408
-201
lines changed

e2e/getServiceKey.spec.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@
22

33
var test = require('tape')
44
var serviceMocks = require('./utils/serviceMocks')
5+
var pkg = require('../package.json')
56

67
var TRACE_MODULE = '..'
78
var TRACE_COLLECTOR_API_URL = 'https://trace-collector-api.risingstack.com'
89
var TRACE_API_KEY_TEST = process.env.TRACE_API_KEY || 'dummy-key'
10+
var TRACE_SERVICE_NAME = process.env.TRACE_SERVICE_NAME
911

1012
test('should get service key', function (t) {
1113
serviceMocks.mockServiceKeyRequest(
1214
TRACE_COLLECTOR_API_URL,
1315
TRACE_API_KEY_TEST,
1416
function (uri, requestBody) {
15-
t.pass('gets service key')
17+
t.pass('collector gets service key')
18+
// some smoke tests
19+
t.equal(requestBody.name, TRACE_SERVICE_NAME)
20+
t.equal(requestBody.version, '2')
21+
t.equal(requestBody.collector.version, pkg.version)
1622
t.end()
1723
process.exit()
1824
})

e2e/reportHttpRequest.spec.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,24 @@ var TRACE_MODULE = '..'
99
var TRACE_COLLECTOR_API_URL = 'https://trace-collector-api.risingstack.com'
1010
var TRACE_API_KEY_TEST = process.env.TRACE_API_KEY || 'dummy-key'
1111
var WEB_SERVER_PORT = process.env.WEBSERVER_PORT || 44332
12+
var DUMMY_SERVICE_KEY = 42
1213

1314
test('should report http requests', function (t) {
1415
serviceMocks.mockServiceKeyRequest(
1516
TRACE_COLLECTOR_API_URL,
1617
TRACE_API_KEY_TEST,
1718
function (uri, requestBody) {
18-
return [200, { key: 42 }]
19+
return [200, { key: DUMMY_SERVICE_KEY }]
1920
})
2021
serviceMocks.mockApmMetricsRequest(
2122
TRACE_COLLECTOR_API_URL,
2223
TRACE_API_KEY_TEST,
23-
42,
24+
DUMMY_SERVICE_KEY,
2425
Number.MAX_SAFE_INTEGER) // set the times parameter high so the http mock catches all
2526
serviceMocks.mockRpmMetricsRequest(
2627
TRACE_COLLECTOR_API_URL,
2728
TRACE_API_KEY_TEST,
28-
42,
29+
DUMMY_SERVICE_KEY,
2930
Number.MAX_SAFE_INTEGER) // set the times parameter high so the http mock catches all
3031
serviceMocks.mockEdgeMetricsRequest(
3132
TRACE_COLLECTOR_API_URL,
@@ -36,7 +37,11 @@ test('should report http requests', function (t) {
3637
TRACE_COLLECTOR_API_URL,
3738
TRACE_API_KEY_TEST,
3839
function (uri, requestBody) {
39-
t.pass('collector sent the trace')
40+
t.pass('collector sends trace')
41+
// some smoke tests
42+
t.equal(requestBody.version, '2')
43+
t.equal(requestBody.service.key, DUMMY_SERVICE_KEY)
44+
t.equal(requestBody.spans.length, 1)
4045
t.end()
4146
process.exit()
4247
})
@@ -49,12 +54,12 @@ test('should report http requests', function (t) {
4954
res.send('test')
5055
})
5156
app.listen(WEB_SERVER_PORT, function (err) {
52-
t.error(err, 'server started at ' + WEB_SERVER_PORT)
57+
t.error(err, 'server startsat ' + WEB_SERVER_PORT)
5358
// http client request
5459
request
5560
.get('127.0.0.1:' + WEB_SERVER_PORT + '/test')
5661
.end(function (err) {
57-
t.error(err, 'client sent request')
62+
t.error(err, 'client sends request')
5863
})
5964
})
6065
})

e2e/utils/serviceMocks.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function mockServiceKeyRequest (url, apiKey, callback) {
1616
'Authorization': 'Bearer ' + apiKey
1717
}
1818
})
19-
.post('/service')
19+
.post('/v2/service')
2020
.reply(callback)
2121
}
2222

@@ -59,7 +59,7 @@ function mockHttpTransactionRequest (url, apiKey, callback) {
5959
'Authorization': 'Bearer ' + apiKey
6060
}
6161
})
62-
.post('/service/sample')
62+
.post('/v2/service/sample')
6363
.reply(callback || 200)
6464
}
6565

lib/agent/api/index.js

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,34 @@ function CollectorApi (options) {
1717
this.COLLECTOR_API_RPM_METRICS = url.resolve(options.collectorApiUrl, options.collectorApiRpmMetricsEndpoint)
1818
this.COLLECTOR_API_EDGE_METRICS = url.resolve(options.collectorApiUrl, options.collectorApiEdgeMetricsEndpoint)
1919

20+
this.collectorLanguage = options.collectorLanguage
2021
this.apiKey = options.apiKey
21-
this.processId = options.processId
22-
this.hostname = options.hostname
22+
this.system = options.system
2323
this.serviceName = options.serviceName
2424
this.baseRetryInterval = 1000 * 60 * 30 // 30 minutes
2525
this.serviceKey = null
2626
}
2727

2828
// USE THIS WITH CAUTION, IT WILL BE BLOCKING
29-
CollectorApi.prototype.sendSync = function (data) {
29+
CollectorApi.prototype._sendSync = function (destinationUrl, data) {
3030
debug('sending data to trace servers sync: ', JSON.stringify(data))
31-
requestSync('POST', this.COLLECTOR_API_SAMPLE, {
31+
requestSync('POST', destinationUrl, {
3232
json: data,
3333
headers: {
3434
'Authorization': 'Bearer ' + this.apiKey,
3535
'Content-Type': 'application/json',
36-
'X-Reporter-Version': libPackage.version
36+
'X-Reporter-Version': libPackage.version,
37+
'X-Reporter-Language': this.collectorLanguage
3738
},
3839
timeout: 1000
3940
})
4041
}
4142

42-
CollectorApi.prototype._sendWithPid = function (destinationUrl, data) {
43-
this._send(destinationUrl, assign({
44-
hostname: this.hostname,
45-
pid: this.processId
46-
}, data))
43+
CollectorApi.prototype._withInstanceInfo = function (data) {
44+
return assign({
45+
hostname: this.system.hostname,
46+
pid: this.system.processId
47+
}, data)
4748
}
4849

4950
CollectorApi.prototype._send = function (destinationUrl, data) {
@@ -59,6 +60,7 @@ CollectorApi.prototype._send = function (destinationUrl, data) {
5960
'Authorization': 'Bearer ' + this.apiKey,
6061
'Content-Type': 'application/json',
6162
'X-Reporter-Version': libPackage.version,
63+
'X-Reporter-Language': this.collectorLanguage,
6264
'Content-Length': payload.length
6365
}
6466
}, function (res) {
@@ -85,7 +87,7 @@ CollectorApi.prototype.sendRpmMetrics = function (data) {
8587
}
8688

8789
var url = util.format(this.COLLECTOR_API_RPM_METRICS, this.serviceKey)
88-
this._sendWithPid(url, data)
90+
this._send(url, this._withInstanceInfo(data))
8991
}
9092

9193
CollectorApi.prototype.sendApmMetrics = function (data) {
@@ -95,7 +97,7 @@ CollectorApi.prototype.sendApmMetrics = function (data) {
9597
}
9698

9799
var url = util.format(this.COLLECTOR_API_METRICS, this.serviceKey)
98-
this._sendWithPid(url, data)
100+
this._send(url, this._withInstanceInfo(data))
99101
}
100102

101103
CollectorApi.prototype.sendEdgeMetrics = function (data) {
@@ -105,12 +107,22 @@ CollectorApi.prototype.sendEdgeMetrics = function (data) {
105107
}
106108

107109
var url = util.format(this.COLLECTOR_API_EDGE_METRICS, this.serviceKey)
108-
this._sendWithPid(url, data)
110+
this._send(url, this._withInstanceInfo(data))
109111
}
110112

111-
CollectorApi.prototype.sendSamples = function (data) {
113+
CollectorApi.prototype.sendSamples = function (samples, sync) {
112114
var url = this.COLLECTOR_API_SAMPLE
113-
this._sendWithPid(url, data)
115+
var metadata = {
116+
version: '2',
117+
instance: this._withInstanceInfo({}),
118+
service: {
119+
key: this.serviceKey,
120+
name: this.serviceName
121+
}
122+
}
123+
124+
var data = assign({}, samples, metadata)
125+
sync ? this._sendSync(url, data) : this._send(url, data)
114126
}
115127

116128
CollectorApi.prototype._getRetryInterval = function () {
@@ -126,7 +138,24 @@ CollectorApi.prototype.getService = function (cb) {
126138
cb = cb || function () {}
127139

128140
var payload = JSON.stringify({
129-
name: _this.serviceName
141+
name: _this.serviceName,
142+
version: '2',
143+
collector: {
144+
language: _this.collectorLanguage,
145+
version: libPackage.version
146+
},
147+
runtime: {
148+
name: _this.system.processName,
149+
version: _this.system.processVersion,
150+
pid: _this.system.processId
151+
},
152+
machine: {
153+
arch: _this.system.osArch,
154+
platform: _this.system.osPlatform,
155+
release: _this.system.osRelease,
156+
hostname: _this.system.hostname,
157+
cpus: _this.system.cpus
158+
}
130159
})
131160
var req = https.request({
132161
hostname: opts.hostname,
@@ -137,6 +166,7 @@ CollectorApi.prototype.getService = function (cb) {
137166
'Authorization': 'Bearer ' + this.apiKey,
138167
'Content-Type': 'application/json',
139168
'X-Reporter-Version': libPackage.version,
169+
'X-Reporter-Language': this.collectorLanguage,
140170
'Content-Length': payload.length
141171
}
142172
}, function (res) {

lib/agent/api/index.spec.js

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,45 @@ var CollectorApi = require('./')
66
var expect = require('chai').expect
77
var nock = require('nock')
88
var libPackage = require('../../../package')
9+
var assign = require('lodash.assign')
910

1011
describe('The Trace CollectorApi module', function () {
1112
var defaultConfig = {
1213
serviceName: 'testName',
1314
apiKey: 'testApiKey',
15+
collectorLanguage: 'nodejs',
1416
collectorApiUrl: 'https://collector.api.mock',
1517
collectorApiSampleEndpoint: '/service/sample',
1618
collectorApiServiceEndpoint: '/service',
1719
collectorApiApmMetricsEndpoint: '/service/%s/apm-metrics',
1820
collectorApiRpmMetricsEndpoint: '/service/%s/rpm-metrics',
19-
hostname: 'test.org',
20-
processId: '7777',
21-
collectorApiEdgeMetricsEndpoint: '/service/%s/edge-metrics'
21+
collectorApiEdgeMetricsEndpoint: '/service/%s/edge-metrics',
22+
system: {
23+
hostname: 'test.org',
24+
processVersion: '4.3.1',
25+
processName: 'node',
26+
processId: 7777,
27+
osArch: 'x86',
28+
osPlatform: 'darwin',
29+
osRelease: '11',
30+
cpus: [
31+
{
32+
model: 'Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz',
33+
speed: 2700
34+
},
35+
{
36+
model: 'Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz',
37+
speed: 2700
38+
},
39+
{
40+
model: 'Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz',
41+
speed: 2700
42+
},
43+
{ model: 'Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz',
44+
speed: 2700
45+
}
46+
]
47+
}
2248
}
2349

2450
it('can be instantiated w/ serviceName and apiKey', function () {
@@ -48,23 +74,32 @@ describe('The Trace CollectorApi module', function () {
4874
expect(sendStub).to.have.been.calledWith(sendUrl, data)
4975
})
5076

51-
it('sends samples to the collector server', function (done) {
77+
it('enhances samples with required properties', function (done) {
5278
var collectorApi = CollectorApi.create(defaultConfig)
5379
var data = {
54-
trace: 'very data',
55-
hostname: 'test.org',
56-
pid: 7777
80+
test: 'clearly a mock'
5781
}
5882

5983
nock(defaultConfig.collectorApiUrl, {
6084
reqheaders: {
6185
'Authorization': 'Bearer testApiKey',
6286
'Content-Type': 'application/json',
63-
'X-Reporter-Version': libPackage.version
87+
'X-Reporter-Version': libPackage.version,
88+
'X-Reporter-Language': defaultConfig.collectorLanguage
6489
}
6590
})
6691
.post(defaultConfig.collectorApiSampleEndpoint, function (body) {
67-
expect(body).to.eql(data)
92+
expect(body).to.eql(assign({
93+
version: '2',
94+
instance: {
95+
hostname: defaultConfig.system.hostname,
96+
pid: defaultConfig.system.processId
97+
},
98+
service: {
99+
name: defaultConfig.serviceName,
100+
key: null
101+
}
102+
}, data))
68103
return JSON.stringify(data)
69104
})
70105
.reply(201, function () {
@@ -77,14 +112,32 @@ describe('The Trace CollectorApi module', function () {
77112
it('can get the service key of serviceName from HttpTransaction server', function (done) {
78113
var collectorApi = CollectorApi.create(defaultConfig)
79114
var data = {
80-
name: defaultConfig.serviceName
115+
name: 'testName',
116+
version: '2',
117+
collector: {
118+
language: 'nodejs',
119+
version: libPackage.version
120+
},
121+
runtime: {
122+
name: defaultConfig.system.processName,
123+
version: defaultConfig.system.processVersion,
124+
pid: defaultConfig.system.processId
125+
},
126+
machine: {
127+
arch: defaultConfig.system.osArch,
128+
platform: defaultConfig.system.osPlatform,
129+
release: defaultConfig.system.osRelease,
130+
hostname: defaultConfig.system.hostname,
131+
cpus: defaultConfig.system.cpus
132+
}
81133
}
82134

83135
nock(defaultConfig.collectorApiUrl, {
84136
reqheaders: {
85137
'Authorization': 'Bearer testApiKey',
86138
'Content-Type': 'application/json',
87-
'X-Reporter-Version': libPackage.version
139+
'X-Reporter-Version': libPackage.version,
140+
'X-Reporter-Language': defaultConfig.collectorLanguage
88141
}
89142
})
90143
.post(defaultConfig.collectorApiServiceEndpoint, JSON.stringify(data))
@@ -103,14 +156,32 @@ describe('The Trace CollectorApi module', function () {
103156
var _getRetryIntervalSpy = this.sandbox.spy(collectorApi, '_getRetryInterval')
104157

105158
var data = {
106-
name: defaultConfig.serviceName
159+
name: 'testName',
160+
version: '2',
161+
collector: {
162+
language: 'nodejs',
163+
version: libPackage.version
164+
},
165+
runtime: {
166+
name: defaultConfig.system.processName,
167+
version: defaultConfig.system.processVersion,
168+
pid: defaultConfig.system.processId
169+
},
170+
machine: {
171+
arch: defaultConfig.system.osArch,
172+
platform: defaultConfig.system.osPlatform,
173+
release: defaultConfig.system.osRelease,
174+
hostname: defaultConfig.system.hostname,
175+
cpus: defaultConfig.system.cpus
176+
}
107177
}
108178

109179
nock(defaultConfig.collectorApiUrl, {
110180
reqheaders: {
111181
'Authorization': 'Bearer testApiKey',
112182
'Content-Type': 'application/json',
113-
'X-Reporter-Version': libPackage.version
183+
'X-Reporter-Version': libPackage.version,
184+
'X-Reporter-Language': defaultConfig.collectorLanguage
114185
}
115186
})
116187
.post(defaultConfig.collectorApiServiceEndpoint, JSON.stringify(data))

0 commit comments

Comments
 (0)