@evenicanpm/common-core 1.2.0 → 1.3.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/package.json +14 -3
- package/src/lib/index.ts +1 -0
- package/{keyvault.ts → src/lib/keyvault.ts} +4 -4
- package/src/otel/README.md +44 -0
- package/src/otel/logger.ts +54 -0
- package/src/otel/setup.ts +99 -0
- package/tsconfig.json +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evenicanpm/common-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Common module for Headless Storefront and Admin panel",
|
|
5
5
|
"author": "Evenica",
|
|
6
6
|
"type": "module",
|
|
@@ -10,10 +10,21 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@azure/identity": "^4.10.1",
|
|
13
|
-
"@azure/keyvault-secrets": "^4.10.0"
|
|
13
|
+
"@azure/keyvault-secrets": "^4.10.0",
|
|
14
|
+
"@azure/monitor-opentelemetry-exporter": "^1.0.0-beta.32",
|
|
15
|
+
"@opentelemetry/api": "^1.9.0",
|
|
16
|
+
"@opentelemetry/api-logs": "^0.206.0",
|
|
17
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.206.0",
|
|
18
|
+
"@opentelemetry/host-metrics": "^0.36.2",
|
|
19
|
+
"@opentelemetry/sdk-logs": "^0.206.0",
|
|
20
|
+
"@opentelemetry/sdk-metrics": "^2.1.0",
|
|
21
|
+
"@opentelemetry/sdk-trace-node": "^2.1.0",
|
|
22
|
+
"@strapi/client": "^1.5.0",
|
|
23
|
+
"@vercel/otel": "^2.0.1",
|
|
24
|
+
"strapi-sdk-js": "^3.0.0"
|
|
14
25
|
},
|
|
15
26
|
"devDependencies": {
|
|
16
27
|
"@types/node": "^24.0.13"
|
|
17
28
|
},
|
|
18
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "074f33378006dfc21ceb49456806a18dbb6e91ad"
|
|
19
30
|
}
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./keyvault";
|
|
@@ -7,7 +7,7 @@ const vaultEndpoint = process.env.KEYVAULT_ENDPOINT;
|
|
|
7
7
|
const url = `https://${vaultName}.${vaultEndpoint}`;
|
|
8
8
|
|
|
9
9
|
// Initialize local secrets cache object
|
|
10
|
-
|
|
10
|
+
const secrets = new Map();
|
|
11
11
|
|
|
12
12
|
// A Key and Secret class to Cache Secrets
|
|
13
13
|
class Secret {
|
|
@@ -27,11 +27,11 @@ class Secret {
|
|
|
27
27
|
* set all secrets in the "secrets" map binding which is exported from this module.
|
|
28
28
|
*/
|
|
29
29
|
const initializeKeyVaultCache = async () => {
|
|
30
|
-
if (process.env.NODE_ENV
|
|
30
|
+
if (process.env.NODE_ENV === "production") {
|
|
31
31
|
const credential = new DefaultAzureCredential();
|
|
32
32
|
const client = new SecretClient(url, credential);
|
|
33
33
|
|
|
34
|
-
for await (
|
|
34
|
+
for await (const secretProperties of client.listPropertiesOfSecrets()) {
|
|
35
35
|
const result = await client.getSecret(secretProperties.name);
|
|
36
36
|
secrets.set(
|
|
37
37
|
secretProperties.name,
|
|
@@ -48,7 +48,7 @@ const initializeKeyVaultCache = async () => {
|
|
|
48
48
|
* @returns Returns the secret string.
|
|
49
49
|
*/
|
|
50
50
|
const getSecret = (key: string): string | undefined => {
|
|
51
|
-
if (process.env.NODE_ENV
|
|
51
|
+
if (process.env.NODE_ENV !== "production") {
|
|
52
52
|
const fixedName = key.replace(/-/g, "_");
|
|
53
53
|
return process.env[fixedName];
|
|
54
54
|
} else {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Using Opentelemetry in e4
|
|
2
|
+
|
|
3
|
+
- `setup.ts` has two main paths:
|
|
4
|
+
1. Azure Not Enabled - Will setup OLTP and @vercel/otel Registration for auto instrumentation with nextjs
|
|
5
|
+
2. Azure Enabled - Does the above AND Azure monitoring for metrics, logs, and traces
|
|
6
|
+
|
|
7
|
+
## Using a Tracer Example
|
|
8
|
+
|
|
9
|
+
From https://opentelemetry.io/docs/languages/js/instrumentation/
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import opentelemetry from "@opentelemetry/api";
|
|
13
|
+
//...
|
|
14
|
+
|
|
15
|
+
const tracer = opentelemetry.trace.getTracer(
|
|
16
|
+
"instrumentation-scope-name",
|
|
17
|
+
"instrumentation-scope-version",
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// You can now use a 'tracer' to do tracing!
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Starting a Span
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
return tracer.startActiveSpan("rollTheDice", (span: Span) => {
|
|
27
|
+
const result: number[] = [];
|
|
28
|
+
for (let i = 0; i < rolls; i++) {
|
|
29
|
+
result.push(rollOnce(min, max));
|
|
30
|
+
}
|
|
31
|
+
// Be sure to end the span!
|
|
32
|
+
span.end();
|
|
33
|
+
return result;
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Using the Logger
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import log from "@evenicanpm/common-core/src/otel/logger";
|
|
41
|
+
|
|
42
|
+
const logger = log();
|
|
43
|
+
logger.info("This is some e4 info!");
|
|
44
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { logs, SeverityNumber } from "@opentelemetry/api-logs";
|
|
2
|
+
|
|
3
|
+
type LogAttriutes = Record<string, string | number | boolean | undefined>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* Centralized logging using opentelemetry log emitter function.
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
function logger() {
|
|
11
|
+
// Global logger is set in ./setup.ts
|
|
12
|
+
const log = logs.getLogger("storefront");
|
|
13
|
+
return {
|
|
14
|
+
info: (message: string, attributes?: LogAttriutes) => {
|
|
15
|
+
log.emit({
|
|
16
|
+
severityNumber: SeverityNumber.INFO,
|
|
17
|
+
body: message,
|
|
18
|
+
attributes,
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
debug: (message: string) => {
|
|
22
|
+
log.emit({
|
|
23
|
+
severityNumber: SeverityNumber.DEBUG,
|
|
24
|
+
body: message,
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
error: (message: string, error?: unknown, attributes?: LogAttriutes) => {
|
|
28
|
+
const err =
|
|
29
|
+
error instanceof Error
|
|
30
|
+
? {
|
|
31
|
+
name: error.name,
|
|
32
|
+
message: error.message,
|
|
33
|
+
stack: error.stack,
|
|
34
|
+
}
|
|
35
|
+
: undefined;
|
|
36
|
+
log.emit({
|
|
37
|
+
severityNumber: SeverityNumber.ERROR,
|
|
38
|
+
body: message,
|
|
39
|
+
attributes: {
|
|
40
|
+
...attributes,
|
|
41
|
+
...(err && { error: err }),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
warn: (message: string) => {
|
|
46
|
+
log.emit({
|
|
47
|
+
severityNumber: SeverityNumber.WARN,
|
|
48
|
+
body: message,
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default logger;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { metrics } from "@opentelemetry/api";
|
|
2
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
3
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
4
|
+
import {
|
|
5
|
+
BatchLogRecordProcessor,
|
|
6
|
+
LoggerProvider,
|
|
7
|
+
} from "@opentelemetry/sdk-logs";
|
|
8
|
+
import {
|
|
9
|
+
MeterProvider,
|
|
10
|
+
PeriodicExportingMetricReader,
|
|
11
|
+
} from "@opentelemetry/sdk-metrics";
|
|
12
|
+
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
13
|
+
import { registerOTel } from "@vercel/otel";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The configuration object passed to setupOtel function.
|
|
17
|
+
*/
|
|
18
|
+
interface otelConfig {
|
|
19
|
+
serviceName: string;
|
|
20
|
+
AzureEnabled?: boolean;
|
|
21
|
+
AzureMonitorKey?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The core setup for Azure Insights and opentelemetry for
|
|
26
|
+
* admin and storefront. Config can be extended to support multiple
|
|
27
|
+
* opentelemetry exports.
|
|
28
|
+
*/
|
|
29
|
+
async function setupOtel(otelConfig?: otelConfig) {
|
|
30
|
+
if (!process.env.OTELCOL_URL) {
|
|
31
|
+
throw new Error("Missing OTELCOL_URL environment variable.");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { serviceName, AzureEnabled, AzureMonitorKey } = otelConfig ?? {};
|
|
35
|
+
|
|
36
|
+
if (!AzureEnabled) {
|
|
37
|
+
return registerOTel({
|
|
38
|
+
serviceName: otelConfig?.serviceName,
|
|
39
|
+
spanProcessors: [
|
|
40
|
+
new BatchSpanProcessor(
|
|
41
|
+
new OTLPTraceExporter({ url: process.env.OTELCOL_URL }),
|
|
42
|
+
),
|
|
43
|
+
],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Azure Enabled */
|
|
48
|
+
if (!AzureMonitorKey)
|
|
49
|
+
throw new Error("No Azure Monitor Connection String Provided.");
|
|
50
|
+
|
|
51
|
+
const connectionString = AzureMonitorKey;
|
|
52
|
+
const config = { connectionString };
|
|
53
|
+
|
|
54
|
+
// Azure - Imports
|
|
55
|
+
const {
|
|
56
|
+
AzureMonitorMetricExporter,
|
|
57
|
+
AzureMonitorTraceExporter,
|
|
58
|
+
AzureMonitorLogExporter,
|
|
59
|
+
} = await import("@azure/monitor-opentelemetry-exporter");
|
|
60
|
+
const { HostMetrics } = await import("@opentelemetry/host-metrics");
|
|
61
|
+
|
|
62
|
+
// Azure - Monitor Exporters
|
|
63
|
+
const metricsExporter = new AzureMonitorMetricExporter(config);
|
|
64
|
+
const logExporter = new AzureMonitorLogExporter(config);
|
|
65
|
+
const traceExporter = new AzureMonitorTraceExporter(config);
|
|
66
|
+
|
|
67
|
+
// Azure - Logging
|
|
68
|
+
const logProcessor = new BatchLogRecordProcessor(logExporter, {
|
|
69
|
+
maxExportBatchSize: 100,
|
|
70
|
+
});
|
|
71
|
+
const loggerProvider = new LoggerProvider({ processors: [logProcessor] });
|
|
72
|
+
logs.setGlobalLoggerProvider(loggerProvider);
|
|
73
|
+
|
|
74
|
+
// Azure - Metrics
|
|
75
|
+
const metricReaderOptions = {
|
|
76
|
+
exporter: metricsExporter,
|
|
77
|
+
};
|
|
78
|
+
const metricReader = new PeriodicExportingMetricReader(metricReaderOptions);
|
|
79
|
+
const meterProvider = new MeterProvider({
|
|
80
|
+
readers: [metricReader],
|
|
81
|
+
});
|
|
82
|
+
metrics.setGlobalMeterProvider(meterProvider);
|
|
83
|
+
// OS level Metrics
|
|
84
|
+
const hostMetrics = new HostMetrics({ meterProvider });
|
|
85
|
+
hostMetrics.start();
|
|
86
|
+
|
|
87
|
+
/** NextJS Otel Registration */
|
|
88
|
+
registerOTel({
|
|
89
|
+
serviceName: serviceName,
|
|
90
|
+
spanProcessors: [
|
|
91
|
+
new BatchSpanProcessor(traceExporter),
|
|
92
|
+
new BatchSpanProcessor(
|
|
93
|
+
new OTLPTraceExporter({ url: process.env.OTELCOL_URL }),
|
|
94
|
+
),
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { setupOtel };
|
package/tsconfig.json
CHANGED
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
"moduleResolution": "node",
|
|
11
11
|
"resolveJsonModule": true,
|
|
12
12
|
"outDir": "./dist",
|
|
13
|
-
"baseUrl": "
|
|
13
|
+
"baseUrl": "./",
|
|
14
14
|
"jsx": "preserve",
|
|
15
|
+
"typeRoots": ["../../../../storefront/node_modules/@types"],
|
|
15
16
|
"paths": {
|
|
16
|
-
"*": ["../../../../storefront/node_modules
|
|
17
|
+
"*": ["../../../../storefront/node_modules/*"]
|
|
17
18
|
}
|
|
18
19
|
},
|
|
19
20
|
"include": ["./"]
|