@appland/telemetry 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/LICENSE.txt +25 -0
- package/README.md +64 -0
- package/dist/backends/application-insights.d.ts +8 -0
- package/dist/backends/application-insights.js +46 -0
- package/dist/backends/application-insights.js.map +1 -0
- package/dist/backends/splunk.d.ts +9 -0
- package/dist/backends/splunk.js +153 -0
- package/dist/backends/splunk.js.map +1 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.js +229 -0
- package/dist/client.js.map +1 -0
- package/dist/git.d.ts +34 -0
- package/dist/git.js +211 -0
- package/dist/git.js.map +1 -0
- package/dist/identity.d.ts +2 -0
- package/dist/identity.js +33 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/session.d.ts +16 -0
- package/dist/session.js +55 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +48 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# [@appland/telemetry-v1.1.0](https://github.com/getappmap/appmap-js/compare/@appland/telemetry-v1.0.0...@appland/telemetry-v1.1.0) (2025-10-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* `git status` is now run with the porcelain flag ([#1328](https://github.com/getappmap/appmap-js/issues/1328)) ([c16eb48](https://github.com/getappmap/appmap-js/commit/c16eb48c293d49c06c0c4a3bb91c9a070e991831))
|
|
7
|
+
* Don't hang when git is not found ([d2faa86](https://github.com/getappmap/appmap-js/commit/d2faa861b64b9ade63e729f894838fcf1efc8b2c))
|
|
8
|
+
* Include contributor counts in `scan` ([1c5de40](https://github.com/getappmap/appmap-js/commit/1c5de40410ae2e1794509fb29e9ba128eaac18c0))
|
|
9
|
+
* Include git contributor count in OpenAPI event ([4c9ee2c](https://github.com/getappmap/appmap-js/commit/4c9ee2c419d95ef0d09f5a12c90712bab890a8b7))
|
|
10
|
+
* Prevent `git status` from potentially hanging ([41f4a08](https://github.com/getappmap/appmap-js/commit/41f4a087d382e1f3ef7d942c4dd83df1cd75585f))
|
|
11
|
+
* Report git state ([a5d3797](https://github.com/getappmap/appmap-js/commit/a5d3797815b283ed114a57351067ed911ca36fa2))
|
|
12
|
+
* **telemetry:** Minor UX and correctness improvements in telemetry ([c41bfca](https://github.com/getappmap/appmap-js/commit/c41bfca46fd8897d828ba9fce51a883d873cfc1f))
|
|
13
|
+
* The Git proxy no longer alters the return type ([3c2be34](https://github.com/getappmap/appmap-js/commit/3c2be342dfc4548d96f7f3342b3146c058691143))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* Add event usage updates to `appmap index` ([dd5dfdb](https://github.com/getappmap/appmap-js/commit/dd5dfdb10c906546bf750a382a1387ccaf14df14))
|
|
19
|
+
* **cli:** Use a configurable telemetry endpoint ([3de5d9f](https://github.com/getappmap/appmap-js/commit/3de5d9f1a322e6414d80d41f124f2e1d8995cc06))
|
|
20
|
+
* Report env var names ([6264cb6](https://github.com/getappmap/appmap-js/commit/6264cb6c73927a90fc350bfb1531d3a8dd97df69))
|
|
21
|
+
* Send git repository URL in appmap:openapi telemetry ([61de641](https://github.com/getappmap/appmap-js/commit/61de641ae05bdfb60558cfd91b69a5a15a6f0c98))
|
|
22
|
+
* **telemetry:** Add an additional telemetry backend ([52d561e](https://github.com/getappmap/appmap-js/commit/52d561ea978f3369b3a6e59f9141debd1bf9bc46))
|
|
23
|
+
* **telemetry:** Release @appland/telemetry as a package ([e001e9b](https://github.com/getappmap/appmap-js/commit/e001e9b2516b0e3c3d130be2dbe71d98e1849da7))
|
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
The Software is provided to you by the Licensor under the License, as defined below, subject to the following condition.
|
|
2
|
+
|
|
3
|
+
Without limiting other conditions in the License, the grant of rights under the License will not include,
|
|
4
|
+
and the License does not grant to you, the right to Sell the Software.
|
|
5
|
+
|
|
6
|
+
For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you under the License to provide to third parties,
|
|
7
|
+
for a fee or other consideration (including without limitation fees for hosting or consulting/ support services related to the Software),
|
|
8
|
+
a product or service whose value derives, entirely or substantially, from the functionality of the Software.
|
|
9
|
+
Any license notice or attribution required by the License must also include this Commons Clause License Condition notice.
|
|
10
|
+
|
|
11
|
+
Software: @appland/telemetry
|
|
12
|
+
|
|
13
|
+
License: MIT License
|
|
14
|
+
|
|
15
|
+
Copyright 2025, AppLand Inc
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
|
18
|
+
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
19
|
+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
25
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# AppMap Telemetry
|
|
2
|
+
|
|
3
|
+
This package provides a shared telemetry client for AppMap projects. It supports multiple backends and offers flexible configuration options.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Telemetry } from '@appland/telemetry';
|
|
9
|
+
|
|
10
|
+
const telemetry = new Telemetry();
|
|
11
|
+
|
|
12
|
+
telemetry.configure({
|
|
13
|
+
product: {
|
|
14
|
+
name: 'My App',
|
|
15
|
+
version: '1.0.0',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
telemetry.sendEvent({
|
|
20
|
+
name: 'my-event',
|
|
21
|
+
properties: {
|
|
22
|
+
'my-property': 'my-value',
|
|
23
|
+
},
|
|
24
|
+
metrics: {
|
|
25
|
+
'my-metric': 123,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
The telemetry client can be configured using environment variables.
|
|
33
|
+
|
|
34
|
+
### General Configuration
|
|
35
|
+
|
|
36
|
+
* `APPMAP_TELEMETRY_DISABLED`: Set to `1`, `true`, or `yes` to disable telemetry.
|
|
37
|
+
* `APPMAP_TELEMETRY_DEBUG`: Set to `1`, `true`, or `yes` to enable debug logging, which will print telemetry events to the console.
|
|
38
|
+
* `APPMAP_TELEMETRY_BACKEND`: Specifies the telemetry backend to use. Supported values are `application-insights` (default) and `splunk`.
|
|
39
|
+
|
|
40
|
+
### Splunk Backend
|
|
41
|
+
|
|
42
|
+
When `APPMAP_TELEMETRY_BACKEND` is set to `splunk`, the following environment variables are used:
|
|
43
|
+
|
|
44
|
+
* `SPLUNK_TOKEN`: **(Required)** The Splunk HTTP Event Collector (HEC) token.
|
|
45
|
+
* `SPLUNK_URL`: **(Required)** The Splunk HEC URL.
|
|
46
|
+
* `SPLUNK_CA_CERT`: Used to configure TLS verification and custom Certificate Authorities (CAs).
|
|
47
|
+
* **Not set (default):** TLS verification is disabled (`rejectUnauthorized: false`). This allows the use of self-signed certificates, which is common in Splunk deployments.
|
|
48
|
+
* `system`: Use the system's trusted Certificate Authorities. TLS verification is enabled.
|
|
49
|
+
* `@/path/to/ca.pem`: Use the specified file as the Certificate Authority. The path must be prefixed with `@`. TLS verification is enabled.
|
|
50
|
+
* `<certificate content>`: Use the value of the environment variable as the Certificate Authority. TLS verification is enabled.
|
|
51
|
+
|
|
52
|
+
### Application Insights Backend
|
|
53
|
+
|
|
54
|
+
When `APPMAP_TELEMETRY_BACKEND` is set to `application-insights`, the client will use a default instrumentation key. This can be overridden by providing an `instrumentationKey` in the configuration:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
telemetry.configure({
|
|
58
|
+
// ...
|
|
59
|
+
backend: {
|
|
60
|
+
type: 'application-insights',
|
|
61
|
+
instrumentationKey: 'YOUR_INSTRUMENTATION_KEY',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ApplicationInsightsBackendConfiguration, FlushCallback, TelemetryBackend, TelemetryData } from '../types';
|
|
2
|
+
export declare class ApplicationInsightsBackend implements TelemetryBackend {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(userId: string, sessionId: string, productName: string, config: ApplicationInsightsBackendConfiguration);
|
|
6
|
+
sendEvent(event: TelemetryData): void;
|
|
7
|
+
flush(callback?: FlushCallback): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApplicationInsightsBackend = void 0;
|
|
4
|
+
const applicationinsights_1 = require("applicationinsights");
|
|
5
|
+
// This key is meant to be publically shared. However, I'm adding a simple
|
|
6
|
+
// obfuscation to mitigate key scraping bots on GitHub. The key is split on
|
|
7
|
+
// hypens and base64 encoded without padding.
|
|
8
|
+
// key.split('-').map((x) => x.toString('base64').replace(/=*/, ''))
|
|
9
|
+
const INSTRUMENTATION_KEY = ['NTBjMWE1YzI', 'NDliNA', 'NDkxMw', 'YjdjYw', 'ODZhNzhkNDA3NDVm']
|
|
10
|
+
.map((x) => Buffer.from(x, 'base64').toString('utf8'))
|
|
11
|
+
.join('-');
|
|
12
|
+
class ApplicationInsightsBackend {
|
|
13
|
+
constructor(userId, sessionId, productName, config) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
process.env.APPLICATION_INSIGHTS_NO_STATSBEAT = '1';
|
|
16
|
+
const instrumentationKey = this.config.instrumentationKey || INSTRUMENTATION_KEY;
|
|
17
|
+
// Disable everything we can, we don't any additional collection from Application Insights.
|
|
18
|
+
(0, applicationinsights_1.setup)(instrumentationKey)
|
|
19
|
+
.setAutoCollectRequests(false)
|
|
20
|
+
.setAutoCollectPerformance(false)
|
|
21
|
+
.setAutoCollectExceptions(false)
|
|
22
|
+
.setAutoCollectDependencies(false)
|
|
23
|
+
.setAutoCollectHeartbeat(false)
|
|
24
|
+
.setAutoDependencyCorrelation(false)
|
|
25
|
+
.setAutoCollectConsole(false)
|
|
26
|
+
.setInternalLogging(false, false)
|
|
27
|
+
.setSendLiveMetrics(false)
|
|
28
|
+
.setUseDiskRetryCaching(true);
|
|
29
|
+
const client = new applicationinsights_1.TelemetryClient(instrumentationKey);
|
|
30
|
+
client.context.tags[client.context.keys.userId] = userId;
|
|
31
|
+
client.context.tags[client.context.keys.sessionId] = sessionId;
|
|
32
|
+
client.context.tags[client.context.keys.cloudRole] = productName;
|
|
33
|
+
client.setAutoPopulateAzureProperties(false);
|
|
34
|
+
this.client = client;
|
|
35
|
+
}
|
|
36
|
+
sendEvent(event) {
|
|
37
|
+
this.client.trackEvent(event);
|
|
38
|
+
this.client.flush();
|
|
39
|
+
}
|
|
40
|
+
flush(callback) {
|
|
41
|
+
this.client.flush();
|
|
42
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.ApplicationInsightsBackend = ApplicationInsightsBackend;
|
|
46
|
+
//# sourceMappingURL=application-insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application-insights.js","sourceRoot":"","sources":["../../src/backends/application-insights.ts"],"names":[],"mappings":";;;AAMA,6DAAsF;AAEtF,0EAA0E;AAC1E,2EAA2E;AAC3E,6CAA6C;AAC7C,oEAAoE;AACpE,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,kBAAkB,CAAC;KAC1F,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;KACrD,IAAI,CAAC,GAAG,CAAC,CAAC;AAEb,MAAa,0BAA0B;IAGrC,YACE,MAAc,EACd,SAAiB,EACjB,WAAmB,EACF,MAA+C;QAA/C,WAAM,GAAN,MAAM,CAAyC;QAEhE,OAAO,CAAC,GAAG,CAAC,iCAAiC,GAAG,GAAG,CAAC;QAEpD,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,mBAAmB,CAAC;QACjF,2FAA2F;QAC3F,IAAA,2BAAW,EAAC,kBAAkB,CAAC;aAC5B,sBAAsB,CAAC,KAAK,CAAC;aAC7B,yBAAyB,CAAC,KAAK,CAAC;aAChC,wBAAwB,CAAC,KAAK,CAAC;aAC/B,0BAA0B,CAAC,KAAK,CAAC;aACjC,uBAAuB,CAAC,KAAK,CAAC;aAC9B,4BAA4B,CAAC,KAAK,CAAC;aACnC,qBAAqB,CAAC,KAAK,CAAC;aAC5B,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC;aAChC,kBAAkB,CAAC,KAAK,CAAC;aACzB,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEhC,MAAM,MAAM,GAAG,IAAI,qCAAM,CAAC,kBAAkB,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QACzD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC;QACjE,MAAM,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,SAAS,CAAC,KAAoB;QAC5B,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,QAAwB;QAC5B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,EAAI,CAAC;IACf,CAAC;CACF;AA3CD,gEA2CC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SplunkBackendConfiguration, TelemetryBackend, TelemetryData, FlushCallback } from '../types';
|
|
2
|
+
export declare class SplunkBackend implements TelemetryBackend {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private readonly httpAgent;
|
|
5
|
+
private pendingRequests;
|
|
6
|
+
constructor(config?: Partial<SplunkBackendConfiguration>);
|
|
7
|
+
sendEvent(event: TelemetryData): void;
|
|
8
|
+
flush(callback?: FlushCallback): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SplunkBackend = void 0;
|
|
37
|
+
const http = __importStar(require("node:http"));
|
|
38
|
+
const https = __importStar(require("node:https"));
|
|
39
|
+
const node_url_1 = require("node:url");
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const DefaultSplunkPath = '/services/collector/event';
|
|
42
|
+
const MaxFlushTime = 5000; // 5 seconds
|
|
43
|
+
class SplunkBackend {
|
|
44
|
+
constructor(config = {}) {
|
|
45
|
+
var _a, _b;
|
|
46
|
+
this.pendingRequests = 0;
|
|
47
|
+
const token = (_a = config.token) !== null && _a !== void 0 ? _a : process.env.SPLUNK_TOKEN;
|
|
48
|
+
const url = (_b = config.url) !== null && _b !== void 0 ? _b : process.env.SPLUNK_URL;
|
|
49
|
+
if (!token) {
|
|
50
|
+
throw new Error('SPLUNK_TOKEN is required');
|
|
51
|
+
}
|
|
52
|
+
if (!url) {
|
|
53
|
+
throw new Error('SPLUNK_URL is required');
|
|
54
|
+
}
|
|
55
|
+
this.config = {
|
|
56
|
+
type: 'splunk',
|
|
57
|
+
token: token,
|
|
58
|
+
url: url,
|
|
59
|
+
};
|
|
60
|
+
const parsedUrl = new node_url_1.URL(this.config.url);
|
|
61
|
+
const isHttps = parsedUrl.protocol === 'https:';
|
|
62
|
+
if (isHttps) {
|
|
63
|
+
const splunkCaCert = process.env.SPLUNK_CA_CERT;
|
|
64
|
+
let httpsAgentOptions = {
|
|
65
|
+
rejectUnauthorized: false, // Self-signed certs are common in Splunk
|
|
66
|
+
};
|
|
67
|
+
if (splunkCaCert) {
|
|
68
|
+
if (splunkCaCert === 'system') {
|
|
69
|
+
httpsAgentOptions = {
|
|
70
|
+
rejectUnauthorized: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else if (splunkCaCert.startsWith('@')) {
|
|
74
|
+
const caPath = splunkCaCert.substring(1);
|
|
75
|
+
httpsAgentOptions = {
|
|
76
|
+
rejectUnauthorized: true,
|
|
77
|
+
ca: fs.readFileSync(caPath),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
httpsAgentOptions = {
|
|
82
|
+
rejectUnauthorized: true,
|
|
83
|
+
ca: splunkCaCert,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this.httpAgent = new https.Agent(httpsAgentOptions);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
this.httpAgent = new http.Agent();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
sendEvent(event) {
|
|
94
|
+
this.pendingRequests++;
|
|
95
|
+
const parsedUrl = new node_url_1.URL(this.config.url);
|
|
96
|
+
const path = parsedUrl.pathname === '/' ? DefaultSplunkPath : parsedUrl.pathname;
|
|
97
|
+
const payload = JSON.stringify({ event });
|
|
98
|
+
const options = {
|
|
99
|
+
hostname: parsedUrl.hostname,
|
|
100
|
+
port: parsedUrl.port ? parseInt(parsedUrl.port, 10) : (parsedUrl.protocol === 'https:' ? 443 : 8088),
|
|
101
|
+
path: path,
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers: {
|
|
104
|
+
'Content-Type': 'application/json',
|
|
105
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
106
|
+
Authorization: `Splunk ${this.config.token}`,
|
|
107
|
+
},
|
|
108
|
+
agent: this.httpAgent,
|
|
109
|
+
};
|
|
110
|
+
const req = (parsedUrl.protocol === 'https:' ? https : http).request(options, (res) => {
|
|
111
|
+
let responseBody = '';
|
|
112
|
+
res.on('data', (chunk) => {
|
|
113
|
+
responseBody += chunk;
|
|
114
|
+
});
|
|
115
|
+
res.on('end', () => {
|
|
116
|
+
this.pendingRequests--;
|
|
117
|
+
if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {
|
|
118
|
+
console.warn(`SplunkBackend: Failed to send telemetry event. Status: ${res.statusCode}, Response: ${responseBody}`);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
req.on('error', (e) => {
|
|
123
|
+
this.pendingRequests--;
|
|
124
|
+
console.warn(`SplunkBackend: Connectivity error sending telemetry event: ${e.message}`);
|
|
125
|
+
});
|
|
126
|
+
req.write(payload);
|
|
127
|
+
req.end();
|
|
128
|
+
}
|
|
129
|
+
flush(callback) {
|
|
130
|
+
const startTime = process.hrtime.bigint();
|
|
131
|
+
const checkPending = () => {
|
|
132
|
+
if (this.pendingRequests === 0) {
|
|
133
|
+
if (callback) {
|
|
134
|
+
callback();
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const elapsedNs = process.hrtime.bigint() - startTime;
|
|
139
|
+
const elapsedMs = Number(elapsedNs / BigInt(1000000));
|
|
140
|
+
if (elapsedMs > MaxFlushTime) {
|
|
141
|
+
console.warn(`SplunkBackend: Flush timed out after ${MaxFlushTime}ms`);
|
|
142
|
+
if (callback) {
|
|
143
|
+
callback();
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
setTimeout(checkPending, 10); // Check again in 10ms
|
|
148
|
+
};
|
|
149
|
+
checkPending();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.SplunkBackend = SplunkBackend;
|
|
153
|
+
//# sourceMappingURL=splunk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"splunk.js","sourceRoot":"","sources":["../../src/backends/splunk.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FlushCallback, ITelemetryClient, TelemetryConfiguration, TelemetryData, TelemetryOptions } from './types';
|
|
2
|
+
export declare class TelemetryClient implements ITelemetryClient {
|
|
3
|
+
private telemetryConfig?;
|
|
4
|
+
private backend?;
|
|
5
|
+
private userConfig?;
|
|
6
|
+
debug: boolean;
|
|
7
|
+
private session?;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
readonly machineId: string;
|
|
10
|
+
get sessionId(): string;
|
|
11
|
+
constructor(config?: Partial<TelemetryConfiguration>);
|
|
12
|
+
configure(config?: Partial<TelemetryConfiguration>): void;
|
|
13
|
+
sendEvent(data: TelemetryData, options?: TelemetryOptions): void;
|
|
14
|
+
flush(callback?: FlushCallback): void;
|
|
15
|
+
}
|
|
16
|
+
declare const defaultClient: TelemetryClient;
|
|
17
|
+
export default defaultClient;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.TelemetryClient = void 0;
|
|
40
|
+
const conf_1 = __importDefault(require("conf"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const identity_1 = require("./identity");
|
|
43
|
+
const session_1 = require("./session");
|
|
44
|
+
const read_pkg_up_1 = require("read-pkg-up");
|
|
45
|
+
const path_1 = __importDefault(require("path"));
|
|
46
|
+
const application_insights_1 = require("./backends/application-insights");
|
|
47
|
+
const splunk_1 = require("./backends/splunk");
|
|
48
|
+
/**
|
|
49
|
+
* Append the prefix to the name of each property and drop undefined values
|
|
50
|
+
*/
|
|
51
|
+
const transformProps = (obj, propPrefix) => {
|
|
52
|
+
const result = {};
|
|
53
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
54
|
+
if (v === undefined)
|
|
55
|
+
continue;
|
|
56
|
+
if (k.includes('.')) {
|
|
57
|
+
result[k] = v;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const prefixedKey = k.startsWith(propPrefix) ? k : `${propPrefix}${k}`;
|
|
61
|
+
result[prefixedKey] = v;
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
function resolvePackageJson() {
|
|
66
|
+
var _a;
|
|
67
|
+
try {
|
|
68
|
+
let myPath = __dirname;
|
|
69
|
+
// If we're in a node_modules directory, go up to the consuming package root
|
|
70
|
+
const nodeModuleIndex = myPath.indexOf(`${path_1.default.sep}node_modules${path_1.default.sep}`);
|
|
71
|
+
if (nodeModuleIndex !== -1) {
|
|
72
|
+
myPath = myPath.substring(0, nodeModuleIndex);
|
|
73
|
+
}
|
|
74
|
+
const result = (_a = (0, read_pkg_up_1.sync)({ cwd: myPath })) === null || _a === void 0 ? void 0 : _a.packageJson;
|
|
75
|
+
if (result) {
|
|
76
|
+
return {
|
|
77
|
+
name: result.name,
|
|
78
|
+
version: result.version,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error('Error resolving package.json:', error);
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function defaultBackend() {
|
|
88
|
+
switch (process.env.APPMAP_TELEMETRY_BACKEND) {
|
|
89
|
+
case 'application-insights':
|
|
90
|
+
case 'splunk':
|
|
91
|
+
return {
|
|
92
|
+
type: process.env.APPMAP_TELEMETRY_BACKEND
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Default to application insights if no backend is specified
|
|
96
|
+
// or if the specified backend is not recognized.
|
|
97
|
+
// This is to maintain backward compatibility.
|
|
98
|
+
return { type: 'application-insights' };
|
|
99
|
+
}
|
|
100
|
+
function buildDefaultConfiguration(base = {}) {
|
|
101
|
+
const product = Object.assign({ name: '', version: '' }, base.product);
|
|
102
|
+
if (!product.name || !product.version) {
|
|
103
|
+
const pkg = resolvePackageJson();
|
|
104
|
+
product.name || (product.name = (pkg === null || pkg === void 0 ? void 0 : pkg.name) || 'unknown');
|
|
105
|
+
product.version || (product.version = (pkg === null || pkg === void 0 ? void 0 : pkg.version) || '0.0.0');
|
|
106
|
+
}
|
|
107
|
+
// By default, the prop prefix will be the product name with non-word characters replaced by dots.
|
|
108
|
+
const propPrefix = base.propPrefix || product.name.replace(/\W/g, '.').replace(/^\./, '') + '.';
|
|
109
|
+
return Object.assign({ product,
|
|
110
|
+
propPrefix, backend: defaultBackend() }, base);
|
|
111
|
+
}
|
|
112
|
+
/** Interpret a boolean as coming from an environment variable.
|
|
113
|
+
* If the value is undefined, return the defaultValue.
|
|
114
|
+
* If the value is '1', 'true', or 'yes' (case insensitive), return true.
|
|
115
|
+
* If the value is '0', 'false', or 'no' (case insensitive), return false.
|
|
116
|
+
* Otherwise, return the defaultValue.
|
|
117
|
+
*/
|
|
118
|
+
function stringToBool(value, defaultValue = false) {
|
|
119
|
+
if (value === undefined)
|
|
120
|
+
return defaultValue;
|
|
121
|
+
switch (value.toLowerCase()) {
|
|
122
|
+
case '1':
|
|
123
|
+
case 'true':
|
|
124
|
+
case 'yes':
|
|
125
|
+
return true;
|
|
126
|
+
case '0':
|
|
127
|
+
case 'false':
|
|
128
|
+
case 'no':
|
|
129
|
+
return false;
|
|
130
|
+
default:
|
|
131
|
+
return defaultValue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
class TelemetryClient {
|
|
135
|
+
get sessionId() {
|
|
136
|
+
if (!this.session) {
|
|
137
|
+
throw new Error('Session is not initialized');
|
|
138
|
+
}
|
|
139
|
+
return this.session.id;
|
|
140
|
+
}
|
|
141
|
+
constructor(config) {
|
|
142
|
+
this.debug = stringToBool(process.env.APPMAP_TELEMETRY_DEBUG);
|
|
143
|
+
this.enabled = !stringToBool(process.env.APPMAP_TELEMETRY_DISABLED);
|
|
144
|
+
this.machineId = (0, identity_1.getMachineId)();
|
|
145
|
+
if (config)
|
|
146
|
+
this.configure(config);
|
|
147
|
+
}
|
|
148
|
+
configure(config = {}) {
|
|
149
|
+
if (this.telemetryConfig) {
|
|
150
|
+
throw new Error('Telemetry client is already configured');
|
|
151
|
+
}
|
|
152
|
+
this.telemetryConfig = buildDefaultConfiguration(config);
|
|
153
|
+
this.userConfig = new conf_1.default({
|
|
154
|
+
projectName: this.telemetryConfig.product.name,
|
|
155
|
+
projectVersion: '0.0.1', // note this is actually config version
|
|
156
|
+
});
|
|
157
|
+
this.session = new session_1.Session(this.userConfig);
|
|
158
|
+
// Construct additional backends here as needed.
|
|
159
|
+
switch (this.telemetryConfig.backend.type) {
|
|
160
|
+
case 'application-insights':
|
|
161
|
+
this.backend = new application_insights_1.ApplicationInsightsBackend(this.machineId, this.session.id, this.telemetryConfig.product.name, this.telemetryConfig.backend);
|
|
162
|
+
break;
|
|
163
|
+
case 'custom':
|
|
164
|
+
this.backend = this.telemetryConfig.backend;
|
|
165
|
+
break;
|
|
166
|
+
case 'splunk':
|
|
167
|
+
this.backend = new splunk_1.SplunkBackend(this.telemetryConfig.backend);
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
if (this.debug) {
|
|
171
|
+
console.warn('Telemetry configuration:', this.telemetryConfig);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
sendEvent(data, options = { includeEnvironment: false }) {
|
|
175
|
+
if (!this.backend)
|
|
176
|
+
this.configure();
|
|
177
|
+
if (!this.backend || !this.telemetryConfig || !this.session)
|
|
178
|
+
throw new Error('Telemetry client is not configured');
|
|
179
|
+
try {
|
|
180
|
+
const { propPrefix } = this.telemetryConfig;
|
|
181
|
+
const { name, version } = this.telemetryConfig.product;
|
|
182
|
+
const transformedProperties = transformProps(Object.assign({ version: version, args: process.argv.slice(1).join(' ') }, data.properties), propPrefix);
|
|
183
|
+
const transformedMetrics = transformProps(data.metrics || {}, propPrefix);
|
|
184
|
+
const properties = Object.assign({ 'common.source': name, 'common.os': os.platform(), 'common.platformversion': os.release(), 'common.arch': os.arch(), 'appmap.cli.machineId': this.machineId, 'appmap.cli.sessionId': this.session.id }, transformedProperties);
|
|
185
|
+
if (options.includeEnvironment) {
|
|
186
|
+
properties['common.environmentVariables'] = Object.keys(process.env).sort().join(',');
|
|
187
|
+
}
|
|
188
|
+
const event = {
|
|
189
|
+
name: `${name}/${data.name}`,
|
|
190
|
+
measurements: transformedMetrics,
|
|
191
|
+
properties,
|
|
192
|
+
};
|
|
193
|
+
if (this.debug) {
|
|
194
|
+
console.warn(JSON.stringify(event, null, 2));
|
|
195
|
+
}
|
|
196
|
+
if (this.enabled) {
|
|
197
|
+
this.backend.sendEvent(event);
|
|
198
|
+
this.session.touch();
|
|
199
|
+
this.backend.flush();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
// Don't let telemetry fail the entire command
|
|
204
|
+
// Do nothing other than log for now, we can't do anything about it
|
|
205
|
+
if (this.debug) {
|
|
206
|
+
if (e instanceof Error) {
|
|
207
|
+
console.error(e.stack);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
console.error(e);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
flush(callback) {
|
|
216
|
+
var _a;
|
|
217
|
+
if (this.enabled) {
|
|
218
|
+
(_a = this.backend) === null || _a === void 0 ? void 0 : _a.flush(callback);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (callback)
|
|
222
|
+
callback();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.TelemetryClient = TelemetryClient;
|
|
227
|
+
const defaultClient = new TelemetryClient();
|
|
228
|
+
exports.default = defaultClient;
|
|
229
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { PathLike } from 'fs';
|
|
2
|
+
export declare enum GitState {
|
|
3
|
+
NotInstalled = 0,// The git cli was not found.
|
|
4
|
+
NoRepository = 1,// Git is installed but no repository was found.
|
|
5
|
+
Ok = 2
|
|
6
|
+
}
|
|
7
|
+
export declare const GitRepositoryEnvKeys: readonly ["GITHUB_REPOSITORY", "CIRCLE_REPOSITORY_URL", "GIT_URL", "CI_REPOSITORY_URL"];
|
|
8
|
+
export declare const GitBranchEnvKeys: readonly ["GITHUB_REF_NAME", "CIRCLE_BRANCH", "GIT_BRANCH", "TRAVIS_BRANCH", "CI_COMMIT_REF_NAME"];
|
|
9
|
+
export declare const GitCommitEnvKeys: readonly ["GITHUB_SHA", "CIRCLE_SHA1", "GIT_COMMIT", "TRAVIS_COMMIT", "CI_COMMIT_SHA"];
|
|
10
|
+
/**
|
|
11
|
+
* This is a wrapper around `execFile` that returns a promise containing the stdout. `execFile` will
|
|
12
|
+
* not spawn a shell, so it is less likely to be vulnerable to shell injection attacks.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} command - The command to execute. This should be resolvable via `PATH`, and contain no arguments.
|
|
15
|
+
* @param {string[]} args - The arguments to pass to the command.
|
|
16
|
+
* @param {object} [options] - Options to pass to `execFile`.
|
|
17
|
+
* @returns {Promise<string>} A promise containing the stdout of the command.
|
|
18
|
+
* @throws {Error} If the command fails with a non-zero (or anything other than the specified) exit code.
|
|
19
|
+
*/
|
|
20
|
+
export declare const execute: (command: string, args: string[], options?: {
|
|
21
|
+
cwd?: string;
|
|
22
|
+
exitCode?: number;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
}) => Promise<string>;
|
|
25
|
+
declare class GitProperties {
|
|
26
|
+
static contributors(sinceDaysAgo: number, cwd?: PathLike): Promise<Array<string>>;
|
|
27
|
+
static repository(cwd?: PathLike): Promise<string | undefined>;
|
|
28
|
+
static branch(cwd?: PathLike): Promise<string | undefined>;
|
|
29
|
+
static commit(cwd?: PathLike): Promise<string | undefined>;
|
|
30
|
+
static state(cwd?: PathLike): Promise<GitState>;
|
|
31
|
+
static clearCache(): void;
|
|
32
|
+
}
|
|
33
|
+
export declare const Git: typeof GitProperties;
|
|
34
|
+
export {};
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.Git = exports.execute = exports.GitCommitEnvKeys = exports.GitBranchEnvKeys = exports.GitRepositoryEnvKeys = exports.GitState = void 0;
|
|
13
|
+
const child_process_1 = require("child_process");
|
|
14
|
+
var GitState;
|
|
15
|
+
(function (GitState) {
|
|
16
|
+
GitState[GitState["NotInstalled"] = 0] = "NotInstalled";
|
|
17
|
+
GitState[GitState["NoRepository"] = 1] = "NoRepository";
|
|
18
|
+
GitState[GitState["Ok"] = 2] = "Ok";
|
|
19
|
+
})(GitState || (exports.GitState = GitState = {}));
|
|
20
|
+
exports.GitRepositoryEnvKeys = [
|
|
21
|
+
'GITHUB_REPOSITORY', // GitHub
|
|
22
|
+
'CIRCLE_REPOSITORY_URL', // CircleCI
|
|
23
|
+
'GIT_URL', // Jenkins
|
|
24
|
+
'CI_REPOSITORY_URL', // GitLab
|
|
25
|
+
];
|
|
26
|
+
exports.GitBranchEnvKeys = [
|
|
27
|
+
'GITHUB_REF_NAME', // GitHub
|
|
28
|
+
'CIRCLE_BRANCH', // CircleCI
|
|
29
|
+
'GIT_BRANCH', // Jenkins
|
|
30
|
+
'TRAVIS_BRANCH', // TravisCI
|
|
31
|
+
'CI_COMMIT_REF_NAME', // GitLab
|
|
32
|
+
];
|
|
33
|
+
exports.GitCommitEnvKeys = [
|
|
34
|
+
'GITHUB_SHA', // GitHub
|
|
35
|
+
'CIRCLE_SHA1', // CircleCI
|
|
36
|
+
'GIT_COMMIT', // Jenkins
|
|
37
|
+
'TRAVIS_COMMIT', // TravisCI
|
|
38
|
+
'CI_COMMIT_SHA', // GitLab
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* This is a wrapper around `execFile` that returns a promise containing the stdout. `execFile` will
|
|
42
|
+
* not spawn a shell, so it is less likely to be vulnerable to shell injection attacks.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} command - The command to execute. This should be resolvable via `PATH`, and contain no arguments.
|
|
45
|
+
* @param {string[]} args - The arguments to pass to the command.
|
|
46
|
+
* @param {object} [options] - Options to pass to `execFile`.
|
|
47
|
+
* @returns {Promise<string>} A promise containing the stdout of the command.
|
|
48
|
+
* @throws {Error} If the command fails with a non-zero (or anything other than the specified) exit code.
|
|
49
|
+
*/
|
|
50
|
+
const execute = (command, args, options) => new Promise((resolve, reject) => {
|
|
51
|
+
var _a, _b, _c, _d;
|
|
52
|
+
const child = (0, child_process_1.execFile)(command, args, Object.assign({}, (options !== null && options !== void 0 ? options : {})));
|
|
53
|
+
let stdout = '';
|
|
54
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.setEncoding('utf8');
|
|
55
|
+
(_b = child.stdout) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
56
|
+
stdout += data.toString();
|
|
57
|
+
});
|
|
58
|
+
let stderr = '';
|
|
59
|
+
(_c = child.stderr) === null || _c === void 0 ? void 0 : _c.setEncoding('utf8');
|
|
60
|
+
(_d = child.stderr) === null || _d === void 0 ? void 0 : _d.on('data', (data) => {
|
|
61
|
+
stderr += data.toString();
|
|
62
|
+
});
|
|
63
|
+
child.on('close', (code) => {
|
|
64
|
+
var _a;
|
|
65
|
+
if (code === ((_a = options === null || options === void 0 ? void 0 : options.exitCode) !== null && _a !== void 0 ? _a : 0))
|
|
66
|
+
resolve(stdout);
|
|
67
|
+
else
|
|
68
|
+
reject(new Error(stderr));
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
exports.execute = execute;
|
|
72
|
+
class GitProperties {
|
|
73
|
+
static contributors(sinceDaysAgo, cwd) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
const unixTimeNow = Math.floor(Number(new Date()) / 1000);
|
|
76
|
+
const unixTimeAgo = unixTimeNow - sinceDaysAgo * 24 * 60 * 60;
|
|
77
|
+
try {
|
|
78
|
+
const args = ['--no-pager', 'log', `--since=${unixTimeAgo}`, '--format="%ae"'];
|
|
79
|
+
if (cwd)
|
|
80
|
+
args.unshift('-C', cwd.toString());
|
|
81
|
+
const stdout = yield (0, exports.execute)('git', args);
|
|
82
|
+
return [
|
|
83
|
+
...stdout
|
|
84
|
+
.trim()
|
|
85
|
+
.split('\n')
|
|
86
|
+
.reduce((acc, email) => {
|
|
87
|
+
acc.add(email);
|
|
88
|
+
return acc;
|
|
89
|
+
}, new Set()),
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
catch (_a) {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Returns the repository URL, first by checking the environment, then by
|
|
98
|
+
// shelling out to git.
|
|
99
|
+
static repository(cwd) {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
const envKey = exports.GitRepositoryEnvKeys.find((key) => process.env[key]);
|
|
102
|
+
if (envKey)
|
|
103
|
+
return process.env[envKey];
|
|
104
|
+
try {
|
|
105
|
+
const args = ['config', '--get', 'remote.origin.url'];
|
|
106
|
+
if (cwd)
|
|
107
|
+
args.unshift('-C', cwd.toString());
|
|
108
|
+
const stdout = yield (0, exports.execute)('git', args);
|
|
109
|
+
return stdout.trim();
|
|
110
|
+
}
|
|
111
|
+
catch (_a) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Returns the branch, first by checking the environment, then by
|
|
117
|
+
// shelling out to git.
|
|
118
|
+
static branch(cwd) {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const envKey = exports.GitBranchEnvKeys.find((key) => process.env[key]);
|
|
121
|
+
if (envKey)
|
|
122
|
+
return process.env[envKey];
|
|
123
|
+
try {
|
|
124
|
+
const args = ['rev-parse', '--abbrev-ref', 'HEAD'];
|
|
125
|
+
if (cwd)
|
|
126
|
+
args.unshift('-C', cwd.toString());
|
|
127
|
+
const stdout = yield (0, exports.execute)('git', args);
|
|
128
|
+
return stdout.trim();
|
|
129
|
+
}
|
|
130
|
+
catch (_a) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// Returns the commit SHA, first by checking the environment, then by
|
|
136
|
+
// shelling out to git.
|
|
137
|
+
static commit(cwd) {
|
|
138
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
139
|
+
const envKey = exports.GitCommitEnvKeys.find((key) => process.env[key]);
|
|
140
|
+
if (envKey)
|
|
141
|
+
return process.env[envKey];
|
|
142
|
+
try {
|
|
143
|
+
const args = ['rev-parse', 'HEAD'];
|
|
144
|
+
if (cwd)
|
|
145
|
+
args.unshift('-C', cwd.toString());
|
|
146
|
+
const stdout = yield (0, exports.execute)('git', args);
|
|
147
|
+
return stdout.trim();
|
|
148
|
+
}
|
|
149
|
+
catch (_a) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
static state(cwd) {
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
try {
|
|
158
|
+
const commandProcess = (0, child_process_1.spawn)('git', ['status', '--porcelain'], {
|
|
159
|
+
shell: true,
|
|
160
|
+
cwd: cwd === null || cwd === void 0 ? void 0 : cwd.toString(),
|
|
161
|
+
stdio: 'ignore',
|
|
162
|
+
timeout: 2000,
|
|
163
|
+
});
|
|
164
|
+
commandProcess.on('exit', (code) => {
|
|
165
|
+
switch (code) {
|
|
166
|
+
case 127:
|
|
167
|
+
return resolve(GitState.NotInstalled);
|
|
168
|
+
case 128:
|
|
169
|
+
return resolve(GitState.NoRepository);
|
|
170
|
+
default:
|
|
171
|
+
return resolve(GitState.Ok);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
commandProcess.on('error', () => resolve(GitState.NotInstalled));
|
|
175
|
+
}
|
|
176
|
+
catch (_a) {
|
|
177
|
+
resolve(GitState.NotInstalled);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
static clearCache() {
|
|
183
|
+
gitCache.clear();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const gitCache = new Map();
|
|
187
|
+
const noCacheList = ['clearCache'];
|
|
188
|
+
// GitProperties is available externally as Git.
|
|
189
|
+
// This export provides a simple caching layer around GitProperties to avoid
|
|
190
|
+
// excessive shelling out to git.
|
|
191
|
+
exports.Git = new Proxy(GitProperties, {
|
|
192
|
+
get(target, prop) {
|
|
193
|
+
if (!noCacheList.includes(prop.toString()) &&
|
|
194
|
+
typeof target[prop] === 'function') {
|
|
195
|
+
return new Proxy(target[prop], {
|
|
196
|
+
apply(target, thisArg, argArray) {
|
|
197
|
+
const cacheKey = `${prop.toString()}(${JSON.stringify(argArray)})`;
|
|
198
|
+
if (gitCache.has(cacheKey)) {
|
|
199
|
+
return gitCache.get(cacheKey);
|
|
200
|
+
}
|
|
201
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-function-type */
|
|
202
|
+
const result = Reflect.apply(target, thisArg, argArray);
|
|
203
|
+
gitCache.set(cacheKey, result);
|
|
204
|
+
return result;
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return Reflect.get(target, prop);
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMachineId = getMachineId;
|
|
4
|
+
const os_1 = require("os");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
const invalidMacAddresses = new Set([
|
|
7
|
+
'00:00:00:00:00:00',
|
|
8
|
+
'ff:ff:ff:ff:ff:ff',
|
|
9
|
+
'ac:de:48:00:11:22',
|
|
10
|
+
]);
|
|
11
|
+
function getMachineId(config) {
|
|
12
|
+
const machineId = config === null || config === void 0 ? void 0 : config.get('machineId');
|
|
13
|
+
if (machineId) {
|
|
14
|
+
return machineId;
|
|
15
|
+
}
|
|
16
|
+
let machineIdSource;
|
|
17
|
+
// Derive a machine ID from the first network interface
|
|
18
|
+
machineIdSource = Object.values((0, os_1.networkInterfaces)())
|
|
19
|
+
.flat()
|
|
20
|
+
.map((iface) => iface === null || iface === void 0 ? void 0 : iface.mac)
|
|
21
|
+
.filter((mac) => mac && !invalidMacAddresses.has(mac))
|
|
22
|
+
.shift();
|
|
23
|
+
if (!machineIdSource) {
|
|
24
|
+
// Fallback to a random string
|
|
25
|
+
machineIdSource = (0, crypto_1.randomBytes)(32);
|
|
26
|
+
}
|
|
27
|
+
const machineIdHash = (0, crypto_1.createHash)('sha256')
|
|
28
|
+
.update(machineIdSource)
|
|
29
|
+
.digest('hex');
|
|
30
|
+
config === null || config === void 0 ? void 0 : config.set('machineId', machineIdHash);
|
|
31
|
+
return machineIdHash;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":";;AAUA,oCA2BC;AArCD,2BAAuC;AACvC,mCAA6D;AAG7D,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;CACpB,CAAC,CAAC;AAEH,SAAgB,YAAY,CAAC,MAAa;IACxC,MAAM,SAAS,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,GAAG,CAAC,WAAW,CAAuB,CAAC;IACjE,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,eAAuC,CAAC;IAE5C,uDAAuD;IACvD,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,IAAA,sBAAiB,GAAE,CAAC;SACjD,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,GAAG,CAAC;SAC1B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SACrD,KAAK,EAAE,CAAC;IAEX,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,8BAA8B;QAC9B,eAAe,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,aAAa,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC;SACvC,MAAM,CAAC,eAA6B,CAAC;SACrC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjB,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAExC,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.Telemetry = void 0;
|
|
21
|
+
var client_1 = require("./client");
|
|
22
|
+
Object.defineProperty(exports, "Telemetry", { enumerable: true, get: function () { return __importDefault(client_1).default; } });
|
|
23
|
+
__exportStar(require("./types"), exports);
|
|
24
|
+
__exportStar(require("./client"), exports);
|
|
25
|
+
__exportStar(require("./git"), exports);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,mCAAgD;AAAvC,oHAAA,OAAO,OAAa;AAC7B,0CAAwB;AACxB,2CAAyB;AACzB,wCAAsB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type Conf from 'conf';
|
|
2
|
+
export declare class Session {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private _id?;
|
|
5
|
+
private _expiration?;
|
|
6
|
+
get id(): string;
|
|
7
|
+
get expiration(): number;
|
|
8
|
+
get valid(): boolean;
|
|
9
|
+
constructor(config: Conf);
|
|
10
|
+
static beyondExpiration(expiration: number): boolean;
|
|
11
|
+
static expirationFromNow(): number;
|
|
12
|
+
static newSessionId(): string;
|
|
13
|
+
private load;
|
|
14
|
+
renew(): void;
|
|
15
|
+
touch(): void;
|
|
16
|
+
}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Session = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const SESSION_EXPIRATION = 1000 * 60 * 30; // 30 minutes
|
|
6
|
+
class Session {
|
|
7
|
+
get id() {
|
|
8
|
+
if (!this.valid)
|
|
9
|
+
this.renew();
|
|
10
|
+
if (!this._id)
|
|
11
|
+
throw new Error('Session ID is not set');
|
|
12
|
+
return this._id;
|
|
13
|
+
}
|
|
14
|
+
get expiration() {
|
|
15
|
+
if (!this.valid)
|
|
16
|
+
this.renew();
|
|
17
|
+
if (!this._expiration)
|
|
18
|
+
throw new Error('Session expiration is not set');
|
|
19
|
+
return this._expiration;
|
|
20
|
+
}
|
|
21
|
+
get valid() {
|
|
22
|
+
return (this._id !== undefined &&
|
|
23
|
+
this._expiration !== undefined &&
|
|
24
|
+
!Session.beyondExpiration(this._expiration));
|
|
25
|
+
}
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.config = config;
|
|
28
|
+
this.load();
|
|
29
|
+
}
|
|
30
|
+
static beyondExpiration(expiration) {
|
|
31
|
+
return expiration <= Date.now();
|
|
32
|
+
}
|
|
33
|
+
static expirationFromNow() {
|
|
34
|
+
return Date.now() + SESSION_EXPIRATION;
|
|
35
|
+
}
|
|
36
|
+
static newSessionId() {
|
|
37
|
+
return (0, crypto_1.createHash)('sha256').update((0, crypto_1.randomBytes)(32)).digest('hex');
|
|
38
|
+
}
|
|
39
|
+
load() {
|
|
40
|
+
this._id = this.config.get('sessionId');
|
|
41
|
+
this._expiration = this.config.get('sessionExpiration');
|
|
42
|
+
}
|
|
43
|
+
renew() {
|
|
44
|
+
this._id = Session.newSessionId();
|
|
45
|
+
this._expiration = Session.expirationFromNow();
|
|
46
|
+
this.config.set('sessionId', this._id);
|
|
47
|
+
this.config.set('sessionExpiration', this._expiration);
|
|
48
|
+
}
|
|
49
|
+
touch() {
|
|
50
|
+
this._expiration = Session.expirationFromNow();
|
|
51
|
+
this.config.set('sessionExpiration', this.expiration);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.Session = Session;
|
|
55
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":";;;AACA,mCAAiD;AAEjD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,aAAa;AAExD,MAAa,OAAO;IAIlB,IAAI,EAAE;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,IAAI,UAAU;QACZ,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,CACL,IAAI,CAAC,GAAG,KAAK,SAAS;YACtB,IAAI,CAAC,WAAW,KAAK,SAAS;YAC9B,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAC5C,CAAC;IACJ,CAAC;IAED,YAA6B,MAAY;QAAZ,WAAM,GAAN,MAAM,CAAM;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,MAAM,CAAC,gBAAgB,CAAC,UAAkB;QACxC,OAAO,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,iBAAiB;QACtB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,YAAY;QACjB,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAuB,CAAC;QAC9D,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAuB,CAAC;IAChF,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACxD,CAAC;CACF;AAxDD,0BAwDC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface TelemetryData {
|
|
2
|
+
name: string;
|
|
3
|
+
properties?: Record<string, string | undefined>;
|
|
4
|
+
metrics?: Record<string, number | undefined>;
|
|
5
|
+
}
|
|
6
|
+
export interface TelemetryOptions {
|
|
7
|
+
includeEnvironment: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type FlushCallback = () => void;
|
|
10
|
+
export interface ITelemetryClient {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
machineId: Readonly<string>;
|
|
13
|
+
sessionId: Readonly<string>;
|
|
14
|
+
configure(config: Partial<TelemetryConfiguration>): void;
|
|
15
|
+
sendEvent(data: TelemetryData, options?: TelemetryOptions): void;
|
|
16
|
+
flush(callback?: FlushCallback): void;
|
|
17
|
+
}
|
|
18
|
+
export interface TelemetryBackend {
|
|
19
|
+
sendEvent(event: TelemetryData): void;
|
|
20
|
+
flush(callback?: FlushCallback): void;
|
|
21
|
+
}
|
|
22
|
+
export type BaseBackendConfiguration = {
|
|
23
|
+
type: string;
|
|
24
|
+
};
|
|
25
|
+
export type ProductConfiguration = {
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
};
|
|
29
|
+
export interface TelemetryConfiguration {
|
|
30
|
+
product: ProductConfiguration;
|
|
31
|
+
propPrefix: string;
|
|
32
|
+
backend: BackendConfiguration;
|
|
33
|
+
}
|
|
34
|
+
export interface SplunkBackendConfiguration extends BaseBackendConfiguration {
|
|
35
|
+
type: 'splunk';
|
|
36
|
+
token?: string;
|
|
37
|
+
url?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ApplicationInsightsBackendConfiguration extends BaseBackendConfiguration {
|
|
40
|
+
type: 'application-insights';
|
|
41
|
+
instrumentationKey?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface CustomBackendConfiguration extends BaseBackendConfiguration, TelemetryBackend {
|
|
44
|
+
type: 'custom';
|
|
45
|
+
sendEvent: (event: TelemetryData) => void;
|
|
46
|
+
flush: (callback?: FlushCallback) => void;
|
|
47
|
+
}
|
|
48
|
+
export type BackendConfiguration = CustomBackendConfiguration | ApplicationInsightsBackendConfiguration | SplunkBackendConfiguration;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@appland/telemetry",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "jest",
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"lint": "eslint src --ext .ts",
|
|
9
|
+
"pre-commit": "lint-staged"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"package.json",
|
|
16
|
+
"LICENSE.txt"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"lint-staged": {
|
|
22
|
+
"**/*": "prettier --write --ignore-unknown"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"applicationinsights": "^2.1.4",
|
|
26
|
+
"conf": "<11",
|
|
27
|
+
"read-pkg-up": "^7.0.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/jest": "^29.4.1",
|
|
31
|
+
"@types/node": "^22",
|
|
32
|
+
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
33
|
+
"@typescript-eslint/parser": "^8.38.0",
|
|
34
|
+
"eslint": "^9.32.0",
|
|
35
|
+
"eslint-config-prettier": "^10.1.8",
|
|
36
|
+
"jest": "^29.5.0",
|
|
37
|
+
"lint-staged": "^10.5.4",
|
|
38
|
+
"prettier": "^2.7.1",
|
|
39
|
+
"sinon": "^13.0.1",
|
|
40
|
+
"ts-jest": "^29.0.5",
|
|
41
|
+
"typescript": "^5.8.3"
|
|
42
|
+
}
|
|
43
|
+
}
|