Skip to content
This repository has been archived by the owner on Aug 4, 2023. It is now read-only.

Commit

Permalink
feat: add 'extraMetadata' config option (#192)
Browse files Browse the repository at this point in the history
This is a way to provide additional metadata that is merged into the
metadata object created from the other individual config options. This
is similar to `expectExtraMetadata: true` && `setExtraMetadata(...)`,
but is a way to provide the metadata *synchronously*.

Refs: elastic/apm-agent-nodejs#3071
  • Loading branch information
trentm authored Dec 16, 2022
1 parent d3842f6 commit 36fd3ba
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 9 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# elastic-apm-http-client changelog

## v11.1.0

- Add an `extraMetadata` config option, which is an object to merge into the
built metadata object. This is an alternative to the existing
`cloudMetadataFetcher` and `expectExtraMetadata` options which provide ways
to asynchronously provide metadata. Only one (or zero) of these three options
may be used.

## v11.0.4

- Update the default `serverUrl` to "http://127.0.0.1:8200". We no longer use
Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ Arguments:
- `options` - An object containing config options (see below). All options
are optional, except those marked "(required)".

Data sent to the APM Server as part of the [metadata object](https://www.elastic.co/guide/en/apm/server/current/metadata-api.html):
Data sent to the APM Server as part of the [metadata object](https://www.elastic.co/guide/en/apm/server/current/metadata-api.html).
See also the "Cloud & Extra Metadata" section below.

- `agentName` - (required) The APM agent name
- `agentVersion` - (required) The APM agent version
Expand Down Expand Up @@ -114,21 +115,22 @@ HTTP client configuration:
default of 15s](https://pkg.go.dev/net#Dialer) (when talking to the Elastic
APM Lambda extension). (default: `4000`)

Cloud & Extra Metadata Configuration:
Cloud & Extra Metadata Configuration. Zero or one of the following three
options may be used.

- `cloudMetadataFetcher` - An object with a `getCloudMetadata(cb)` method
for fetching metadata related to the current cloud environment. The callback
is of the form `function (err, cloudMetadata)` and the returned `cloudMetadata`
will be set on `metadata.cloud` for intake requests to APM Server. If
provided, this client will not begin any intake requests until the callback
is called. The `cloudMetadataFetcher` option must not be used with the
`expectExtraMetadata` option.
is called.
- `expectExtraMetadata` - A boolean option to indicate that the client should
not allow any intake requests to begin until `cloud.setExtraMetadata(...)`
has been called. It is the responsibility of the caller to call
`cloud.setExtraMetadata()`. If not, then the Client will never perform an
intake request. The `expectExtraMetadata` option must not be used with the
`cloudMetadataFetcher` option.
intake request.
- `extraMetadata` - An object with extra metadata to merge into the metadata
object created from the individual fields above.

APM Agent Configuration via Kibana:

Expand Down
11 changes: 9 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,13 @@ function Client (opts) {
this.config(opts)
this._log = this._conf.logger || new NoopLogger()

if (this._conf.cloudMetadataFetcher && this._conf.expectExtraMetadata) {
throw new Error('it is an error to create a Client with both cloudMetadataFetcher and expectExtraMetadata')
const numExtraMdOpts = [
this._conf.cloudMetadataFetcher,
this._conf.expectExtraMetadata,
this._conf.extraMetadata
].reduce((accum, curr) => curr ? accum + 1 : accum, 0)
if (numExtraMdOpts > 1) {
throw new Error('it is an error to configure a Client with more than one of "cloudMetadataFetcher", "expectExtraMetadata", or "extraMetadata"')
} else if (this._conf.cloudMetadataFetcher) {
// Start stream in corked mode, uncork when cloud metadata is fetched and
// assigned. Also, the _maybeUncork will not uncork until _encodedMetadata
Expand All @@ -155,6 +160,8 @@ function Client (opts) {
// Uncorking will happen in the expected `.setExtraMetadata()` call.
this._log.trace('corking (expectExtraMetadata)')
this.cork()
} else if (this._conf.extraMetadata) {
this.setExtraMetadata(this._conf.extraMetadata)
} else {
this._resetEncodedMetadata()
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "elastic-apm-http-client",
"version": "11.0.4",
"version": "11.1.0",
"description": "A low-level HTTP client for communicating with the Elastic APM intake API",
"main": "index.js",
"directories": {
Expand Down
47 changes: 47 additions & 0 deletions test/extraMetadata.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict'

// Test usage of `extraMetadata: ...`.

const test = require('tape')
const utils = require('./lib/utils')

const APMServer = utils.APMServer
const processIntakeReq = utils.processIntakeReq

test('extraMetadata', function (t) {
const apmEvents = []
const extraMetadata = {
foo: 'bar',
service: {
language: {
name: 'spam'
}
}
}

const server = APMServer(function (req, res) {
const objStream = processIntakeReq(req)
objStream.on('data', function (obj) {
apmEvents.push(obj)
})
objStream.on('end', function () {
res.statusCode = 202
res.end()
})
}).client({ extraMetadata, apmServerVersion: '8.0.0' }, function (client) {
client.sendTransaction({ req: 1 })

client.flush(() => {
t.equal(apmEvents.length, 2, 'APM Server got 2 events')
t.ok(apmEvents[0].metadata, 'event 0 is metadata')
t.equal(apmEvents[0].metadata.foo, 'bar', 'extraMetadata added "foo" field')
t.equal(apmEvents[0].metadata.service.language.name, 'spam',
'extraMetadata overrode nested service.language.name field properly')
t.ok(apmEvents[1].transaction, 'event 1 is a transaction')

client.end()
server.close()
t.end()
})
})
})

0 comments on commit 36fd3ba

Please sign in to comment.