diff --git a/apps/pay/package.json b/apps/pay/package.json
index ae9f073c0e..177bfe75fc 100644
--- a/apps/pay/package.json
+++ b/apps/pay/package.json
@@ -14,6 +14,18 @@
"dependencies": {
"@apollo/client": "^3.7.12",
"@galoymoney/client": "^0.2.2",
+ "@opentelemetry/api": "^1.7.0",
+ "@opentelemetry/context-zone": "^1.21.0",
+ "@opentelemetry/core": "^1.21.0",
+ "@opentelemetry/exporter-trace-otlp-http": "^0.48.0",
+ "@opentelemetry/instrumentation": "^0.47.0",
+ "@opentelemetry/instrumentation-fetch": "^0.48.0",
+ "@opentelemetry/instrumentation-xml-http-request": "^0.48.0",
+ "@opentelemetry/propagator-b3": "^1.21.0",
+ "@opentelemetry/sdk-metrics": "^1.21.0",
+ "@opentelemetry/sdk-trace-base": "^1.20.0",
+ "@opentelemetry/sdk-trace-web": "^1.21.0",
+ "@opentelemetry/semantic-conventions": "^1.21.0",
"@t3-oss/env-nextjs": "^0.6.1",
"bech32": "^2.0.0",
"bitcoinjs-lib": "5.0.5",
diff --git a/apps/pay/pages/index.tsx b/apps/pay/pages/index.tsx
index 72aa16c44a..69fdf0debb 100644
--- a/apps/pay/pages/index.tsx
+++ b/apps/pay/pages/index.tsx
@@ -12,6 +12,8 @@ import { useRouter } from "next/router"
import CurrencyDropdown from "../components/Currency/currency-dropdown"
import { getClientSideGqlConfig } from "../config/config"
+import initializeTelemetry from "./otel"
+
const GET_NODE_STATS = gql`
query nodeIds {
globals {
@@ -29,6 +31,8 @@ function Home() {
localStorage.getItem("display") ?? "USD",
)
+ initializeTelemetry()
+
const router = useRouter()
const [username, setUsername] = React.useState("")
@@ -68,8 +72,8 @@ function Home() {
{error
? "Unavailable"
: loading
- ? "Loading..."
- : data.globals.nodesIds[0]}
+ ? "Loading..."
+ : data.globals.nodesIds[0]}
diff --git a/apps/pay/pages/otel.ts b/apps/pay/pages/otel.ts
new file mode 100644
index 0000000000..708af09ce4
--- /dev/null
+++ b/apps/pay/pages/otel.ts
@@ -0,0 +1,43 @@
+// Importing necessary modules from OpenTelemetry packages
+import { context, trace } from "@opentelemetry/api"
+import { ConsoleSpanExporter, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base"
+import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
+import { WebTracerProvider } from "@opentelemetry/sdk-trace-web"
+import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch"
+import { ZoneContextManager } from "@opentelemetry/context-zone"
+import { B3Propagator } from "@opentelemetry/propagator-b3"
+import { registerInstrumentations } from "@opentelemetry/instrumentation"
+
+// Define the initialization function
+export default function initializeTelemetry() {
+ const provider = new WebTracerProvider()
+
+ provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter()))
+ provider.register({
+ contextManager: new ZoneContextManager(),
+ propagator: new B3Propagator(),
+ })
+
+ registerInstrumentations({
+ instrumentations: [
+ new FetchInstrumentation({
+ ignoreUrls: [/localhost:8090\/sockjs-node/],
+ propagateTraceHeaderCorsUrls: [
+ "https://cors-test.appspot.com/test",
+ "https://httpbin.org/get",
+ ],
+ clearTimingResources: true,
+ }),
+ ],
+ })
+
+ // Example of how you might use the provider to create a tracer
+ // This example function doesn't do anything by itself but is here to show how you might use it
+ const webTracerWithZone = provider.getTracer("example-tracer-web")
+
+ // Placeholder for any setup logic you might have
+ console.log("OpenTelemetry initialized")
+}
+
+// Note: This file does not include the event listener setup from the original otel.js example,
+// as those are typically handled within the components or pages themselves in a React application.
diff --git a/apps/pay/public/BBLogo.png b/apps/pay/public/BBLogo.png
deleted file mode 100644
index 6b10c3b652..0000000000
Binary files a/apps/pay/public/BBLogo.png and /dev/null differ
diff --git a/apps/pay/public/BBQRLogo.png b/apps/pay/public/BBQRLogo.png
deleted file mode 100644
index 80223cc374..0000000000
Binary files a/apps/pay/public/BBQRLogo.png and /dev/null differ
diff --git a/apps/pay/public/BBW-QRLOGO.png b/apps/pay/public/BBW-QRLOGO.png
deleted file mode 100644
index 6dd409b17b..0000000000
Binary files a/apps/pay/public/BBW-QRLOGO.png and /dev/null differ
diff --git a/apps/pay/public/QRLOGO-BBW.png b/apps/pay/public/QRLOGO-BBW.png
deleted file mode 100644
index 41ac95fa90..0000000000
Binary files a/apps/pay/public/QRLOGO-BBW.png and /dev/null differ
diff --git a/apps/pay/public/otel.js b/apps/pay/public/otel.js
new file mode 100644
index 0000000000..0f1842a6e1
--- /dev/null
+++ b/apps/pay/public/otel.js
@@ -0,0 +1,72 @@
+const { context, trace } = require( '@opentelemetry/api');
+const { ConsoleSpanExporter, SimpleSpanProcessor } = require( '@opentelemetry/sdk-trace-base');
+const { OTLPTraceExporter } = require( '@opentelemetry/exporter-trace-otlp-http');
+const { WebTracerProvider } = require( '@opentelemetry/sdk-trace-web');
+const { FetchInstrumentation } = require( '@opentelemetry/instrumentation-fetch');
+const { ZoneContextManager } = require( '@opentelemetry/context-zone');
+const { B3Propagator } = require( '@opentelemetry/propagator-b3');
+const { registerInstrumentations } = require( '@opentelemetry/instrumentation');
+
+const provider = new WebTracerProvider();
+
+// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests
+// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the
+// exporter without delay
+// provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
+provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter()));
+provider.register({
+ contextManager: new ZoneContextManager(),
+ propagator: new B3Propagator(),
+});
+
+registerInstrumentations({
+ instrumentations: [
+ new FetchInstrumentation({
+ ignoreUrls: [/localhost:8090\/sockjs-node/],
+ propagateTraceHeaderCorsUrls: [
+ 'https://cors-test.appspot.com/test',
+ 'https://httpbin.org/get',
+ ],
+ clearTimingResources: true,
+ }),
+ ],
+});
+
+const webTracerWithZone = provider.getTracer('example-tracer-web');
+
+const getData = (url) => fetch(url, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+});
+
+// example of keeping track of context between async operations
+const prepareClickEvent = () => {
+ const url = 'https://httpbin.org/get';
+
+ const element = document.getElementById('button1');
+
+ const onClick = () => {
+ const singleSpan = webTracerWithZone.startSpan('files-series-info');
+ context.with(trace.setSpan(context.active(), singleSpan), () => {
+ getData(url).then((_data) => {
+ trace.getSpan(context.active()).addEvent('fetching-single-span-completed');
+ singleSpan.end();
+ });
+ });
+ for (let i = 0, j = 5; i < j; i += 1) {
+ const span = webTracerWithZone.startSpan(`files-series-info-${i}`);
+ context.with(trace.setSpan(context.active(), span), () => {
+ getData(url).then((_data) => {
+ trace.getSpan(context.active()).addEvent(`fetching-span-${i}-completed`);
+ span.end();
+ });
+ });
+ }
+ };
+ element.addEventListener('click', onClick);
+};
+
+window.addEventListener('load', prepareClickEvent);
diff --git a/core/api/dev/otel-agent-config.yaml b/core/api/dev/otel-agent-config.yaml
index 0a7995ab2c..702e5171a1 100644
--- a/core/api/dev/otel-agent-config.yaml
+++ b/core/api/dev/otel-agent-config.yaml
@@ -9,6 +9,10 @@ receivers:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
+ cors:
+ allowed_origins:
+ - http://*
+ - https://*
processors:
filter/ottl:
diff --git a/dev/config/otel-agent-config.yaml b/dev/config/otel-agent-config.yaml
index 0a7995ab2c..702e5171a1 100644
--- a/dev/config/otel-agent-config.yaml
+++ b/dev/config/otel-agent-config.yaml
@@ -9,6 +9,10 @@ receivers:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
+ cors:
+ allowed_origins:
+ - http://*
+ - https://*
processors:
filter/ottl:
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 132015f20e..cea0a1d3b9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -574,6 +574,42 @@ importers:
'@galoymoney/client':
specifier: ^0.2.2
version: 0.2.6(@bitcoinerlab/secp256k1@1.0.5)(bitcoinjs-lib@5.0.5)(bolt11@1.3.4)(lnurl-pay@1.0.1)(url@0.11.3)
+ '@opentelemetry/api':
+ specifier: ^1.7.0
+ version: 1.7.0
+ '@opentelemetry/context-zone':
+ specifier: ^1.21.0
+ version: 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/core':
+ specifier: ^1.21.0
+ version: 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/exporter-trace-otlp-http':
+ specifier: ^0.48.0
+ version: 0.48.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/instrumentation':
+ specifier: ^0.47.0
+ version: 0.47.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/instrumentation-fetch':
+ specifier: ^0.48.0
+ version: 0.48.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/instrumentation-xml-http-request':
+ specifier: ^0.48.0
+ version: 0.48.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/propagator-b3':
+ specifier: ^1.21.0
+ version: 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-metrics':
+ specifier: ^1.21.0
+ version: 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-trace-base':
+ specifier: ^1.20.0
+ version: 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-trace-web':
+ specifier: ^1.21.0
+ version: 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/semantic-conventions':
+ specifier: ^1.21.0
+ version: 1.21.0
'@t3-oss/env-nextjs':
specifier: ^0.6.1
version: 0.6.1(typescript@5.2.2)(zod@3.22.4)
@@ -612,7 +648,7 @@ importers:
version: 4.0.8
next:
specifier: ^13.4.19
- version: 13.5.6(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0)
+ version: 13.5.6(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0)
react:
specifier: ^18.2.0
version: 18.2.0
@@ -6387,8 +6423,8 @@ packages:
optional: true
dependencies:
'@babel/generator': 7.23.6
- '@babel/template': 7.22.15
- '@babel/types': 7.23.6
+ '@babel/template': 7.23.9
+ '@babel/types': 7.23.9
'@graphql-codegen/core': 4.0.0(graphql@16.8.1)
'@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1)
'@graphql-tools/apollo-engine-loader': 8.0.0(graphql@16.8.1)
@@ -7266,7 +7302,7 @@ packages:
'@graphql-tools/utils': 8.9.0(graphql@16.8.1)
dataloader: 2.1.0
graphql: 16.8.1
- tslib: 2.4.1
+ tslib: 2.6.2
value-or-promise: 1.0.11
dev: false
@@ -9625,6 +9661,27 @@ packages:
'@opentelemetry/api': 1.7.0
dev: false
+ /@opentelemetry/context-zone-peer-dep@1.21.0(@opentelemetry/api@1.7.0)(zone.js@0.11.8):
+ resolution: {integrity: sha512-VShgSOPlc2UWaNdJST7syUDLdFKstkiqVDBaFEwSwvXP9IIaE7XxS5uAVkd55EVOzfB7PhdEQ91roAt5pHyzhQ==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ '@opentelemetry/api': '>=1.0.0 <1.8.0'
+ zone.js: ^0.10.2 || ^0.11.0 || ^0.13.0
+ dependencies:
+ '@opentelemetry/api': 1.7.0
+ zone.js: 0.11.8
+ dev: false
+
+ /@opentelemetry/context-zone@1.21.0(@opentelemetry/api@1.7.0):
+ resolution: {integrity: sha512-YJQH3LroaZZBN0baGLkvw1WlNNpdNxXf7wfdJrst5v+lYGOus5HX9GUAOB9dByj3Z6yGlPIboPPojnc+ybxKGA==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@opentelemetry/context-zone-peer-dep': 1.21.0(@opentelemetry/api@1.7.0)(zone.js@0.11.8)
+ zone.js: 0.11.8
+ transitivePeerDependencies:
+ - '@opentelemetry/api'
+ dev: false
+
/@opentelemetry/core@1.17.1(@opentelemetry/api@1.7.0):
resolution: {integrity: sha512-I6LrZvl1FF97FQXPR0iieWQmKnGxYtMbWA1GrAXnLUR+B1Hn2m8KqQNEIlZAucyv00GBgpWkpllmULmZfG8P3g==}
engines: {node: '>=14'}
@@ -9807,6 +9864,21 @@ packages:
'@opentelemetry/semantic-conventions': 1.21.0
dev: false
+ /@opentelemetry/instrumentation-fetch@0.48.0(@opentelemetry/api@1.7.0):
+ resolution: {integrity: sha512-y4Zw9VeUUMaowg3aXYZXcaUJQ7IKfpR6sjClrAQOJwWG8LYFpM6NIRSoAeJv/ShfxWWCPWC0P4zgXcKRqpURFQ==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ '@opentelemetry/api': ^1.0.0
+ dependencies:
+ '@opentelemetry/api': 1.7.0
+ '@opentelemetry/core': 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/instrumentation': 0.48.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-trace-web': 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/semantic-conventions': 1.21.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/@opentelemetry/instrumentation-graphql@0.35.2(@opentelemetry/api@1.7.0):
resolution: {integrity: sha512-lJv7BbHFK0ExwogdQMtVHfnWhCBMDQEz8KYvhShXfRPiSStU5aVwa3TmT0O00KiJFpATSKJNZMv1iZNHbF6z1g==}
engines: {node: '>=14'}
@@ -9951,7 +10023,7 @@ packages:
dependencies:
'@opentelemetry/api': 1.7.0
'@opentelemetry/instrumentation': 0.46.0(@opentelemetry/api@1.7.0)
- '@opentelemetry/sdk-metrics': 1.20.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-metrics': 1.21.0(@opentelemetry/api@1.7.0)
'@opentelemetry/semantic-conventions': 1.21.0
transitivePeerDependencies:
- supports-color
@@ -9996,6 +10068,21 @@ packages:
- supports-color
dev: false
+ /@opentelemetry/instrumentation-xml-http-request@0.48.0(@opentelemetry/api@1.7.0):
+ resolution: {integrity: sha512-YJ9d1sR28hcEVtP4/tHtPX5Hhu0w2LsAMp3M+75YGTHkkunsN8PwcY/1FcSHUP9xwy7Z2myQvT7fTpL3g4tn4A==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ '@opentelemetry/api': ^1.0.0
+ dependencies:
+ '@opentelemetry/api': 1.7.0
+ '@opentelemetry/core': 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/instrumentation': 0.48.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-trace-web': 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/semantic-conventions': 1.21.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/@opentelemetry/instrumentation@0.44.0(@opentelemetry/api@1.7.0):
resolution: {integrity: sha512-B6OxJTRRCceAhhnPDBshyQO7K07/ltX3quOLu0icEvPK9QZ7r9P1y0RQX8O5DxB4vTv4URRkxkg+aFU/plNtQw==}
engines: {node: '>=14'}
@@ -10576,6 +10663,18 @@ packages:
semver: 7.6.0
dev: false
+ /@opentelemetry/sdk-trace-web@1.21.0(@opentelemetry/api@1.7.0):
+ resolution: {integrity: sha512-MxkmY/UNXkDiZj7JUu5T7wWt8Ai4NJEwSjGoQQ9YLvgLUIivvaIo9Mne+Q+KLOUG2v/uhivz3qzxbCODVa0c1A==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ '@opentelemetry/api': '>=1.0.0 <1.8.0'
+ dependencies:
+ '@opentelemetry/api': 1.7.0
+ '@opentelemetry/core': 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/sdk-trace-base': 1.21.0(@opentelemetry/api@1.7.0)
+ '@opentelemetry/semantic-conventions': 1.21.0
+ dev: false
+
/@opentelemetry/semantic-conventions@1.17.1:
resolution: {integrity: sha512-xbR2U+2YjauIuo42qmE8XyJK6dYeRMLJuOlUP5SO4auET4VtOHOzgkRVOq+Ik18N+Xf3YPcqJs9dZMiDddz1eQ==}
engines: {node: '>=14'}
@@ -15055,7 +15154,7 @@ packages:
debug: 4.3.4(supports-color@5.5.0)
globby: 11.1.0
is-glob: 4.0.3
- semver: 7.5.4
+ semver: 7.6.0
tsutils: 3.21.0(typescript@4.9.5)
typescript: 4.9.5
transitivePeerDependencies:
@@ -15076,7 +15175,7 @@ packages:
debug: 4.3.4(supports-color@5.5.0)
globby: 11.1.0
is-glob: 4.0.3
- semver: 7.5.4
+ semver: 7.6.0
tsutils: 3.21.0(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
@@ -15097,7 +15196,7 @@ packages:
debug: 4.3.4(supports-color@5.5.0)
globby: 11.1.0
is-glob: 4.0.3
- semver: 7.5.4
+ semver: 7.6.0
tsutils: 3.21.0(typescript@5.3.3)
typescript: 5.3.3
transitivePeerDependencies:
@@ -15141,7 +15240,7 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.3
- semver: 7.5.4
+ semver: 7.6.0
ts-api-utils: 1.0.3(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
@@ -15163,7 +15262,7 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.3
- semver: 7.5.4
+ semver: 7.6.0
ts-api-utils: 1.0.3(typescript@5.3.3)
typescript: 5.3.3
transitivePeerDependencies:
@@ -15267,7 +15366,7 @@ packages:
'@typescript-eslint/types': 6.17.0
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3)
eslint: 8.56.0
- semver: 7.5.4
+ semver: 7.6.0
transitivePeerDependencies:
- supports-color
- typescript
@@ -25717,7 +25816,7 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
- /next@13.5.6(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0):
+ /next@13.5.6(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==}
engines: {node: '>=16.14.0'}
hasBin: true
@@ -25733,6 +25832,7 @@ packages:
optional: true
dependencies:
'@next/env': 13.5.6
+ '@opentelemetry/api': 1.7.0
'@swc/helpers': 0.5.2
busboy: 1.6.0
caniuse-lite: 1.0.30001561
@@ -25887,7 +25987,7 @@ packages:
resolution: {integrity: sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==}
engines: {node: '>=10'}
dependencies:
- semver: 7.5.4
+ semver: 7.6.0
dev: false
/node-abort-controller@3.1.1:
@@ -28843,7 +28943,7 @@ packages:
resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
engines: {node: '>=10'}
dependencies:
- semver: 7.5.4
+ semver: 7.6.0
dev: true
/sisteransi@1.0.5:
@@ -29824,7 +29924,7 @@ packages:
hasBin: true
dependencies:
'@jridgewell/source-map': 0.3.5
- acorn: 8.11.2
+ acorn: 8.11.3
commander: 2.20.3
source-map-support: 0.5.21
dev: true
@@ -30612,7 +30712,7 @@ packages:
/unplugin@1.5.1:
resolution: {integrity: sha512-0QkvG13z6RD+1L1FoibQqnvTwVBXvS4XSPwAyinVgoOCl2jAgwzdUKmEj05o4Lt8xwQI85Hb6mSyYkcAGwZPew==}
dependencies:
- acorn: 8.11.2
+ acorn: 8.11.3
chokidar: 3.6.0
webpack-sources: 3.2.3
webpack-virtual-modules: 0.6.1
@@ -31533,3 +31633,9 @@ packages:
/zod@3.22.4:
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
dev: false
+
+ /zone.js@0.11.8:
+ resolution: {integrity: sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==}
+ dependencies:
+ tslib: 2.6.2
+ dev: false