diff --git a/CHANGELOG.md b/CHANGELOG.md index 1455280..5566140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # Changelog +## v1.1.2 +- Change telemetry provider. ## v1.1.1 - Fix variable case-sensitivity ([#7](https://github.com/qetza/replacetokens-action/issues/7)). diff --git a/dist/index.js b/dist/index.js index afa01a2..5bb7086 100644 --- a/dist/index.js +++ b/dist/index.js @@ -63417,7 +63417,7 @@ async function run() { const telemetry = new telemetry_1.TelemetryClient(process.env['GITHUB_REPOSITORY'], process.env['GITHUB_WORKFLOW'], process.env['GITHUB_SERVER_URL'] === 'https://github.com' ? 'cloud' : 'server', process.env['RUNNER_OS']); if (!core.getBooleanInput('no-telemetry') && !['true', '1'].includes(process.env['REPLACETOKENS_TELEMETRY_OPTOUT'] || '')) { - telemetry.useApplicationInsightsExporter({ log: core.debug }); + telemetry.enableTelemetry({ log: core.debug }); } const telemetryEvent = telemetry.startSpan('run'); try { @@ -63803,11 +63803,11 @@ const sdk_trace_base_1 = __nccwpck_require__(29253); const crypto = __importStar(__nccwpck_require__(6113)); const axios_1 = __importDefault(__nccwpck_require__(88757)); const application = 'replacetokens-action'; -const version = '1.1.0'; -const url = 'https://westeurope-5.in.applicationinsights.azure.com/v2/track'; -const key = 'e18a8793-c093-46f9-8c3b-433c9553eb7f'; +const version = '1.1.2'; +const endpoint = 'https://insights-collector.eu01.nr-data.net/v1/accounts/4392697/events'; +const key = 'eu01xxc28887c2d47d9719ed24a74df5FFFFNRAL'; const timeout = 3000; -class ApplicationInsightsExporter { +class NewRelicExporter { _log; _isShutdown = false; constructor(log) { @@ -63821,9 +63821,7 @@ class ApplicationInsightsExporter { } if (spans.length > 0) { const events = spans.map(s => this._spanToEvent(s)); - this._log(`telemetry: ${JSON.stringify(events.map(e => { - return { ...e, name: '*****', iKey: '*****' }; - }))}`); + this._log(`telemetry: ${JSON.stringify(events)}`); resultCallback(await this._send(events)); } resultCallback({ code: core_1.ExportResultCode.SUCCESS }); @@ -63834,48 +63832,33 @@ class ApplicationInsightsExporter { } _spanToEvent(span) { return { - name: `Microsoft.ApplicationInsights.Dev.${key}.Event`, - time: new Date((0, core_1.hrTimeToNanoseconds)(span.startTime) / 1000000).toISOString(), - iKey: key, - tags: { - 'ai.application.ver': version, - 'ai.cloud.role': span.attributes['host'], - 'ai.internal.sdkVersion': 'replacetokens:2.0.0', - 'ai.operation.id': span.spanContext().traceId, - 'ai.operation.name': application, - 'ai.user.accountId': span.attributes['account'], - 'ai.user.authUserId': span.attributes['workflow'] - }, - data: { - baseType: 'EventData', - baseData: { - ver: '2', - name: 'tokens.replaced', - properties: { - ...span.attributes, - host: undefined, - account: undefined, - workflow: undefined, - result: (() => { - switch (span.status.code) { - case api_1.SpanStatusCode.ERROR: - return 'failed'; - case api_1.SpanStatusCode.OK: - return 'success'; - default: - return ''; - } - })(), - duration: (0, core_1.hrTimeToMilliseconds)(span.duration) - } + eventType: 'TokensReplaced', + application: application, + version: version, + ...span.attributes, + result: (() => { + switch (span.status.code) { + case api_1.SpanStatusCode.ERROR: + return 'failed'; + case api_1.SpanStatusCode.OK: + return 'success'; + default: + return ''; } - } + })(), + duration: (0, core_1.hrTimeToMilliseconds)(span.duration) }; } async _send(data) { try { - const options = { timeout: timeout }; - await axios_1.default.post(url, data, options); + const options = { + headers: { + 'Api-Key': key, + 'Content-Type': 'application/json' + }, + timeout: timeout + }; + await axios_1.default.post(endpoint, data, options); return { code: core_1.ExportResultCode.SUCCESS }; } catch (e) { @@ -63890,7 +63873,7 @@ class TelemetryClient { _workflow; _host; _os; - _isApplicationInsightsExporterRegistered = false; + _isEnabled = false; constructor(account, workflow, host, os) { this._provider = new sdk_trace_base_1.BasicTracerProvider({ forceFlushTimeoutMillis: timeout }); this._tracer = this._provider.getTracer(application, version); @@ -63907,14 +63890,14 @@ class TelemetryClient { } startSpan(name) { return this._tracer.startSpan(name, { - attributes: { account: this._account, workflow: this._workflow, host: this._host, os: this._os } + attributes: { account: this._account, pipeline: this._workflow, host: this._host, os: this._os } }); } - useApplicationInsightsExporter(options) { - if (this._isApplicationInsightsExporterRegistered) + enableTelemetry(options) { + if (this._isEnabled) return; - this._provider.addSpanProcessor(new sdk_trace_base_1.SimpleSpanProcessor(new ApplicationInsightsExporter(options.log))); - this._isApplicationInsightsExporterRegistered = true; + this._provider.addSpanProcessor(new sdk_trace_base_1.SimpleSpanProcessor(new NewRelicExporter(options.log))); + this._isEnabled = true; } } exports.TelemetryClient = TelemetryClient; diff --git a/package.json b/package.json index 94d530d..0570fe9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "replacetokens-action", - "version": "1.1.1", + "version": "1.1.2", "description": "An action to replace tokens with variables and/or secrets.", "private": true, "author": "Guillaume ROUCHON", @@ -30,7 +30,7 @@ "build": "npm run format && npm run package", "format": "prettier --write **/*.ts", "format:check": "prettier --check **/*.ts", - "package": "ncc build src/index.ts --license licenses.txt", + "package": "ncc build src/index.ts --license licenses.txt && node scripts/package.js", "test": "jest" }, "dependencies": { diff --git a/scripts/package.js b/scripts/package.js new file mode 100644 index 0000000..00149ba --- /dev/null +++ b/scripts/package.js @@ -0,0 +1,14 @@ +var fs = require('fs'); +var path = require('path'); + +console.log(); +console.log('update metadata'); + +var package = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8')); + +var p = path.join(__dirname, '..', 'dist', 'index.js'); +var index = fs.readFileSync(p, 'utf-8'); +index = index.replace(/const\s+version\s*=\s*'[^']*'\s*;/, `const version = '${package.version}';`); +console.log(`> version: ${package.version}`) + +fs.writeFileSync(p, index); \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 2405b45..2771c4a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -24,7 +24,7 @@ export async function run(): Promise { !core.getBooleanInput('no-telemetry') && !['true', '1'].includes(process.env['REPLACETOKENS_TELEMETRY_OPTOUT'] || '') ) { - telemetry.useApplicationInsightsExporter({ log: core.debug }); + telemetry.enableTelemetry({ log: core.debug }); } const telemetryEvent = telemetry.startSpan('run'); diff --git a/src/telemetry.ts b/src/telemetry.ts index b93b611..df6d014 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -1,16 +1,16 @@ -import { ExportResult, ExportResultCode, hrTimeToMilliseconds, hrTimeToNanoseconds } from '@opentelemetry/core'; +import { ExportResult, ExportResultCode, hrTimeToMilliseconds } from '@opentelemetry/core'; import { SpanStatusCode, Tracer, Span } from '@opentelemetry/api'; import { BasicTracerProvider, SimpleSpanProcessor, SpanExporter, ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as crypto from 'crypto'; import axios from 'axios'; const application = 'replacetokens-action'; -const version = '1.1.0'; -const url = 'https://westeurope-5.in.applicationinsights.azure.com/v2/track'; -const key = 'e18a8793-c093-46f9-8c3b-433c9553eb7f'; +const version = '1.0.0'; +const endpoint = 'https://insights-collector.eu01.nr-data.net/v1/accounts/4392697/events'; +const key = 'eu01xxc28887c2d47d9719ed24a74df5FFFFNRAL'; const timeout = 3000; -class ApplicationInsightsExporter implements SpanExporter { +class NewRelicExporter implements SpanExporter { private readonly _log: (message: string) => void; private _isShutdown = false; @@ -28,13 +28,7 @@ class ApplicationInsightsExporter implements SpanExporter { if (spans.length > 0) { const events = spans.map(s => this._spanToEvent(s)); - this._log( - `telemetry: ${JSON.stringify( - events.map(e => { - return { ...e, name: '*****', iKey: '*****' }; - }) - )}` - ); + this._log(`telemetry: ${JSON.stringify(events)}`); resultCallback(await this._send(events)); } @@ -50,49 +44,34 @@ class ApplicationInsightsExporter implements SpanExporter { private _spanToEvent(span: ReadableSpan): { [key: string]: any } { return { - name: `Microsoft.ApplicationInsights.Dev.${key}.Event`, - time: new Date(hrTimeToNanoseconds(span.startTime) / 1000000).toISOString(), - iKey: key, - tags: { - 'ai.application.ver': version, - 'ai.cloud.role': span.attributes['host'], - 'ai.internal.sdkVersion': 'replacetokens:2.0.0', - 'ai.operation.id': span.spanContext().traceId, - 'ai.operation.name': application, - 'ai.user.accountId': span.attributes['account'], - 'ai.user.authUserId': span.attributes['workflow'] - }, - data: { - baseType: 'EventData', - baseData: { - ver: '2', - name: 'tokens.replaced', - properties: { - ...span.attributes, - host: undefined, - account: undefined, - workflow: undefined, - result: (() => { - switch (span.status.code) { - case SpanStatusCode.ERROR: - return 'failed'; - case SpanStatusCode.OK: - return 'success'; - default: - return ''; - } - })(), - duration: hrTimeToMilliseconds(span.duration) - } + eventType: 'TokensReplaced', + application: application, + version: version, + ...span.attributes, + result: (() => { + switch (span.status.code) { + case SpanStatusCode.ERROR: + return 'failed'; + case SpanStatusCode.OK: + return 'success'; + default: + return ''; } - } + })(), + duration: hrTimeToMilliseconds(span.duration) }; } private async _send(data: any[]): Promise { try { - const options: axios.AxiosRequestConfig = { timeout: timeout }; - await axios.post(url, data, options); + const options: axios.AxiosRequestConfig = { + headers: { + 'Api-Key': key, + 'Content-Type': 'application/json' + }, + timeout: timeout + }; + await axios.post(endpoint, data, options); return { code: ExportResultCode.SUCCESS }; } catch (e) { @@ -109,7 +88,7 @@ export class TelemetryClient { private readonly _host: string; private readonly _os: string; - private _isApplicationInsightsExporterRegistered = false; + private _isEnabled = false; constructor(account?: string, workflow?: string, host?: string, os?: string) { this._provider = new BasicTracerProvider({ forceFlushTimeoutMillis: timeout }); @@ -128,14 +107,14 @@ export class TelemetryClient { startSpan(name: string): Span { return this._tracer.startSpan(name, { - attributes: { account: this._account, workflow: this._workflow, host: this._host, os: this._os } + attributes: { account: this._account, pipeline: this._workflow, host: this._host, os: this._os } }); } - useApplicationInsightsExporter(options: { log: (message: string) => void }) { - if (this._isApplicationInsightsExporterRegistered) return; + enableTelemetry(options: { log: (message: string) => void }) { + if (this._isEnabled) return; - this._provider.addSpanProcessor(new SimpleSpanProcessor(new ApplicationInsightsExporter(options.log))); - this._isApplicationInsightsExporterRegistered = true; + this._provider.addSpanProcessor(new SimpleSpanProcessor(new NewRelicExporter(options.log))); + this._isEnabled = true; } } diff --git a/tests/run.test.ts b/tests/run.test.ts index 96dbd66..838c902 100644 --- a/tests/run.test.ts +++ b/tests/run.test.ts @@ -246,7 +246,7 @@ describe('run', () => { expect(debugSpy).toHaveBeenCalledWith( expect.stringMatching( - /\[\{"name":"\*+","time":"[^"]+","iKey":"\*+","tags":\{"ai\.application\.ver":"1\.\d+\.\d+","ai\.cloud\.role":"server","ai\.internal\.sdkVersion":"replacetokens:2\.0\.0","ai\.operation\.id":"[^"]+","ai\.operation\.name":"replacetokens-action","ai\.user\.accountId":"c054bf9f6127dc352a184a29403ac9114f6c2a8e27cb467197cdfc1c3df119e4","ai\.user\.authUserId":"59830ebc3a4184110566bf1a290d08473dfdcbd492ce498b14cd1a5e2fa2e441"},"data":\{"baseType":"EventData","baseData":\{"ver":"2","name":"tokens\.replaced","properties":\{"os":"Windows","sources":3,"add-bom":false,"chars-to-escape":"","encoding":"auto","escape":"auto","escape-char":"","if-no-files-found":"ignore","log-level":"info","missing-var-action":"none","missing-var-default":"","missing-var-log":"warn","recusrive":false,"separator":"\.","token-pattern":"default","token-prefix":"","token-suffix":"","transforms":false,"transforms-prefix":"\(","transforms-suffix":"\)","variable-files":0,"variable-envs":0,"inline-variables":0,"output-defaults":1,"output-files":2,"output-replaced":3,"output-tokens":4,"output-transforms":5,"result":"success","duration":\d+(?:\.\d+)?}}}}]/ + /\[\{"eventType":"TokensReplaced","application":"replacetokens-action","version":"1\.\d+\.\d+","account":"c054bf9f6127dc352a184a29403ac9114f6c2a8e27cb467197cdfc1c3df119e4","pipeline":"59830ebc3a4184110566bf1a290d08473dfdcbd492ce498b14cd1a5e2fa2e441","host":"server","os":"Windows","sources":3,"add-bom":false,"chars-to-escape":"","encoding":"auto","escape":"auto","escape-char":"","if-no-files-found":"ignore","log-level":"info","missing-var-action":"none","missing-var-default":"","missing-var-log":"warn","recusrive":false,"separator":"\.","token-pattern":"default","token-prefix":"","token-suffix":"","transforms":false,"transforms-prefix":"\(","transforms-suffix":"\)","variable-files":0,"variable-envs":0,"inline-variables":0,"output-defaults":1,"output-files":2,"output-replaced":3,"output-tokens":4,"output-transforms":5,"result":"success","duration":\d+(?:\.\d+)?}]/ ) ); }); @@ -267,7 +267,7 @@ describe('run', () => { expect(debugSpy).toHaveBeenCalledWith( expect.stringMatching( - /\[\{"name":"\*+","time":"[^"]+","iKey":"\*+","tags":\{"ai\.application\.ver":"1\.\d+\.\d+","ai\.cloud\.role":"server","ai\.internal\.sdkVersion":"replacetokens:2\.0\.0","ai\.operation\.id":"[^"]+","ai\.operation\.name":"replacetokens-action","ai\.user\.accountId":"c054bf9f6127dc352a184a29403ac9114f6c2a8e27cb467197cdfc1c3df119e4","ai\.user\.authUserId":"59830ebc3a4184110566bf1a290d08473dfdcbd492ce498b14cd1a5e2fa2e441"},"data":\{"baseType":"EventData","baseData":\{"ver":"2","name":"tokens\.replaced","properties":\{"os":"Windows","result":"failed","duration":\d+(?:\.\d+)?}}}}]/ + /\[\{"eventType":"TokensReplaced","application":"replacetokens-action","version":"1\.\d+\.\d+","account":"c054bf9f6127dc352a184a29403ac9114f6c2a8e27cb467197cdfc1c3df119e4","pipeline":"59830ebc3a4184110566bf1a290d08473dfdcbd492ce498b14cd1a5e2fa2e441","host":"server","os":"Windows","result":"failed","duration":\d+(?:\.\d+)?}]/ ) ); });