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
2
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 8.0.0 to 8.1.0

.ci/.editorconfig

186

index.js

@@ -7,2 +7,3 @@ 'use strict'

const zlib = require('zlib')
const querystring = require('querystring')
const Writable = require('readable-stream').Writable

@@ -77,2 +78,3 @@ const getContainerInfo = require('container-info')

this._transport = null
this._configTimer = null

@@ -107,2 +109,4 @@ switch (this._conf.serverUrl.protocol.slice(0, -1)) { // 'http:' => 'http'

clients.push(this)
if (this._conf.centralConfig) this._pollConfig()
}

@@ -132,2 +136,3 @@

this._conf.keepAlive = this._conf.keepAlive !== false
this._conf.centralConfig = this._conf.centralConfig || false

@@ -150,5 +155,67 @@ // process

// http request options
this._conf.request = getRequestOptions(this._conf, this._agent)
this._conf.requestIntake = getIntakeRequestOptions(this._conf, this._agent)
this._conf.requestConfig = getConfigRequestOptions(this._conf, this._agent)
}
Client.prototype._pollConfig = function () {
const opts = this._conf.requestConfig
if (this._conf.lastConfigEtag) {
opts.headers['If-None-Match'] = this._conf.lastConfigEtag
}
const req = this._transport.get(opts, res => {
res.on('error', err => {
// Not sure this event can ever be emitted, but just in case
res.destroy(err)
})
this._scheduleNextConfigPoll(getMaxAge(res))
if (
res.statusCode === 304 || // No new config since last time
res.statusCode === 403 || // Central config not enabled in APM Server
res.statusCode === 404 // No config for the given service.name / service.environment
) {
res.resume()
return
}
streamToBuffer(res, (err, buf) => {
if (err) return res.destroy(err)
if (res.statusCode === 200) {
// 200: New config available
const etag = res.headers['etag']
if (etag) this._conf.lastConfigEtag = etag
try {
this.emit('config', JSON.parse(buf))
} catch (e) {
res.destroy(e)
}
} else {
res.destroy(processConfigErrorResponse(res, buf))
}
})
})
req.on('error', err => {
this._scheduleNextConfigPoll()
this.emit('request-error', err)
})
}
Client.prototype._scheduleNextConfigPoll = function (seconds) {
if (this._configTimer !== null) return
seconds = seconds || 300
this._configTimer = setTimeout(() => {
this._configTimer = null
this._pollConfig()
}, seconds * 1000)
this._configTimer.unref()
}
// re-ref the open socket handles

@@ -308,2 +375,6 @@ Client.prototype._ref = function () {

Client.prototype._final = function (cb) {
if (this._configTimer) {
clearTimeout(this._configTimer)
this._configTimer = null
}
clients[this._index] = null // remove global reference to ease garbage collection

@@ -316,2 +387,6 @@ this._ref()

Client.prototype._destroy = function (err, cb) {
if (this._configTimer) {
clearTimeout(this._configTimer)
this._configTimer = null
}
clients[this._index] = null // remove global reference to ease garbage collection

@@ -334,3 +409,3 @@ this._chopper.destroy()

const req = client._transport.request(client._conf.request, onResult(onerror))
const req = client._transport.request(client._conf.requestIntake, onResult(onerror))

@@ -425,30 +500,27 @@ // Abort the current request if the server responds prior to the request

if (res.statusCode < 200 || res.statusCode > 299) {
const err = new Error('Unexpected APM Server response')
onerror(processIntakeErrorResponse(res, buf))
}
})
}
err.code = res.statusCode
function getIntakeRequestOptions (opts, agent) {
const headers = getHeaders(opts)
headers['Content-Type'] = 'application/x-ndjson'
headers['Content-Encoding'] = 'gzip'
if (buf.length > 0) {
const body = buf.toString('utf8')
const contentType = res.headers['content-type']
if (contentType && contentType.indexOf('application/json') === 0) {
try {
const data = JSON.parse(body)
err.accepted = data.accepted
err.errors = data.errors
if (!err.errors) err.response = body
} catch (e) {
err.response = body
}
} else {
err.response = body
}
}
return getBasicRequestOptions('POST', '/intake/v2/events', headers, opts, agent)
}
onerror(err)
}
function getConfigRequestOptions (opts, agent) {
const path = '/config/v1/agents?' + querystring.stringify({
'service.name': opts.serviceName,
'service.environment': opts.environment
})
const headers = getHeaders(opts)
return getBasicRequestOptions('GET', path, headers, opts, agent)
}
function getRequestOptions (opts, agent) {
const defaultPath = '/intake/v2/events'
function getBasicRequestOptions (method, defaultPath, headers, opts, agent) {
return {

@@ -459,5 +531,5 @@ agent: agent,

port: opts.serverUrl.port,
method: 'POST',
method,
path: opts.serverUrl.path === '/' ? defaultPath : opts.serverUrl.path + defaultPath,
headers: getHeaders(opts)
headers
}

@@ -469,4 +541,2 @@ }

if (opts.secretToken) headers['Authorization'] = 'Bearer ' + opts.secretToken
headers['Content-Type'] = 'application/x-ndjson'
headers['Content-Encoding'] = 'gzip'
headers['Accept'] = 'application/json'

@@ -595,1 +665,61 @@ headers['User-Agent'] = opts.userAgent + ' ' + pkg.name + '/' + pkg.version

}
function getMaxAge (res) {
const header = res.headers['cache-control']
const match = header && header.match(/max-age=(\d+)/)
return parseInt(match && match[1], 10)
}
function processIntakeErrorResponse (res, buf) {
const err = new Error('Unexpected APM Server response')
err.code = res.statusCode
if (buf.length > 0) {
const body = buf.toString('utf8')
const contentType = res.headers['content-type']
if (contentType && contentType.startsWith('application/json')) {
try {
const data = JSON.parse(body)
err.accepted = data.accepted
err.errors = data.errors
if (!err.errors) err.response = body
} catch (e) {
err.response = body
}
} else {
err.response = body
}
}
return err
}
function processConfigErrorResponse (res, buf) {
const err = new Error('Unexpected APM Server response when polling config')
err.code = res.statusCode
if (buf.length > 0) {
const body = buf.toString('utf8')
const contentType = res.headers['content-type']
if (contentType && contentType.startsWith('application/json')) {
try {
const response = JSON.parse(body)
if (typeof response === 'string') {
err.response = response
} else if (typeof response === 'object' && response !== null && typeof response.error === 'string') {
err.response = response.error
} else {
err.response = body
}
} catch (e) {
err.response = body
}
} else {
err.response = body
}
}
return err
}

2

package.json
{
"name": "elastic-apm-http-client",
"version": "8.0.0",
"version": "8.1.0",
"description": "A low-level HTTP client for communicating with the Elastic APM intake API",

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

# elastic-apm-http-client
[![npm](https://img.shields.io/npm/v/elastic-apm-http-client.svg)](https://www.npmjs.com/package/elastic-apm-http-client)
[![Build status](https://travis-ci.org/elastic/apm-nodejs-http-client.svg?branch=master)](https://travis-ci.org/elastic/apm-nodejs-http-client)
[![Build status in Travis](https://travis-ci.org/elastic/apm-nodejs-http-client.svg?branch=master)](https://travis-ci.org/elastic/apm-nodejs-http-client)
[![Build Status in Jenkins](https://apm-ci.elastic.co/buildStatus/icon?job=apm-agent-nodejs%2Fapm-nodejs-http-client-mbp%2Fmaster)](https://apm-ci.elastic.co/job/apm-agent-nodejs/job/apm-nodejs-http-client-mbp/job/master/)
[![codecov](https://img.shields.io/codecov/c/github/elastic/apm-nodejs-http-client.svg)](https://codecov.io/gh/elastic/apm-nodejs-http-client)

@@ -103,2 +104,10 @@ [![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)

APM Agent Configuration via Kibana:
- `centralConfig` - Whether or not the client should poll the APM
Server regularly for new agent configuration. If set to `true`, the
`config` event will be emitted when there's an update to an agent config
option (default: `false`). _Requires APM Server v7.3 or later and that
the APM Server is configured with `kibana.enabled: true`._
Streaming configuration:

@@ -146,2 +155,12 @@

### Event: `config`
Emitted every time a change to the agent config is pulled from the APM
Server. The listener is passed the updated config options as a key/value
object.
Each key is the lowercase version of the environment variable, without
the `ELASTIC_APM_` prefix, e.g. `transaction_sample_rate` instead of
`ELASTIC_APM_TRANSACTION_SAMPLE_RATE`.
### Event: `close`

@@ -168,4 +187,5 @@

This means that the current request to the APM Server is terminated and
that the data included in that request is lost.
The request to the APM Server that caused the error is terminated and
the data included in that request is lost. This is normally only
important to consider for requests to the Intake API.

@@ -175,4 +195,4 @@ If a non-2xx response was received from the APM Server, the status code

If the APM Serer responded with a structured error message, the `error`
object will have the following properties:
For requests to the Intake API where the response is a structured error
message, the `error` object will have the following properties:

@@ -189,3 +209,3 @@ - `error.accepted` - An integer indicating how many events was accepted

If the APM returned an errro body that could not be parsed by the
If the response contained an error body that could not be parsed by the
client, the raw body will be available on `error.response`.

@@ -213,2 +233,3 @@

- `maxFreeSockets`
- `centralConfig`

@@ -215,0 +236,0 @@ ### `client.sendSpan(span[, callback])`

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