Export Digital Assistant Insights
Here's how to use JavaScript to export a digital assistant's insights into ZIP files that contain the data in CSV format. You can optionally export the data for a specific date range.
Disclaimer: This example is provided as-is, with no support provided by Oracle world-wide customer support.
Before You Begin
- Verify that you are an IAM user who has been assigned to a group with a policy that allows you to use oda-instance-resource. This is typically the IAM policy for service administrators. To learn about IAM users, policies, and groups, see Set Up Groups, Users, and Policies in Using Oracle Digital Assistant.
Create the Folder Structure and Add Files
Follow these steps to create the folder structure and add the necessary files.
-
Create the top-level folder. For example:
export-da-insights
. -
Add a
package.json
file with the following content:{ "name": "da-insights-export", "version": "2.0.0", "description": "This is the code for the digital assistants insights export use case in the REST Reference.", "main": "main.js", "scripts": { "start": "node src/main.js", "start:dev": "nodemon --inspect src/main.js", "lint": "eslint ./src/lib", "lint:fix": "eslint ./src/lib --fix" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "log4js": "^6.3.0", "oci-common": "^2.1.0" }, "devDependencies": { "eslint": "^7.32.0", "nodemon": "^2.0.12" } }
-
In the top-level folder, create
config
andsrc
subfolders. -
Add a file named
config.js
to theconfig
folder and add this content:/* * Logging level ALL|INFO|DEBUG|WARN|ERROR|FATAL|OFF|TRACE */ module.exports.LOGGING_LEVEL = 'INFO'; /* * OCI request signature configurations */ // OCI CLI config file module.exports.OCI_CONFIG_FILE_PATH = '~/.oci/config'; // OCI CLI profile name module.exports.OCI_CONFIG_PROFILE_NAME = 'DEFAULT'; /* * Oracle Digital Assistant configurations */ // Digital Assistant host name without "https://" module.exports.ODA_HOSTNAME= ''; // API base path - do not modify module.exports.INSIGHTS_API_BASE_PATH = '/api/v1'; /* * Run configurations */ // Relative path for output directory for exported data module.exports.INSIGHTS_EXPORT_OUTPUT_DIRECTORY_NAME = 'output'; // Query and body parameters // For parameter descriptions and valid values see // https://docs.oracle.com/en/cloud/paas/digital-assistant/rest-api-oci/op-bots-insights-dataexports-post.html // Insights Export job name module.exports.INSIGHTS_EXPORT_NAME = ''; // ID of digital assistant module.exports.ODA_DA_ID = ''; // Insights Export job range start date in format YYYY-MM-DD module.exports.INSIGHTS_EXPORT_START_DATE_RANGE = '2021-01-01'; // Insights Export job range end date in format YYYY-MM-DD module.exports.INSIGHTS_EXPORT_END_DATE_RANGE = '2021-08-24'; // Task type EXPORT|EXPORT_PURGE module.exports.INSIGHTS_API_TASK_TYPE = 'EXPORT'; // Just export the essential data module.exports.INSIGHTS_DATA_EXPORT= 'true'; // Maximum number of rows per ZIP file module.exports.MAX_FILE_LENGTH= '100000000'; /* * Constants */ // Maximum number of tries to check for export task completion module.exports.MAX_STATUS_RETRIES = 20; // Active export task statuses - do not modify module.exports.ACTIVE_STATUSES= 'SUBMITTED IN_PROGRESS';
-
In the
src
folder, create a file namedmain.js
, and then add this code:const CONFIG = require('../config/config'); const ODAManager = require('./lib/ODAManager'); const log4js = require('log4js'); const logger = log4js.getLogger('ODA Insights Exporter'); logger.level = CONFIG.LOGGING_LEVEL; // Start insights export job ODAManager.startInsightsExport() .then( () => {logger.info('Insights data exported and downloaded.');}) .catch(error => { logger.debug(error); logger.info('Could not export insights data.'); });
-
Create a
lib
subfolder undersrc
. -
Complete the instructions in the Send Signed Requests use case to add
OCIManager.js
to thelib
directory, create the OCIconfig
file, and update the package'sconfig/config.js
file to provide the OCI request signature configurations. -
In the
lib
folder, createODAManager.js
and add this content.const CONFIG = require('../../config/config'); const OCIManager = require('./OCIManager'); const fs = require('fs'); const path = require('path'); const log4js = require('log4js'); const logger = log4js.getLogger('ODA Manager'); logger.level = CONFIG.LOGGING_LEVEL; class ODAManager { constructor() { } /** * Export insights data into filesystem */ async startInsightsExport() { try { // Create job to export insights data const exportJobId = await this._generateInsightsExport(); // Wait for export job to finish const exportResult = await this._waitForInsightsExport(exportJobId); // Examine results of export job const examineExportResult = this._examineExportResult(exportResult); // If export job finished successfully, then write the exported data to the file system if (examineExportResult) { // Write exported data to file system await this._writeExportedData(exportResult); } } catch (error) { const errorMessage = `Error exporting DA insights data. Detailed error: ${error.message} Request ID: ${error.opcRequestId}`; logger.error(errorMessage); throw (error); } } /** * Start an insights export job * @returns {Promise<string>} Insights export job ID */ async _generateInsightsExport() { try { // Prepare body for export insights data API const body = { insightsDataExport: CONFIG.INSIGHTS_DATA_EXPORT, taskType: CONFIG.INSIGHTS_API_TASK_TYPE, name: CONFIG.INSIGHTS_EXPORT_NAME }; // Prepare query params for export insights data API const sinceQueryParm = CONFIG.INSIGHTS_EXPORT_START_DATE_RANGE ? `&since=${encodeURIComponent(CONFIG.INSIGHTS_EXPORT_START_DATE_RANGE)}` : ''; const untilQueryParm = CONFIG.INSIGHTS_EXPORT_END_DATE_RANGE ? `&until=${encodeURIComponent(CONFIG.INSIGHTS_EXPORT_END_DATE_RANGE)}` : ''; const odaId = encodeURIComponent(CONFIG.ODA_DA_ID); const maxFileLength = encodeURIComponent(CONFIG.MAX_FILE_LENGTH); const URI = `https://${CONFIG.ODA_HOSTNAME}${CONFIG.INSIGHTS_API_BASE_PATH}/bots/insights/dataExports?odaId=${odaId}&maxFileLength=${maxFileLength}${sinceQueryParm}${untilQueryParm}`; // Send request for starting an insights export job const result = await OCIManager.send(URI, 'POST', body); const jobId = result.result.jobId; return jobId; } catch (error) { const errorMessage = `Error getting DA insights data. Detailed error: ${error.message} Request ID ${error.opcRequestId}`; logger.error(errorMessage); throw error; } } /** * Wait for an insights export job to finish * @param {string} jobId - An alphanumeric string representing an insights export job ID * @returns {object} Result from GET /bots/insights/dataExports/{id} */ async _waitForInsightsExport(jobId) { try { const URL = `https://${CONFIG.ODA_HOSTNAME}${CONFIG.INSIGHTS_API_BASE_PATH}/bots/insights/dataExports/${encodeURIComponent(jobId)}`; const method = 'GET'; let attemptsCount = 0; const exponentialBackOffFactor = 3; let result = null; logger.info('Insights data export job is in progress.'); // Loop indefinitely till the maximum number of retires reached as defined in /config/config.js // eslint-disable-next-line no-constant-condition while (true) { // Check if maximum number of retries reached, if yes, throw an error to exit if (++attemptsCount > CONFIG.MAX_STATUS_RETRIES) { const errorMessage = `Max retries reached for checking the status of insights export job [ ${jobId} ]`; throw new Error(errorMessage); } // Send request to get the status of insights export job result = await OCIManager.send(URL, method); // check the status of the insights job, and if it is still not ready, // sleep for exponential backoff number of seconds and then try again if (result.result && result.result.status && CONFIG.ACTIVE_STATUSES.includes(result.result.status.toUpperCase())) { logger.warn('Insights data export job is still in progress.'); // Wait before retrying again by implementing exponential back-off strategy using a factor of 3 await this._sleep(attemptsCount * exponentialBackOffFactor * 1000); // ex. ( 1 (attemptCount) * 3 exponentialBackOffFactor ) seconds * 1000 milliseconds } // Insights export job has finished processing else { logger.info('Insights data export job has finished and the data is ready to download.'); break; } } // Return insights export job result return result.result; } catch (error) { const errorMessage = `Error waiting for insights export job [ ${jobId} ] to finish. Detailed error: ${error.message} Request ID: ${error.opcRequestId}`; logger.error(errorMessage); throw new Error(errorMessage); } } /** * Wait for a specified time. * @param {number} duration wait duration in milliseconds * @returns */ _sleep(duration) { return new Promise(resolve => setTimeout(resolve, duration)); } /** * Examine the outcome of an insights export job to determine if it was successful or not * @param {object} exportResult - JSON object returned as a result of getting insights export job details * @returns boolean to indicate if the export job was successful or not */ _examineExportResult(exportResult) { logger.info('Examining insights export status.'); let exportSucceeded = false; switch (exportResult.status.toUpperCase()) { case 'EXPORT_SUCCEEDED': { exportSucceeded = true; break; } case 'EXPORT_FAILED': logger.error(exportResult.error); break; case 'NO_DATA': logger.warn('There isn\'t any data to export, try a different date range.'); break; default: logger.warn(`The export task is still running. You'll have to download the file later. The export task ID = ${exportResult.jobId}`); } return exportSucceeded; } /** * Get the insights export data ZIPs and write them to the specified relative directory * @param {object} exportResult - JSON object returned as a result of getting insights export job details */ async _writeExportedData(exportResult) { try { // Make sure output directory exists if(!fs.existsSync(path.resolve(path.join( __dirname,'..', '..',CONFIG.INSIGHTS_EXPORT_OUTPUT_DIRECTORY_NAME)))){ fs.mkdirSync(path.resolve(path.join(__dirname,'..','..', CONFIG.INSIGHTS_EXPORT_OUTPUT_DIRECTORY_NAME))); } const outputDirectoryPath = path.resolve(path.join(__dirname,'..','..', CONFIG.INSIGHTS_EXPORT_OUTPUT_DIRECTORY_NAME)); if (exportResult.filenames && Array.isArray(exportResult.filenames)) { // Loop over all the insights export ZIP file names for (const file of exportResult.filenames) { // Get insights export ZIP file const URL = `https://${CONFIG.ODA_HOSTNAME}${CONFIG.INSIGHTS_API_BASE_PATH}/bots/insights/dataExports/${encodeURIComponent(exportResult.jobId)}/files/${encodeURIComponent(file)}`; const result = await OCIManager.send(URL, 'GET'); // Write exported insights ZIP file to file system const outputFilePath = path.join(outputDirectoryPath, path.sep , file); const fileStream = fs.createWriteStream(outputFilePath); //`${path.resolve(CONFIG.INSIGHTS_EXPORT_OUTPUT_DIRECTORY)}/${file}` result.result.body.on('error', (error) => { throw error; }); result.result.body.on('finish', () => { }); result.result.body.pipe(fileStream); logger.info(`${outputFilePath} downloaded.`); } } } catch (error) { const errorMessage = `Error writing exported files. Request ID: ${error.opcRequestId}`; logger.error(errorMessage); throw new Error(errorMessage); } } } module.exports = new ODAManager();
-
From a command terminal, change to the top level directory and run this command to install the libraries:
npm install
Run the Script
-
Open the
config/config.js
file and set the desired run configurations./* * Run configurations */ // Relative path for output directory for exported data module.exports.INSIGHTS_EXPORT_OUTPUT_DIRECTORY_NAME = 'output'; // Query and body parameters // For parameter descriptions and valid values see // https://docs.oracle.com/en/cloud/paas/digital-assistant/rest-api-oci/op-bots-insights-dataexports-post.html // Insights Export job name module.exports.INSIGHTS_EXPORT_NAME = ''; // ID of digital assistant module.exports.ODA_DA_ID = ''; // Insights Export job range start date in format YYYY-MM-DD module.exports.INSIGHTS_EXPORT_START_DATE_RANGE = '2021-01-01'; // Insights Export job range end date in format YYYY-MM-DD module.exports.INSIGHTS_EXPORT_END_DATE_RANGE = '2021-08-24'; // Task type EXPORT|EXPORT_PURGE module.exports.INSIGHTS_API_TASK_TYPE = 'EXPORT'; // Just export the essential data module.exports.INSIGHTS_DATA_EXPORT= 'true'; // Maximum number of rows per ZIP file module.exports.MAX_FILE_LENGTH= '100000000';
-
From a terminal, change to the top-level directory, and then enter this command to run the script:
npm start
You should see output similar to this:
[2021-09-14T10:13:58.134] [INFO] ODA Manager - Insights data export job is in progress. [2021-09-14T10:13:59.066] [INFO] ODA Manager - Insights data export job has finished and the data is ready to download. [2021-09-14T10:13:59.069] [INFO] ODA Manager - Examining insights export status. [2021-09-14T10:14:00.657] [INFO] ODA Manager - ~/output/ocid1.odainstance.oc1.phx.abcdefgjvdfmgia437o~insightsdata~0.zip downloaded. [2021-09-14T10:14:00.660] [INFO] ODA Insights Exporter - Insights data exported and downloaded.