strogger
Version:
📊 A modern structured logging library with functional programming, duck-typing, and comprehensive third-party integrations
131 lines • 5.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createNewRelicTransport = void 0;
const types_1 = require("../types");
const errors_1 = require("../utils/errors");
const base_transport_1 = require("./base-transport");
const createNewRelicTransport = (options = {}) => {
const transportName = "New Relic";
try {
let minLevel = options.level ?? types_1.LogLevel.INFO;
// Note: formatter is available for custom formatting
// const formatter = options.formatter || {
// format: (entry: LogEntry) => JSON.stringify(entry),
// };
const apiKey = options.apiKey || process.env.NEW_RELIC_LICENSE_KEY;
const accountId = options.accountId || process.env.NEW_RELIC_ACCOUNT_ID;
const region = options.region || process.env.NEW_RELIC_REGION || "us";
const serviceName = options.serviceName || process.env.NEW_RELIC_SERVICE_NAME;
const batchSize = options.batchSize || 10;
const flushInterval = options.flushInterval || 5000;
// Validate required configuration
(0, errors_1.validateEnvironmentVariable)("NEW_RELIC_LICENSE_KEY", apiKey, true);
(0, errors_1.validateEnvironmentVariable)("NEW_RELIC_ACCOUNT_ID", accountId, true);
// Validate transport configuration
(0, errors_1.validateTransportConfig)(transportName, { apiKey, accountId }, [
"apiKey",
"accountId",
]);
let batch = [];
let flushTimer = null;
const sendToNewRelic = async (entries) => {
try {
const url = `https://log-api.${region}.newrelic.com/log/v1`;
const payload = {
timestamp: Date.now(),
service: serviceName,
attributes: {
// New Relic specific attributes
logtype: "application",
timestamp: new Date().toISOString(),
},
logs: entries.map((entry) => ({
message: entry.message,
level: entry.level,
timestamp: new Date(entry.timestamp).getTime(),
attributes: {
...entry.context,
...(entry.error && {
error_name: entry.error.name,
error_message: entry.error.message,
error_stack: entry.error.stack,
}),
...(entry.metadata && { metadata: entry.metadata }),
},
})),
};
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key": apiKey,
"X-License-Key": apiKey,
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw (0, errors_1.createDetailedError)("NEW_RELIC_API_ERROR", transportName, {
status: response.status,
statusText: response.statusText,
url,
responseBody: await response
.text()
.catch(() => "Unable to read response body"),
});
}
}
catch (error) {
(0, errors_1.handleTransportError)(error, transportName, true);
}
};
const flush = async () => {
if (batch.length === 0)
return;
const entriesToSend = [...batch];
batch = [];
await sendToNewRelic(entriesToSend);
};
const startFlushTimer = () => {
if (flushTimer)
return;
flushTimer = setInterval(() => {
flush().catch((error) => {
(0, errors_1.handleTransportError)(error, transportName, true);
});
}, flushInterval);
};
// Start the flush timer
startFlushTimer();
return {
log: async (entry) => {
if (!(0, base_transport_1.shouldLog)(entry.level, minLevel))
return;
batch.push(entry);
if (batch.length >= batchSize) {
await flush();
}
},
setLevel: (level) => {
minLevel = level;
},
getLevel: () => minLevel,
// New Relic specific methods
flush: async () => {
await flush();
},
close: async () => {
if (flushTimer) {
clearInterval(flushTimer);
flushTimer = null;
}
await flush();
},
};
}
catch (error) {
(0, errors_1.handleTransportError)(error, transportName, false);
throw error; // Re-throw for proper error handling
}
};
exports.createNewRelicTransport = createNewRelicTransport;
//# sourceMappingURL=newrelic-transport.js.map