-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: AWS S3 instrumentation #2112
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
ccc7fd7
feat: AWS S3 instrumentation
trentm a48477c
drop setting span.context.db.* for S3 spans for now pending discussion
trentm 9410ae5
aws-sdk@2 S3 instrumentation should be good with this commit
trentm 2b48d1a
first partial impl of @awk-sdk/client-s3 instrumentation; doubtful th…
trentm cec0575
avoid 'disableInstrumentations' test of @aws-sdk/client-s3 on node <v…
trentm 0cf170a
v3 SDK: destination context, error capture, outcome
trentm 26310ba
clean up TODOs in the s3 instrumentations
trentm 0c9d3be
first crack at testing S3 aws-sdk instrumentation using localstack
trentm 642b58d
github actions need to setup localstack as well; drop node 15 testing…
trentm 5305b47
correct GH action yaml syntax
trentm bdb89df
fix the following "openssl ... No such file or directory" when exec'i…
trentm 7006d39
debugging CI test failures
trentm fe0b0a1
limit tests run for debugging failures; fix AWS auth envvars for test…
trentm d42619b
not helping standard
trentm 0adb071
log used endpoint for debugging; add .promise()-style case
trentm 1eb42da
fixes; still debugging CI
trentm 585206a
's3ForcePathStyle: true' to fix the bucketName.localstack DNS resolut…
trentm e8067e4
windows test fix
trentm b157b25
cleaning up tests
trentm e89a021
restore full node ver testing; modulo dropping node v15
trentm d1239ab
restore runing all the test files
trentm 44c860d
drop v3 SDK instrumentation, it has moved to a separate PR
trentm 31da8a1
Merge branch 'master' into trentm/instrument-s3
trentm a1892d5
method S3 is supported tech
trentm 5455623
changelog entry
trentm 79cfb27
Merge branch 'master' into trentm/instrument-s3
trentm ea9e8ed
updates from review feedback
trentm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
version: '2.1' | ||
|
||
services: | ||
localstack: | ||
extends: | ||
file: docker-compose.yml | ||
service: localstack | ||
node_tests: | ||
extends: | ||
file: docker-compose-node-test.yml | ||
service: node_tests | ||
depends_on: | ||
localstack: | ||
condition: service_healthy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -200,6 +200,9 @@ elif [[ -n "${TAV_MODULE}" ]]; then | |
memcached) | ||
DOCKER_COMPOSE_FILE=docker-compose-memcached.yml | ||
;; | ||
aws-sdk) | ||
DOCKER_COMPOSE_FILE=docker-compose-localstack.yml | ||
;; | ||
*) | ||
# Just the "node_tests" container. No additional services needed for testing. | ||
DOCKER_COMPOSE_FILE=docker-compose-node-test.yml | ||
|
@@ -210,6 +213,8 @@ else | |
DOCKER_COMPOSE_FILE=docker-compose-all.yml | ||
fi | ||
|
||
ELASTIC_APM_ASYNC_HOOKS=${ELASTIC_APM_ASYNC_HOOKS:-true} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. REVIEW NOTE: This ensures that
which is just noise in test output. |
||
set +e | ||
NVM_NODEJS_ORG_MIRROR=${NVM_NODEJS_ORG_MIRROR} \ | ||
ELASTIC_APM_ASYNC_HOOKS=${ELASTIC_APM_ASYNC_HOOKS} \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
'use strict' | ||
|
||
// Instrument AWS S3 operations via the 'aws-sdk' package. | ||
|
||
const constants = require('../../../constants') | ||
|
||
const TYPE = 'storage' | ||
const SUBTYPE = 's3' | ||
|
||
// Return the PascalCase operation name from `request.operation` by undoing to | ||
// `lowerFirst()` from | ||
// https://github.com/aws/aws-sdk-js/blob/c0c44b8a4e607aae521686898f39a3e359f727e4/lib/model/api.js#L63-L65 | ||
// | ||
// For example: 'headBucket' -> 'HeadBucket' | ||
function opNameFromOperation (operation) { | ||
return operation[0].toUpperCase() + operation.slice(1) | ||
} | ||
|
||
// Return an APM "resource" string for the bucket, Access Point ARN, or Outpost | ||
// ARN. ARNs are normalized to a shorter resource name. | ||
// | ||
// Known ARN patterns: | ||
// - arn:aws:s3:<region>:<account-id>:accesspoint/<accesspoint-name> | ||
// - arn:aws:s3-outposts:<region>:<account>:outpost/<outpost-id>/bucket/<bucket-name> | ||
// - arn:aws:s3-outposts:<region>:<account>:outpost/<outpost-id>/accesspoint/<accesspoint-name> | ||
// | ||
// In general that is: | ||
// arn:$partition:$service:$region:$accountId:$resource | ||
// | ||
// This parses using the same "split on colon" used by the JavaScript AWS SDK v3. | ||
// https://github.com/aws/aws-sdk-js-v3/blob/v3.18.0/packages/util-arn-parser/src/index.ts#L14-L37 | ||
function resourceFromBucket (bucket) { | ||
let resource = null | ||
if (bucket) { | ||
resource = bucket | ||
if (resource.startsWith('arn:')) { | ||
resource = bucket.split(':').slice(5).join(':') | ||
} | ||
} | ||
return resource | ||
} | ||
|
||
// Instrument an [email protected] operation (i.e. a AWS.Request.send or | ||
// AWS.Request.promise). | ||
// | ||
// @param {AWS.Request} request https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html | ||
function instrumentationS3 (orig, origArguments, request, AWS, agent, { version, enabled }) { | ||
const opName = opNameFromOperation(request.operation) | ||
let name = 'S3 ' + opName | ||
const resource = resourceFromBucket(request.params && request.params.Bucket) | ||
if (resource) { | ||
name += ' ' + resource | ||
} | ||
|
||
const span = agent.startSpan(name, TYPE, SUBTYPE, opName) | ||
if (span) { | ||
request.on('complete', function onComplete (response) { | ||
// `response` is an AWS.Response | ||
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html | ||
|
||
// Determining the bucket's region. | ||
// `request.httpRequest.region` isn't documented, but the aws-sdk@2 | ||
// lib/services/s3.js will set it to the bucket's determined region. | ||
// This can be asynchronously determined -- e.g. if it differs from the | ||
// configured service endpoint region -- so this won't be set until | ||
// 'complete'. | ||
const region = request.httpRequest && request.httpRequest.region | ||
|
||
// Destination context. | ||
// '.httpRequest.endpoint' might differ from '.service.endpoint' if | ||
// the bucket is in a different region. | ||
const endpoint = request.httpRequest && request.httpRequest.endpoint | ||
const destContext = { | ||
trentm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
service: { | ||
name: SUBTYPE, | ||
type: TYPE | ||
} | ||
} | ||
if (endpoint) { | ||
destContext.address = endpoint.hostname | ||
destContext.port = endpoint.port | ||
} | ||
if (resource) { | ||
destContext.service.resource = resource | ||
} | ||
if (region) { | ||
destContext.cloud = { region } | ||
} | ||
span.setDestinationContext(destContext) | ||
|
||
if (response) { | ||
trentm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Follow the spec for HTTP client span outcome. | ||
// https://github.com/elastic/apm/blob/master/specs/agents/tracing-instrumentation-http.md#outcome | ||
// | ||
// For example, a S3 GetObject conditional request (e.g. using the | ||
// IfNoneMatch param) will respond with response.error=NotModifed and | ||
// statusCode=304. This is a *successful* outcome. | ||
const statusCode = response.httpResponse && response.httpResponse.statusCode | ||
if (statusCode) { | ||
span._setOutcomeFromHttpStatusCode(statusCode) | ||
} else { | ||
// `statusCode` will be undefined for errors before sending a request, e.g.: | ||
// InvalidConfiguration: Custom endpoint is not compatible with access point ARN | ||
span._setOutcomeFromErrorCapture(constants.OUTCOME_FAILURE) | ||
} | ||
|
||
if (response.error && (!statusCode || statusCode >= 400)) { | ||
agent.captureError(response.error, { skipOutcome: true }) | ||
} | ||
} | ||
|
||
// Workaround a bug in the agent's handling of `span.sync`. | ||
// | ||
// The bug: Currently this span.sync is not set `false` because there is | ||
// an HTTP span created (for this S3 request) in the same async op. That | ||
// HTTP span becomes the "active span" for this async op, and *it* gets | ||
// marked as sync=false in `before()` in async-hooks.js. | ||
span.sync = false | ||
|
||
span.end() | ||
}) | ||
} | ||
|
||
return orig.apply(request, origArguments) | ||
} | ||
|
||
module.exports = { | ||
instrumentationS3 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
REVIEW NOTE: This was necessary to avoid this error message:
when executing a subprocess to run
node fixtures/use-s3.js
as part ofs3.test.js
below... because that subprocess is run in a separate directory (in "test/instrumentation/modules/aws-sdk") rather than at the top-level. Using an absolute path fixes this -- which is the same thing that is done for this in test/test.js: