Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

elastic-apm-http-client

Package Overview
Dependencies
Maintainers
3
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

elastic-apm-http-client - npm Package Compare versions

Comparing version 10.2.0 to 10.3.0

15

CHANGELOG.md
# elastic-apm-http-client changelog
## v10.3.0
- Add the `expectExtraMetadata: true` configuration option and
`Client#setExtraMetadata(metadata)` method to provide a mechanism for the
Node.js APM Agent to pass in metadata asynchronously and be sure that the
client will not begin an intake request until that metadata is provided.
This is to support passing in [AWS Lambda metadata that cannot be gathered
until the first Lambda function
invocation](https://github.com/elastic/apm-agent-nodejs/issues/2404).
(Note: The `expectExtraMetadata` option cannot be used in combination with
`cloudMetadataFetcher`.)
- Use `Z_BEST_SPEED` for gzip compression per
https://github.com/elastic/apm/blob/master/specs/agents/transport.md#compression
## v10.2.0

@@ -4,0 +19,0 @@

146

index.js

@@ -95,6 +95,5 @@ 'use strict'

this._intakeRequestGracefulExitFn = null // set in makeIntakeRequest
// _encodedMetadata is pre-encoded JSON of metadata from `_conf.metadata` and
// `_cloudMetadata` (asynchronously fetched via `_conf.cloudMetadataFetcher`)
this._encodedMetadata = null
this._cloudMetadata = null
this._extraMetadata = null
this._metadataFilters = new Filters()

@@ -119,20 +118,31 @@

// start stream in corked mode, uncork when cloud
// metadata is fetched and assigned. Also, the
// _maybeUncork will not uncork until _encodedMetadata
// is set
this.cork()
this._fetchAndEncodeMetadata(() => {
// _fetchAndEncodeMetadata will have set/memoized the encoded
// metadata to the _encodedMetadata property.
if (this._conf.cloudMetadataFetcher && this._conf.expectExtraMetadata) {
throw new Error('it is an error to create a Client with both cloudMetadataFetcher and expectExtraMetadata')
} 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
// is set.
this._log.trace('corking (cloudMetadataFetcher)')
this.cork()
this._fetchAndEncodeMetadata(() => {
// _fetchAndEncodeMetadata will have set/memoized the encoded
// metadata to the _encodedMetadata property.
// This reverses the cork() call in the constructor above. "Maybe" uncork,
// in case the client has been destroyed before this callback is called.
this._maybeUncork()
// This reverses the cork() call in the constructor above. "Maybe" uncork,
// in case the client has been destroyed before this callback is called.
this._maybeUncork()
this._log.trace('uncorked (cloudMetadataFetcher)')
// the `cloud-metadata` event allows listeners to know when the
// agent has finished fetching and encoding its metadata for the
// first time
this.emit('cloud-metadata', this._encodedMetadata)
})
// the `cloud-metadata` event allows listeners to know when the
// agent has finished fetching and encoding its metadata for the
// first time
this.emit('cloud-metadata', this._encodedMetadata)
})
} else if (this._conf.expectExtraMetadata) {
// Uncorking will happen in the expected `.setExtraMetadata()` call.
this._log.trace('corking (expectExtraMetadata)')
this.cork()
} else {
this._resetEncodedMetadata()
}

@@ -144,3 +154,5 @@ this._chopper = new StreamChopper({

transform () {
return zlib.createGzip()
return zlib.createGzip({
level: zlib.constants.Z_BEST_SPEED
})
}

@@ -269,2 +281,24 @@ })

/**
* Set extra additional metadata to be sent to APM Server in intake requests.
*
* If the Client was configured with `expectExtraMetadata: true` then will
* uncork the client to allow intake requests to begin.
*
* If this is called multiple times, it is additive.
*/
Client.prototype.setExtraMetadata = function (extraMetadata) {
if (!this._extraMetadata) {
this._extraMetadata = extraMetadata
} else {
metadataMergeDeep(this._extraMetadata, extraMetadata)
}
this._resetEncodedMetadata()
if (this._conf.expectExtraMetadata) {
this._maybeUncork()
this._log.trace('uncorked (expectExtraMetadata)')
}
}
/**
* Add a filter function used to filter the "metadata" object sent to APM

@@ -283,3 +317,4 @@ * server. See the APM Agent `addMetadataFilter` documentation for details.

/**
* (Re)set `_encodedMetadata` from this._conf.metadata and this._cloudMetadata.
* (Re)set `_encodedMetadata` from this._conf.metadata, this._cloudMetadata,
* this._extraMetadata and possible this._metadataFilters.
*/

@@ -290,6 +325,9 @@ Client.prototype._resetEncodedMetadata = function () {

// cycle for cloning should suffice.
let metadata = JSON.parse(JSON.stringify(this._conf.metadata))
let metadata = deepClone(this._conf.metadata)
if (this._cloudMetadata) {
metadata.cloud = JSON.parse(JSON.stringify(this._cloudMetadata))
metadata.cloud = deepClone(this._cloudMetadata)
}
if (this._extraMetadata) {
metadataMergeDeep(metadata, deepClone(this._extraMetadata))
}

@@ -299,3 +337,2 @@ // Possible filters from APM agent's `apm.addMetadataFilter()`.

metadata = this._metadataFilters.process(metadata)
this._log.trace({ filteredMetadata: metadata }, 'filtered metadata')
}

@@ -305,2 +342,3 @@

this._encodedMetadata = this._encode({ metadata }, Client.encoding.METADATA)
this._log.trace({ _encodedMetadata: this._encodedMetadata }, '_resetEncodedMetadata')
}

@@ -993,21 +1031,16 @@

Client.prototype._fetchAndEncodeMetadata = function (cb) {
if (!this._conf.cloudMetadataFetcher) {
// no metadata fetcher from the agent -- encode our data and move on
assert(this._conf.cloudMetadataFetcher, '_fetchAndEncodeMetadata should not be called without a configured cloudMetadataFetcher')
this._conf.cloudMetadataFetcher.getCloudMetadata((err, cloudMetadata) => {
if (err) {
// We ignore this error (other than logging it). A common case, when
// not running on one of the big 3 clouds, is "all callbacks failed",
// which is *fine*. Because it is a common "error" we don't log the
// stack trace.
this._log.trace('getCloudMetadata err: %s', err)
} else if (cloudMetadata) {
this._cloudMetadata = cloudMetadata
}
this._resetEncodedMetadata()
process.nextTick(cb)
} else {
this._conf.cloudMetadataFetcher.getCloudMetadata((err, cloudMetadata) => {
if (err) {
// We ignore this error (other than logging it). A common case, when
// not running on one of the big 3 clouds, is "all callbacks failed",
// which is *fine*. Because it is a common "error" we don't log the
// stack trace.
this._log.trace('getCloudMetadata err: %s', err)
} else if (cloudMetadata) {
this._cloudMetadata = cloudMetadata
}
this._resetEncodedMetadata()
cb()
})
}
cb()
})
}

@@ -1277,1 +1310,32 @@

}
/**
* Performs a deep merge of `source` into `target`. Mutates `target` only but
* not its objects. Objects are merged, Arrays are not.
*
* @author inspired by [eden](https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6#gistcomment-2930530)
*/
function metadataMergeDeep (target, source) {
const isObject = (obj) => obj && typeof obj === 'object' && !Array.isArray(obj)
if (!isObject(target) || !isObject(source)) {
return source
}
Object.keys(source).forEach(key => {
const targetValue = target[key]
const sourceValue = source[key]
if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = metadataMergeDeep(Object.assign({}, targetValue), sourceValue)
} else {
target[key] = sourceValue
}
})
return target
}
function deepClone (obj) {
return JSON.parse(JSON.stringify(obj))
}
{
"name": "elastic-apm-http-client",
"version": "10.2.0",
"version": "10.3.0",
"description": "A low-level HTTP client for communicating with the Elastic APM intake API",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -108,2 +108,18 @@ # elastic-apm-http-client

Cloud & Extra Metadata Configuration:
- `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.
- `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.
APM Agent Configuration via Kibana:

@@ -302,3 +318,15 @@

### `client.setExtraMetadata([metadata])`
Add extra metadata to be included in the "metadata" object sent to APM Server in
intake requests. The given `metadata` object is merged into the metadata
determined from the client configuration.
The reason this exists is to allow some metadata to be provided asynchronously,
especially in combination with the `expectExtraMetadata` configuration option
to ensure that event data is not sent to APM Server until this extra metadata
is provided. For example, in an AWS Lambda function some metadata is not
available until the first function invocation -- which is some async time after
Client creation.
### `client.sendSpan(span[, callback])`

@@ -305,0 +333,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc