How can i ensure uploaded source maps exists on server and contains correct settings, to be used in observed project?

Problem:

Successfully uploaded source maps, does not applied to project being monitored.

Description:

Hello everyone, i got a problem i don`t know how to solve. We added apm-rum-vue@2.1.2 to our project.

After that all errors successfully was downloaded and we can check their stacktrace in Kibana.

But, after uploading generated source maps nothing changed. The stacktrace remained the same.

The problem is, all source maps were uploaded successfully. I can fetch them back and delete them. But they not used for my project.

I thought, thats happen because i not configured my vue.config.js as shown in this document. But, after i configured it nothing changed.

I tried to check network tab in APM section of Kibana, to ensure that service fetches correct version of generated source maps. But, i cannot find any request like that in network section.

So, i don`t know how to check, that APM fetches correct version of source maps, or find any information about errors, that occured.

And because of that, i don`t know what i need to fix in my code, to make source maps working. Is there a way to do it?

Stack i`m using

  1. What version of RUM are you using? @elastic/apm-rum-vue: "^2.1.2
  2. What version of the elastic stack are you using? APM Standalone server
  3. Are you using APM server standalone or APM integration? Kibana separately, apm Separately.

Vue.config.js

const serviceVersion = require("./package.json").version;
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
    configureWebpack: {
        devtool: 'source-map',
        devServer: {
            host: 'vue.crm.local'
        },
        optimization: {
            minimize: true,
            minimizer: [new TerserPlugin(
                {
                    sourceMap: true,
                },
            )],
        },
    },
    chainWebpack: config => {
        config.plugin('define').tap(args => {
            args[0].serviceVersion = JSON.stringify(serviceVersion);
            return args
        })
    },
}

Someone, pls help :frowning:

Hi @Ivan.K,

  1. What version of the elastic stack are you using? APM Standalone server

Could you please specify the version? for example: 8.13

But, after uploading generated source maps nothing changed. The stacktrace remained the same.

Did I understand correctly that you already have errors indexed, and after uploading the sourcemap, you'd expect to see the sourcemap applied for those errors? The sourcemapping is applied on ingest, so the errors indexed before uploading the sourcemap won't have the sourcemapping applied retroactively. You could try to index errors after uploading the sourcemap, and it should show up if the sourcemap is uploaded correctly.

On the other hand, if sourcemapping is not applied to the errors that have been ingested after uploading the sourcemap, it'd worth checking the config when you've uploaded the sourcemap, especially the bundle_filepath parameter. It needs to match with the abs_path of the stacktrace.

Hello @kyungeunni, partly yes. But after uploading source maps, i created another Error

After uploading source maps, i created another Error programmatically. Even though the sourcemaps were loaded, the wasn`t applied to new error.

If i understand correctly, you want to take a look at code, that i use to download sourcemaps to server, there bundle_filepath is used.

The version of apm is 7.17.6

This is my config file:

// const DEFAULT_VUE_APP_VERSION = require('../package.json').version;
const DEFAULT_VUE_APP_VERSION = require('../../package.json').version;
const DEFAULT_VUE_APP_HOST_URL = 'http://localhost:8080';
const DEFAULT_KIBANA_API_KEY = APIKEY
const DEFAULT_KIBANA_URL = URL
const DEFAULT_VUE_APM_SERVICE_NAME = 'crm-front';

const kibanaUrl = process.env.KIBANA_URL || DEFAULT_KIBANA_URL;
const kibanaApiKey = process.env.KIBANA_API_KEY || DEFAULT_KIBANA_API_KEY;
const publicUrl = PUBLIC_URL || DEFAULT_VUE_APP_HOST_URL;
const serviceVersion = process.env.VUE_APP_VERSION || DEFAULT_VUE_APP_VERSION;
const serviceName = process.env.VUE_APP_APM_SERVICE_NAME || DEFAULT_VUE_APM_SERVICE_NAME;

const config = {
    kibanaUrl,
    kibanaApiKey,
    publicUrl,
    service: {
        version: serviceVersion,
        name: serviceName,
    },
};

module.exports = config;

This is my code for uploading sourcemaps:

const path = require('path');
const fs = require('fs');
const FormData = require('form-data');

const axiosInstance = require('./axiosInstance');
const config = require('./config');


const DIST_PATH = 'dist/js';
const EXIT_CODE = 1;
const STRINGIFY_SPACER = 2;

if (!fs.existsSync(path.resolve(__dirname, `../../${DIST_PATH}`))) {
    console.log(`${DIST_PATH} does not exists`);
    process.exit(EXIT_CODE);
}

/**
 * Generate form data with a sourcemap file to upload.
 * @param {string} folder
 * @param {string} sourcemap
 * @param {string} bundle
 * @returns {object}
 */
const generateFormData = ({ folder, sourcemap, bundle }) => {

    const fileName = path.resolve(__dirname, `../../${DIST_PATH}/${sourcemap}`);
    const formData = new FormData();

    formData.append('service_name', config.service.name);
    formData.append('service_version', config.service.version);
    formData.append('bundle_filepath', `${config.publicUrl}/js/${bundle}`);
    formData.append('sourcemap', fs.readFileSync(fileName));

    return formData;
};

/**
 * Send a request to upload a sourcemap file.
 * @param {object} data
 * @returns {Promise<AxiosResponse<any>>}
 */
const sendUploadRequest = (data) => {
    return axiosInstance.post(`api/apm/sourcemaps`, data, {
        headers: {
            ...data.getHeaders(),
        },
    });
};

/**
 * @param {string} bundle
 * @param {object} response
 */
const onSuccess = (bundle, response) => {
    console.log(`Successfully uploaded sourcemap for ${bundle}`);
    console.log(JSON.stringify({
        id: response.data.id,
        created: response.data.created,
        relative_url: response.data.relative_url,
        identifier: response.data.identifier,
    }, null, STRINGIFY_SPACER));
};

/**
 * @param {string} bundle
 * @param {object} error
 */
const onError = (bundle, error) => {
    console.log(`Failed to upload sourcemap for ${bundle}:`);

    if (error.response) {
        console.log(`[${error.response.status}]\n`, error.response.data);
    } else {
        console.error(error);
    }

    throw error;
};

/**
 * Upload .map files from a folder
 * @param {string} folder
 */
const uploadFromFolder = (folder) => {
    return fs.readdir(path.resolve(__dirname, `../../${DIST_PATH}`), (err, files) => {
        if (err) {
            throw err;
        }

        files.filter(fileName => fileName.endsWith('.js')).map((fileName) => {
            const mapFile = files.find(currentFileName => currentFileName === `${fileName}.map`);

            if (!mapFile || !mapFile.length) {
                console.log(fileName, 'fileName aborted upload');
                return null;
            }

            return {
                bundle: fileName,
                sourcemap: mapFile,
            };
        }).filter(file => !!file).reduce((promise, { bundle, sourcemap }) => promise.then(() => {
            const formData = generateFormData({
                folder,
                bundle,
                sourcemap,
            });

            return sendUploadRequest(formData)
                .then(onSuccess.bind(null, bundle))
                .catch(onError.bind(null, bundle));
        }), Promise.resolve());
    });
};

['client', 'server'].reduce((promise, folder) => {
    return promise.then(() => uploadFromFolder(folder));
}, Promise.resolve()).catch(() => {
    process.exit(EXIT_CODE);
});

So can anyone help me?
Unfortunately @kyungeunni forget about me, but we need your help and waiting for it(

From Elastic Observability to APM

Added server