@newrelic/newrelic-capacitor-plugin
Version:
NewRelic Plugin for ionic Capacitor
500 lines (491 loc) • 20.4 kB
JavaScript
var capacitorNewRelicCapacitorPlugin = (function (exports, core) {
'use strict';
/**
* Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
* Any copyright is dedicated to the Public Domain: https://creativecommons.org/publicdomain/zero/1.0/
*/
const getCircularReplacer = () => {
const seen = new WeakSet();
return (_key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
/*
* Copyright (c) 2022-present New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
exports.NREnums = void 0;
(function (NREnums) {
(function (LogLevel) {
LogLevel["ERROR"] = "ERROR";
LogLevel["WARNING"] = "WARNING";
LogLevel["INFO"] = "INFO";
LogLevel["VERBOSE"] = "VERBOSE";
LogLevel["AUDIT"] = "AUDIT";
})(NREnums.LogLevel || (NREnums.LogLevel = {}));
(function (NetworkFailure) {
NetworkFailure["Unknown"] = "Unknown";
NetworkFailure["BadURL"] = "BadURL";
NetworkFailure["TimedOut"] = "TimedOut";
NetworkFailure["CannotConnectToHost"] = "CannotConnectToHost";
NetworkFailure["DNSLookupFailed"] = "DNSLookupFailed";
NetworkFailure["BadServerResponse"] = "BadServerResponse";
NetworkFailure["SecureConnectionFailed"] = "SecureConnectionFailed";
})(NREnums.NetworkFailure || (NREnums.NetworkFailure = {}));
(function (MetricUnit) {
MetricUnit["PERCENT"] = "PERCENT";
MetricUnit["BYTES"] = "BYTES";
MetricUnit["SECONDS"] = "SECONDS";
MetricUnit["BYTES_PER_SECOND"] = "BYTES_PER_SECOND";
MetricUnit["OPERATIONS"] = "OPERATIONS";
})(NREnums.MetricUnit || (NREnums.MetricUnit = {}));
})(exports.NREnums || (exports.NREnums = {}));
/*
* Copyright (c) 2022-present New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
const NewRelicCapacitorPlugin = core.registerPlugin('NewRelicCapacitorPlugin', {
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.NewRelicCapacitorPluginWeb())
});
const defaultLog = window.console.log;
const defaultWarn = window.console.warn;
const defaultError = window.console.error;
const defaultAssert = window.console.assert;
const defaultDebug = window.console.debug;
console.log = function () {
var msgs = [];
defaultLog(...arguments);
while (arguments.length) {
var copyArguments = Object.assign({}, arguments);
msgs.push('[]' + ': ' + [].shift.call(arguments));
sendConsole('log', copyArguments);
}
};
console.warn = function () {
var msgs = [];
defaultWarn(...arguments);
while (arguments.length) {
var copyArguments = Object.assign({}, arguments);
msgs.push('[]' + ': ' + [].shift.call(arguments));
sendConsole('warn', copyArguments);
}
};
console.error = function () {
var msgs = [];
defaultError(...arguments);
while (arguments.length) {
var copyArguments = Object.assign({}, arguments);
msgs.push('[]' + ': ' + [].shift.call(arguments));
sendConsole('error', copyArguments);
}
};
console.assert = function () {
var msgs = [];
defaultAssert(...arguments);
while (arguments.length) {
var copyArguments = Object.assign({}, arguments);
msgs.push('[]' + ': ' + [].shift.call(arguments));
sendConsole('assert', copyArguments);
}
};
console.debug = function () {
var msgs = [];
defaultDebug(...arguments);
while (arguments.length) {
var copyArguments = Object.assign({}, arguments);
msgs.push('[]' + ': ' + [].shift.call(arguments));
sendConsole('debug', copyArguments);
}
};
function sendConsole(consoleType, _arguments) {
NewRelicCapacitorPlugin.getAgentConfiguration().then((agentConfig) => {
if (agentConfig.sendConsoleEvents) {
const argsStr = JSON.stringify(_arguments, getCircularReplacer());
if (consoleType === 'error') {
NewRelicCapacitorPlugin.logError({ message: `[CONSOLE][ERROR]${argsStr}` });
}
else if (consoleType === 'warn') {
NewRelicCapacitorPlugin.logWarning({ message: `[CONSOLE][WARN]${argsStr}` });
}
else if (consoleType === 'debug') {
NewRelicCapacitorPlugin.logDebug({ message: `[CONSOLE][DEBUG]${argsStr}` });
}
else {
NewRelicCapacitorPlugin.logInfo({ message: `[CONSOLE][LOG]${argsStr}` });
}
}
});
}
window.addEventListener('error', event => {
NewRelicCapacitorPlugin.recordError({
name: event.error.name,
message: event.error.message,
stack: event.error.stack,
isFatal: true,
});
});
window.addEventListener('unhandledrejection', e => {
var err = new Error(e.reason);
NewRelicCapacitorPlugin.recordError({
name: err.name,
message: err.message,
stack: 'no stack',
isFatal: false,
});
});
const networkRequest = {
url: "",
method: "",
body: "",
bytesSent: 0,
startTime: 0,
headers: [],
params: {}
};
const oldFetch = window.fetch;
window.fetch = function fetch() {
var _arguments = arguments;
var urlOrRequest = arguments[0];
var options = arguments[1];
return NewRelicCapacitorPlugin.getHTTPHeadersTrackingFor().then((trackingHeadersList) => {
console.log(trackingHeadersList);
return NewRelicCapacitorPlugin.generateDistributedTracingHeaders().then((headers) => {
networkRequest.startTime = Date.now();
if (urlOrRequest && typeof urlOrRequest === 'object') {
networkRequest.url = urlOrRequest.url;
if (options && 'method' in options) {
networkRequest.method = options.method;
}
else if (urlOrRequest && 'method' in urlOrRequest) {
networkRequest.method = urlOrRequest.method;
}
}
else {
networkRequest.url = urlOrRequest;
if (options && 'method' in options) {
networkRequest.method = options.method;
}
}
return NewRelicCapacitorPlugin.getAgentConfiguration().then((agentConfig) => {
if (options && 'headers' in options) {
if (agentConfig.distributedTracingEnabled) {
options.headers['newrelic'] = headers['newrelic'];
options.headers['traceparent'] = headers['traceparent'];
options.headers['tracestate'] = headers['tracestate'];
}
JSON.parse(trackingHeadersList["headersList"]).forEach((e) => {
if (options.headers[e] !== undefined) {
networkRequest.params[e] = options.headers[e];
}
});
}
else {
if (options === undefined) {
options = {};
}
if (agentConfig.distributedTracingEnabled) {
options['headers'] = {};
options.headers['newrelic'] = headers['newrelic'];
options.headers['traceparent'] = headers['traceparent'];
options.headers['tracestate'] = headers['tracestate'];
}
_arguments[1] = options;
}
if (!agentConfig.distributedTracingEnabled) {
headers = {};
}
if (options && 'body' in options && options.body !== null && options.body !== undefined) {
networkRequest.bytesSent = options.body.length;
}
else {
networkRequest.bytesSent = 0;
}
if (networkRequest.method === undefined || networkRequest.method === "") {
networkRequest.method = 'GET';
}
return new Promise(function (resolve, reject) {
// pass through to native fetch
oldFetch.apply(void 0, _arguments).then(function (response) {
handleFetchSuccess(response.clone(), networkRequest.method, networkRequest.url, networkRequest.startTime, headers, networkRequest.params);
resolve(response);
})["catch"](function (error) {
reject(error);
});
});
});
});
});
};
const originalXhrOpen = XMLHttpRequest.prototype.open;
const originalXhrSend = XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.open = function (method, url) {
networkRequest.url = url;
networkRequest.method = method;
networkRequest.bytesSent = 0;
networkRequest.startTime = Date.now();
return originalXhrOpen.apply(this, arguments);
};
window.XMLHttpRequest.prototype.send = function () {
if (this.addEventListener) {
this.addEventListener("readystatechange", async () => {
if (this.readyState === this.OPENED) ;
if (this.readyState === this.HEADERS_RECEIVED) {
if (this.getAllResponseHeaders()) {
const responseHeaders = this.getAllResponseHeaders().split("\r\n");
responseHeaders.forEach((element) => {
element.split(":")[0];
element.split(":")[1];
});
}
}
if (this.readyState === this.DONE) {
networkRequest.endTime = Date.now();
networkRequest.status = this.status;
const type = this.responseType;
if (type === "arraybuffer") {
networkRequest.bytesreceived = this.response.byteLength;
}
else if (type === "blob") {
networkRequest.bytesreceived = this.response.size;
}
else if (type === "text" || type === "" || type === undefined) {
networkRequest.bytesreceived = this.responseText.length;
networkRequest.body = this.responseText;
}
else {
// unsupported response type
networkRequest.bytesreceived = 0;
}
if (isValidURL(networkRequest.url)) {
NewRelicCapacitorPlugin.noticeHttpTransaction({
url: networkRequest.url,
method: networkRequest.method,
status: networkRequest.status,
startTime: networkRequest.startTime,
endTime: networkRequest.endTime,
bytesSent: networkRequest.bytesSent,
bytesReceived: networkRequest.bytesreceived,
body: networkRequest.body,
traceAttributes: networkRequest.headers,
params: networkRequest.params
});
}
}
}, false);
}
return originalXhrSend.apply(this, arguments);
};
function handleFetchSuccess(response, method, url, startTime, traceAttributes, params) {
response.text().then((v) => {
if (isValidURL(url)) {
NewRelicCapacitorPlugin.noticeHttpTransaction({
url: url,
method: method,
status: response.status,
startTime: startTime,
endTime: Date.now(),
bytesSent: networkRequest.bytesSent,
bytesReceived: v.length,
body: v,
traceAttributes: traceAttributes,
params: params
});
}
});
}
function isValidURL(url) {
try {
const newUrl = new URL(url);
return newUrl.protocol === 'http:' || newUrl.protocol === 'https:';
}
catch (err) {
return false;
}
}
class NewRelicCapacitorPluginWeb extends core.WebPlugin {
start(_options) {
// throw new Error('Method not implemented.');
}
setUserId(_options) {
//throw new Error('Method not implemented.');
}
setAttribute(_options) {
//throw new Error('Method not implemented.');
}
removeAttribute(_options) {
//throw new Error('Method not implemented.');
}
recordBreadcrumb(_options) {
// throw new Error('Method not implemented.');
}
recordCustomEvent(_options) {
// throw new Error('Method not implemented.');
}
startInteraction(_options) {
return new Promise((resolve) => {
resolve({ value: '' });
});
}
endInteraction(_options) {
// throw new Error('Method not implemented.');
}
crashNow(_options) {
//throw new Error('Method not implemented.');
}
currentSessionId(_options) {
//throw new Error('Method not implemented.');
return new Promise((resolve) => {
resolve({ sessionId: '' });
});
}
incrementAttribute(_options) {
// throw new Error('Method not implemented.');
}
noticeNetworkFailure(_options) {
// throw new Error('Method not implemented.');
}
noticeHttpTransaction(_options) {
// throw new Error('Method not implemented.');
}
recordMetric(_options) {
// throw new Error('Method not implemented.');
}
removeAllAttributes(_options) {
// throw new Error('Method not implemented.');
}
setMaxEventBufferTime(_options) {
// throw new Error('Method not implemented.');
}
setMaxEventPoolSize(_options) {
// throw new Error('Method not implemented.');
}
setMaxOfflineStorageSize(_options) {
// throw new Error('Method not implemented.');
}
recordError(_options) {
// throw new Error('Method not implemented.');
}
analyticsEventEnabled(_options) {
// throw new Error('Method not implemented.');
}
networkRequestEnabled(_options) {
// throw new Error('Method not implemented.');
}
networkErrorRequestEnabled(_options) {
// throw new Error('Method not implemented.');
}
httpResponseBodyCaptureEnabled(_options) {
// throw new Error('Method not implemented.');
}
getAgentConfiguration(_options) {
let a = {
analyticsEventEnabled: true,
crashReportingEnabled: true,
interactionTracingEnabled: true,
networkRequestEnabled: true,
networkErrorRequestEnabled: true,
httpResponseBodyCaptureEnabled: true,
webViewInstrumentation: true,
loggingEnabled: true,
logLevel: '',
collectorAddress: '',
crashCollectorAddress: '',
sendConsoleEvents: true,
fedRampEnabled: false,
offlineStorageEnabled: true,
distributedTracingEnabled: false,
};
return new Promise((resolve) => {
resolve(a);
});
}
shutdown(_options) {
// throw new Error('Method not implemented.');
}
generateDistributedTracingHeaders(_options) {
let dtHeaders = {
newrelic: "1",
traceparent: "1",
tracestate: "1",
traceid: "1",
guid: "1",
id: "1"
};
return new Promise((resolve) => {
resolve(dtHeaders);
});
// throw new Error('Method not implemented.');
}
addHTTPHeadersTrackingFor(_options) {
// throw new Error('Method not implemented.');
}
log(_options) {
if (_options.message === undefined || _options.message.length === 0) {
// If the message is empty, log an error message and return
console.error("Log message is empty.");
return;
}
// Create a new Map to store attributes
let attributes = new Map();
// Set the message and log level as attributes
attributes.set("message", _options.message);
attributes.set("level", _options.level);
// Log the attributes
this.logAttributes({ attributes: attributes });
}
logError(_options) {
this.log({ level: exports.NREnums.LogLevel.ERROR, message: _options.message });
}
logWarning(_options) {
this.log({ level: exports.NREnums.LogLevel.WARNING, message: _options.message });
}
logAll(_options) {
let allAttributes = new Map();
// Set the error message as an attribute
allAttributes.set("message", _options.error);
// Iterate over the attributes Map and add each attribute to allAttributes
for (let [key, value] of Object.entries(_options.attributes)) {
allAttributes.set(key, value);
}
// Log all attributes
this.logAttributes({ attributes: allAttributes });
}
logInfo(_options) {
this.log({ level: exports.NREnums.LogLevel.INFO, message: _options.message });
}
logVerbose(_options) {
this.log({ level: exports.NREnums.LogLevel.VERBOSE, message: _options.message });
}
logDebug(_options) {
this.log({ level: exports.NREnums.LogLevel.AUDIT, message: _options.message });
}
logAttributes(_options) {
if (_options.attributes === undefined || _options.attributes.size === 0) {
// If the attributes are empty, log an error message and return
console.error("Attributes are empty.");
return;
}
}
getHTTPHeadersTrackingFor() {
let httpHeadersTracking = {
headersList: "[]"
};
return new Promise((resolve) => {
resolve(httpHeadersTracking);
});
}
}
var web = /*#__PURE__*/Object.freeze({
__proto__: null,
NewRelicCapacitorPluginWeb: NewRelicCapacitorPluginWeb
});
exports.NewRelicCapacitorPlugin = NewRelicCapacitorPlugin;
return exports;
})({}, capacitorExports);
//# sourceMappingURL=plugin.js.map