Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7e1ebf3
Adding android upload map validation
LikeTheSalad Jul 5, 2023
fb4002b
Adding same service name and version android map files
LikeTheSalad Jul 5, 2023
a995b4f
Setting android upload map endpoint body max size to 30 MB
LikeTheSalad Jul 5, 2023
f670716
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Jul 5, 2023
6ea4d39
Fixing lint issues
LikeTheSalad Jul 5, 2023
91e0b8b
Merge branch 'main' into uploading-android-map-files
LikeTheSalad Jul 5, 2023
271b757
Fixing type issues
LikeTheSalad Jul 5, 2023
e05b441
Adding | undefined to test return type
LikeTheSalad Jul 6, 2023
4366939
Update x-pack/plugins/apm/server/routes/source_maps/route.ts
LikeTheSalad Jul 6, 2023
5dceb1c
Merge branch 'uploading-android-map-files' of github.com:LikeTheSalad…
LikeTheSalad Jul 6, 2023
1eaef79
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Jul 6, 2023
a593a12
Fixing maxBytes value for sourcemaps upload endpoint
LikeTheSalad Jul 6, 2023
03bbf95
Merge branch 'uploading-android-map-files' of github.com:LikeTheSalad…
LikeTheSalad Jul 6, 2023
588fa1a
Merge branch 'main' into uploading-android-map-files
kibanamachine Jul 6, 2023
20a0e32
Merge branch 'main' into uploading-android-map-files
kibanamachine Jul 7, 2023
740007b
Setting the sourcemaps and androidmaps endpoints max limit file size …
LikeTheSalad Jul 10, 2023
13a1def
Adding documentation for the new android upload map endpoint
LikeTheSalad Jul 10, 2023
db098dd
Merge branch 'main' into uploading-android-map-files
kibanamachine Jul 10, 2023
65052a0
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
2d6bb59
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
8ba1518
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
b285717
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
356450f
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
1b48fff
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
74bf995
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
82a1c13
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
7dc2d44
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
04ad479
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
673eb18
Update docs/apm/api.asciidoc
LikeTheSalad Jul 11, 2023
04dae25
Merge branch 'main' into uploading-android-map-files
kibanamachine Jul 24, 2023
7c34a1a
Merge branch 'main' into uploading-android-map-files
kibanamachine Jul 24, 2023
c774db8
Update x-pack/plugins/apm/server/routes/source_maps/route.ts
LikeTheSalad Jul 31, 2023
292b9ec
Removing unnecessary string conversion
LikeTheSalad Jul 31, 2023
9bccc1d
Merge branch 'main' into uploading-android-map-files
kibanamachine Jul 31, 2023
0676b19
Fixing typo
LikeTheSalad Jul 31, 2023
083ed70
Merge branch 'uploading-android-map-files' of github.com:LikeTheSalad…
LikeTheSalad Jul 31, 2023
37c7143
Renaming var to match type's name
LikeTheSalad Jul 31, 2023
4d6160c
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Jul 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 214 additions & 0 deletions docs/apm/api.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Some APM app features are provided via a REST API:
* <<agent-config-api>>
* <<apm-annotation-api>>
* <<rum-sourcemap-api>>
* <<android-sourcemap-api>>
* <<agent-key-api>>

[float]
Expand Down Expand Up @@ -715,6 +716,219 @@ curl -X DELETE "http://localhost:5601/api/apm/sourcemaps/apm:foo-1.0.0-644fd5a9"
*******************************************************
////

[role="xpack"]
[[android-sourcemap-api]]
=== Android source map API

IMPORTANT: This endpoint is only compatible with the
{apm-guide-ref}/index.html[APM integration for Elastic Agent].

An Android source map (generated using Android's https://developer.android.com/build/shrink-code[R8 tool])
allows obfuscated app stacktraces to be mapped back to original source code --
allowing you to maintain the size and security of minimized code, without losing the ability to debug your application.

For best results, uploading source maps should become a part of your deployment procedure,
and not something you only do when you see unhelpful errors.
That’s because uploading source maps after errors happen won’t make old errors magically readable --
errors must occur again for source mapping to occur.

The following APIs are available:

* <<android-sourcemap-post>>
* <<android-sourcemap-get>>
* <<android-sourcemap-delete>>

[float]
[[use-sourcemap-api]]
==== How to use APM APIs

.Expand for required headers, privileges, and usage details
[%collapsible%closed]
======
include::api.asciidoc[tag=using-the-APIs]
======

////
*******************************************************
////

[[android-sourcemap-post]]
==== Create or update an Android source map

Create or update an Android source map for a specific app and version.

[[android-sourcemap-post-privs]]
===== Privileges

The user accessing this endpoint requires `All` Kibana privileges for the {beat_kib_app} feature.
For more information, see <<kibana-privileges>>.

[[apm-sourcemap-post-req]]
===== Request

`POST /api/apm/androidmaps`

[role="child_attributes"]
[[apm-sourcemap-post-req-body]]
===== Request body

`service_name`::
(required, string) The name of the Android app that the map should apply to.

`service_version`::
(required, string) The version of the Android app that the map should apply to.

`map_file`::
(required, string or file upload) The R8-generated map.

[[apm-sourcemap-post-example]]
===== Examples

The following example uploads a source map for a app named `foo` and a service version of `1.0.0`:

[source,curl]
--------------------------------------------------
curl -X POST "http://localhost:5601/api/apm/androidmaps" \
-H 'Content-Type: multipart/form-data' \
-H 'kbn-xsrf: true' \
-H 'Authorization: ApiKey ${YOUR_API_KEY}' \
-F 'service_name="foo"' \
-F 'service_version="1.0.0"' \
-F 'map_file=@"/Path/to/the/file/mapping.txt"'
--------------------------------------------------

[[apm-sourcemap-post-body]]
===== Response body

[source,js]
--------------------------------------------------
{
"type": "sourcemap",
"identifier": "foo-1.0.0-android",
"relative_url": "/api/fleet/artifacts/foo-1.0.0-android/644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456",
"body": "eJyFkL1OwzAUhd/Fc+MbYMuCEBIbHRjKgBgc96R16tiWr1OQqr47NwqJxEK3q/PzWccXxchnZ7E1A1SjuhjVZtF2yOxiEPlO17oWox3D3uPFeSRTjmJQARfCPeiAgGx8NTKsYdAc1T3rwaSJGcds8Sp3c1HnhfywUZ3QhMTFFGepZxqMC9oex3CS9tpk1XyozgOlmoVKuJX1DqEQZ0su7PGtLU+V/3JPKc3cL7TJ2FNDRPov4bFta3MDM4f7W69lpJjLO9qdK8bzVPhcJz3HUCQ4LbO/p5hCSC4cZPByrp/wFqOklbpefwAhzpqI",
"created": "2021-07-09T20:47:44.812Z",
"id": "apm:foo-1.0.0-android-644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456",
"compressionAlgorithm": "zlib",
"decodedSha256": "644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456",
"decodedSize": 441,
"encodedSha256": "024c72749c3e3dd411b103f7040ae62633558608f480bce4b108cf5b2275bd24",
"encodedSize": 237,
"encryptionAlgorithm": "none",
"packageName": "apm"
}
--------------------------------------------------

////
*******************************************************
////

[[android-sourcemap-get]]
==== Get source maps

Returns an array of Fleet artifacts, including source map uploads.

[[android-sourcemap-get-privs]]
===== Privileges

The user accessing this endpoint requires `Read` or `All` Kibana privileges for the {beat_kib_app} feature.
For more information, see <<kibana-privileges>>.

[[apm-sourcemap-get-req]]
===== Request

`GET /api/apm/sourcemaps`

[[apm-sourcemap-get-example]]
===== Example

The following example requests all uploaded source maps:

[source,curl]
--------------------------------------------------
curl -X GET "http://localhost:5601/api/apm/sourcemaps" \
-H 'Content-Type: application/json' \
-H 'kbn-xsrf: true' \
-H 'Authorization: ApiKey ${YOUR_API_KEY}'
--------------------------------------------------

[[apm-sourcemap-get-body]]
===== Response body

[source,js]
--------------------------------------------------
{
"artifacts": [
{
"type": "sourcemap",
"identifier": "foo-1.0.0-android",
"relative_url": "/api/fleet/artifacts/foo-1.0.0-android/644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456",
"body": {
"serviceName": "foo",
"serviceVersion": "1.0.0",
"bundleFilepath": "android",
"sourceMap": "# compiler: R8\n# compiler_version: 3.2.47\n# min_api: 26\n..."
},
"created": "2021-07-09T20:47:44.812Z",
"id": "apm:foo-1.0.0-android-644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456",
"compressionAlgorithm": "zlib",
"decodedSha256": "644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456",
"decodedSize": 441,
"encodedSha256": "024c72749c3e3dd411b103f7040ae62633558608f480bce4b108cf5b2275bd24",
"encodedSize": 237,
"encryptionAlgorithm": "none",
"packageName": "apm"
}
]
}
--------------------------------------------------

////
*******************************************************
////

[[android-sourcemap-delete]]
==== Delete source map

Delete a previously uploaded source map.

[[android-sourcemap-delete-privs]]
===== Privileges

The user accessing this endpoint requires `All` Kibana privileges for the {beat_kib_app} feature.
For more information, see <<kibana-privileges>>.

[[apm-sourcemap-delete-req]]
===== Request

`DELETE /api/apm/sourcemaps/:id`

[[apm-sourcemap-delete-example]]
===== Example

The following example deletes a source map with an id of `apm:foo-1.0.0-android-644fd5a9`:

[source,curl]
--------------------------------------------------
curl -X DELETE "http://localhost:5601/api/apm/sourcemaps/apm:foo-1.0.0-android-644fd5a9" \
-H 'Content-Type: application/json' \
-H 'kbn-xsrf: true' \
-H 'Authorization: ApiKey ${YOUR_API_KEY}'
--------------------------------------------------

[[apm-sourcemap-delete-body]]
===== Response body

[source,js]
--------------------------------------------------
{}
--------------------------------------------------

////
*******************************************************
*******************************************************
////

[role="xpack"]
[[agent-key-api]]
=== APM agent Key API
Expand Down
25 changes: 24 additions & 1 deletion x-pack/plugins/apm/server/routes/fleet/source_maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ import { getPackagePolicyWithSourceMap } from './get_package_policy_decorators';

const doUnzip = promisify(unzip);

interface ApmSourceMapArtifactBody {
interface ApmMapArtifactBody {
serviceName: string;
serviceVersion: string;
bundleFilepath: string;
sourceMap: string;
}

interface ApmSourceMapArtifactBody
extends Omit<ApmMapArtifactBody, 'sourceMap'> {
sourceMap: SourceMap;
}

export type ArtifactSourceMap = Omit<Artifact, 'body'> & {
body: ApmSourceMapArtifactBody;
};
Expand Down Expand Up @@ -104,6 +110,23 @@ export async function createFleetSourceMapArtifact({
});
}

export async function createFleetAndroidMapArtifact({
apmArtifactBody,
fleetPluginStart,
}: {
apmArtifactBody: ApmMapArtifactBody;
fleetPluginStart: FleetPluginStart;
}) {
const apmArtifactClient = getApmArtifactClient(fleetPluginStart);
const identifier = `${apmArtifactBody.serviceName}-${apmArtifactBody.serviceVersion}-android`;

return apmArtifactClient.createArtifact({
type: 'sourcemap',
identifier,
content: JSON.stringify(apmArtifactBody),
});
}

export async function deleteFleetSourcemapArtifact({
id,
fleetPluginStart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Artifact } from '@kbn/fleet-plugin/server';
import { getUnzippedArtifactBody } from '../fleet/source_maps';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { ApmSourceMap } from './create_apm_source_map_index_template';
import { getEncodedContent, getSourceMapId } from './sourcemap_utils';
import { getEncodedSourceMapContent, getSourceMapId } from './sourcemap_utils';

export async function bulkCreateApmSourceMaps({
artifacts,
Expand All @@ -24,7 +24,7 @@ export async function bulkCreateApmSourceMaps({
const { serviceName, serviceVersion, bundleFilepath, sourceMap } =
await getUnzippedArtifactBody(artifact.body);

const { contentEncoded, contentHash } = await getEncodedContent(
const { contentEncoded, contentHash } = await getEncodedSourceMapContent(
sourceMap
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { Logger } from '@kbn/core/server';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { ApmSourceMap } from './create_apm_source_map_index_template';
import { SourceMap } from './route';
import { getEncodedContent, getSourceMapId } from './sourcemap_utils';
import {
getEncodedSourceMapContent,
getEncodedContent,
getSourceMapId,
} from './sourcemap_utils';

export async function createApmSourceMap({
internalESClient,
Expand All @@ -31,9 +35,75 @@ export async function createApmSourceMap({
serviceName: string;
serviceVersion: string;
}) {
const { contentEncoded, contentHash } = await getEncodedContent(
const { contentEncoded, contentHash } = await getEncodedSourceMapContent(
sourceMapContent
);
return await doCreateApmMap({
internalESClient,
logger,
fleetId,
created,
bundleFilepath,
serviceName,
serviceVersion,
contentEncoded,
contentHash,
});
}

export async function createApmAndroidMap({
internalESClient,
logger,
fleetId,
created,
mapContent,
bundleFilepath,
serviceName,
serviceVersion,
}: {
internalESClient: ElasticsearchClient;
logger: Logger;
fleetId: string;
created: string;
mapContent: string;
bundleFilepath: string;
serviceName: string;
serviceVersion: string;
}) {
const { contentEncoded, contentHash } = await getEncodedContent(mapContent);
return await doCreateApmMap({
internalESClient,
logger,
fleetId,
created,
bundleFilepath,
serviceName,
serviceVersion,
contentEncoded,
contentHash,
});
}
async function doCreateApmMap({
internalESClient,
logger,
fleetId,
created,
bundleFilepath,
serviceName,
serviceVersion,
contentEncoded,
contentHash,
}: {
internalESClient: ElasticsearchClient;
logger: Logger;
fleetId: string;
created: string;
bundleFilepath: string;
serviceName: string;
serviceVersion: string;
contentEncoded: string;
contentHash: string;
}) {
const doc: ApmSourceMap = {
fleet_id: fleetId,
created,
Expand Down
Loading