Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d9c7aff
feat(ui): fetch storage capabilities from backend during Vite dev mode
aryunewaskar77-art Feb 13, 2026
10244f8
chore: resolve merge conflict in package.json
aryunewaskar77-art Feb 13, 2026
e143e1a
Update packages/jaeger-ui/vite.config.mts
aryunewaskar77-art Feb 13, 2026
83038e1
fix(ui): improve error handling and safety in Vite config plugin
aryunewaskar77-art Feb 13, 2026
0445460
Update packages/jaeger-ui/vite.config.mts
aryunewaskar77-art Feb 14, 2026
0ffe98b
Update package.json
aryunewaskar77-art Feb 14, 2026
bde05c2
Update verify_otel.cjs
aryunewaskar77-art Feb 14, 2026
6bd9e08
Update package.json
aryunewaskar77-art Feb 15, 2026
5270fc6
Update packages/jaeger-ui/vite.config.mts
aryunewaskar77-art Feb 16, 2026
50456de
Update packages/jaeger-ui/vite.config.mts
aryunewaskar77-art Feb 16, 2026
dfc45b6
monitor tab fixed
aryunewaskar77-art Feb 16, 2026
b65bfb5
Fix: address code review feedback for Monitor EmptyState and Vite config
aryunewaskar77-art Feb 17, 2026
66d16e2
Fix: centralize config keys and restrict Vite plugin to serve mode
aryunewaskar77-art Feb 17, 2026
28d9e5e
Update packages/jaeger-ui/src/constants/config-keys.ts
aryunewaskar77-art Feb 17, 2026
381a83c
Update packages/jaeger-ui/vite.config.mts
aryunewaskar77-art Feb 17, 2026
d3defc0
Merge branch 'main' into feat/vite-config-fetch
aryunewaskar77-art Feb 20, 2026
ba7bd29
Merge branch 'main' into feat/vite-config-fetch
aryunewaskar77-art Feb 21, 2026
141747f
Merge branch 'main' into feat/vite-config-fetch
aryunewaskar77-art Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@babel/cli": "7.28.0",
"@babel/core": "7.28.5",
"@testing-library/dom": "^10.4.1",
"@types/node": "^25.2.3",
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The repo declares engines.node as >=24, but this adds @types/node ^25.2.3. If the project is targeting Node 24 in CI/dev, consider aligning the major version of @types/node with the supported runtime (or pinning a known-good version) to avoid type drift and incompatibilities.

Suggested change
"@types/node": "^25.2.3",
"@types/node": "^24.0.0",

Copilot uses AI. Check for mistakes.
"@typescript-eslint/eslint-plugin": "8.50.0",
"@typescript-eslint/parser": "8.50.0",
"ajv": "^6.12.6",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@ describe('<MonitorATMEmptyState>', () => {
fireEvent.click(button);
expect(mockClickHandler).toHaveBeenCalled();
});

it('renders nothing when config is missing', () => {
getConfigValue.mockReturnValue(null);
const { container } = render(<MonitorATMEmptyState />);
expect(container.firstChild).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import monitorImg from './media/monitor.png';
const MonitorATMEmptyState: React.FC = () => {
const config: MonitorEmptyStateConfig = getConfigValue('monitor.emptyState');

if (!config) {
return null;
}
Comment on lines +14 to +16
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new null check on lines 14-16 adds a code path that returns early when config is null/undefined. However, the existing test file (index.test.js) only tests the case where config is defined and doesn't cover the scenario where getConfigValue returns null/undefined. Consider adding a test case to verify that the component renders null when config is not available, ensuring this defensive code path is covered.

Copilot uses AI. Check for mistakes.

return (
<Col>
<Row justify="center">
Expand Down
6 changes: 6 additions & 0 deletions packages/jaeger-ui/src/constants/config-keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

// Fields that should be merged with user-supplied config values rather than overwritten.
export type TMergeField = 'dependencies' | 'search' | 'tracking' | 'monitor';
export const mergeFields: readonly TMergeField[] = ['dependencies', 'search', 'tracking', 'monitor'];
6 changes: 3 additions & 3 deletions packages/jaeger-ui/src/constants/default-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ const defaultConfig: Config = {
useOpenTelemetryTerms: false,
};

// Fields that should be merged with user-supplied config values rather than overwritten.
type TMergeField = 'dependencies' | 'search' | 'tracking';
export const mergeFields: readonly TMergeField[] = ['dependencies', 'search', 'tracking'];
import { mergeFields } from './config-keys';
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement at line 122 is placed after the const declaration, which is unconventional. While JavaScript/TypeScript hoists imports automatically, it's more idiomatic and consistent with typical code style to place all imports at the top of the file (lines 3-10). Consider moving this import to line 11 to group it with other imports.

Copilot uses AI. Check for mistakes.

export { mergeFields };

export default deepFreeze(defaultConfig);

Expand Down
121 changes: 97 additions & 24 deletions packages/jaeger-ui/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import legacy from '@vitejs/plugin-legacy';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { mergeFields } from './src/constants/config-keys';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const proxyConfig = {
target: 'http://localhost:16686',
target: 'http://127.0.0.1:16686',
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change from 'localhost' to '127.0.0.1' improves consistency with the fetch URL used later in the code (line 63), but breaks consistency with existing documentation. The CONTRIBUTING.md and AGENTS.md files both reference 'http://localhost:16686' throughout. While both localhost and 127.0.0.1 generally work the same, using localhost is more standard and user-friendly in documentation. Consider either reverting this change or updating the documentation files to match.

Suggested change
target: 'http://127.0.0.1:16686',
target: 'http://localhost:16686',

Copilot uses AI. Check for mistakes.
secure: false,
changeOrigin: true,
ws: true,
Expand All @@ -39,52 +40,124 @@ function jaegerUiConfigPlugin() {

return {
name: 'jaeger-ui-config',
configureServer(server) {
apply: 'serve' as const,
configureServer(server: import('vite').ViteDevServer) {
server.watcher.add([jsConfigPath, jsonConfigPath]);
server.watcher.on('change', path => {
if (path === jsConfigPath || path === jsonConfigPath) {
console.log(`[jaeger-ui-config] Config changed: ${path}. Triggering full reload...`);
server.watcher.on('change', (changedPath: string) => {
if (changedPath === jsConfigPath || changedPath === jsonConfigPath) {
console.log(`[jaeger-ui-config] Config changed: ${changedPath}. Triggering full reload...`);
server.ws.send({ type: 'full-reload', path: '*' });
}
});
},
transformIndexHtml: {
order: 'pre' as const,
async handler(html: string) {
Comment on lines 41 to 55
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The transformIndexHtml hook runs during vite build as well as dev server. With the new backend fetch + HTML replacements, a local backend running during build would bake UI config/capabilities/version into the built index.html and remove the exact placeholder patterns the query-service expects to search/replace at runtime. Consider restricting this plugin to dev-only (e.g., apply: 'serve' and/or guard on Vite command === 'serve') so production builds keep the injection markers intact.

Copilot uses AI. Check for mistakes.
// Check for JS config first (higher priority, like in Go server)
let backendUiConfig: any = null;
let storageCapabilities: any = null;
let version: any = null;
Comment on lines +56 to +58
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variables 'backendUiConfig', 'storageCapabilities', and 'version' are all typed as 'any', which bypasses TypeScript's type safety. Since '@types/node' was added as a dependency in this PR, consider defining proper TypeScript interfaces for the expected backend response structure. This would make the code more maintainable and catch potential type errors at compile time.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +58
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variables backendUiConfig, storageCapabilities, and version are typed as any. Consider using more specific types or at least defining a type interface for the expected backend response structure. This would provide better type safety and make the code more maintainable. For example:

interface BackendConfig {
  uiConfig?: Record<string, any>;
  storageCapabilities?: { archiveStorage?: boolean; metricsStorage?: boolean };
  version?: { gitCommit: string; gitVersion: string; buildDate: string };
}

let backendConfig: BackendConfig | null = null;

Copilot uses AI. Check for mistakes.

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 1000);
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout value (1000ms) is hardcoded in the implementation. This should be extracted as a named constant at the top of the function or module level to make it more maintainable and easier to adjust if needed. Consider defining something like const BACKEND_FETCH_TIMEOUT_MS = 1000;.

Copilot uses AI. Check for mistakes.

try {
const fetchOptions = { signal: controller.signal };
const response = await fetch('http://127.0.0.1:16686/api/ui/config', fetchOptions);

Comment on lines 53 to +66
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This plugin is included unconditionally in the Vite config, and transformIndexHtml also runs during vite build. With the new backend fetch, production builds can become non-deterministic (if a local backend is running) and will always incur the 1s timeout on failures. Consider gating the backend fetch logic to command === 'serve' / dev mode so builds remain reproducible and fast.

Copilot uses AI. Check for mistakes.
if (response?.ok) {
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optional chaining operator 'response?.ok' is unnecessary here. If the fetch call succeeds without throwing, the response object is guaranteed to be defined. The check can be simplified to 'response.ok'. The optional chaining doesn't add safety since any network or timeout errors are already caught in the catch block.

Suggested change
if (response?.ok) {
if (response.ok) {

Copilot uses AI. Check for mistakes.
const data = await response.json();

// Extract data from unified response
storageCapabilities = data.storageCapabilities;
version = data.version;
backendUiConfig = data.uiConfig;
Comment on lines +67 to +73
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding validation for the backend response to ensure it has the expected structure before attempting to access properties. For example, if data is null or not an object, accessing data.storageCapabilities could lead to unexpected behavior. Adding a basic check like if (data && typeof data === 'object') would make the code more robust.

Copilot uses AI. Check for mistakes.

console.log('[jaeger-ui-config] Fetched config from backend /api/ui/config');
Comment on lines +63 to +75
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code assumes the backend endpoint '/api/ui/config' exists and returns a JSON response with 'storageCapabilities', 'version', and 'uiConfig' fields. However, this is a frontend-only repository and the backend implementation is not visible in this PR. The PR description mentions this endpoint as a "prerequisite", but there's no verification that it exists or that it returns data in the expected format. If the endpoint doesn't exist yet or returns a different structure, the fetch will fail silently and the UI will fall back to defaults. Consider adding a comment documenting the expected response structure, or better yet, creating a TypeScript interface for the expected response.

Copilot uses AI. Check for mistakes.
}
Comment on lines +67 to +76
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optional chaining response?.ok is unnecessary here because if fetch completes successfully (doesn't throw), it always returns a Response object, never null or undefined. The optional chaining may give a false sense of safety - if the fetch succeeds but returns a non-ok status (e.g., 404, 500), the code silently skips config injection without logging any information about the error status.

Consider changing this to check only response.ok and optionally log the status code when it's not ok: if (!response.ok) { console.log('[jaeger-ui-config] Backend returned status: ' + response.status); }

Copilot uses AI. Check for mistakes.
} catch (err) {
// Silent fallback for production behavior, but log for dev visibility
Comment on lines +56 to +78
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transformIndexHtml will run on every page load in dev, and this implementation fetches /api/ui/config each time (plus logs on success). This can add noticeable overhead and noisy logs during development. Consider caching the backend response for a short TTL (e.g., 5–30s) and/or only logging when the source changes.

Copilot uses AI. Check for mistakes.
if (err instanceof Error && err.name === 'AbortError') {
console.log('[jaeger-ui-config] Backend fetch timed out (1s)');
} else if (err instanceof Error) {
console.log(`[jaeger-ui-config] Error fetching backend config: ${err.message}`, err);
} else {
console.log('[jaeger-ui-config] Unknown error fetching backend config:', err);
}
Comment on lines +77 to +85
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AbortError check will never execute because the fetch is already wrapped in .catch(() => null) on line 63. When the timeout triggers controller.abort(), the fetch's catch handler converts it to null, preventing the outer catch block from seeing the AbortError.

The code will incorrectly log "Backend not running or error fetching config" instead of "Backend fetch timed out (1s)" when a timeout occurs.

Fix:

try {
  const fetchOptions = { signal: controller.signal };
  const response = await fetch('http://127.0.0.1:16686/api/ui/config', fetchOptions);
  
  if (response?.ok) {
    const data = await response.json();
    // ... rest of the logic
  }
} catch (err) {
  if (err instanceof Error && err.name === 'AbortError') {
    console.log('[jaeger-ui-config] Backend fetch timed out (1s)');
  } else {
    console.log('[jaeger-ui-config] Backend not running or error fetching config');
  }
}

Remove the .catch(() => null) to allow proper error propagation.

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +77 to +85
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backend fetch failures/timeouts are logged inside transformIndexHtml, which runs frequently during dev. If the backend isn’t running, this will repeatedly print the same message on every request/reload. Consider logging once per TTL (or behind a debug flag) to avoid noisy console output.

Copilot uses AI. Check for mistakes.
} finally {
clearTimeout(timeout);
}

// Check for JS config first (highest priority - no merge)
if (fs.existsSync(jsConfigPath)) {
try {
const jsContent = fs.readFileSync(jsConfigPath, 'utf-8');
// Replace the JAEGER_CONFIG_JS comment with UIConfig function
// This mimics the Go server behavior for .js config files
const uiConfigFn = `function UIConfig() { ${jsContent} }`;
html = html.replace('// JAEGER_CONFIG_JS', uiConfigFn);
console.log('[jaeger-ui-config] Loaded config from jaeger-ui.config.js');
return html;
console.log(
'[jaeger-ui-config] Loaded config from jaeger-ui.config.js (full override, no merge)'
);
// Note: Don't return early here, we still need to inject storageCapabilities and version below
Comment on lines 91 to +99
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a JS config file exists, the code still attempts to inject storageCapabilities and version from the backend, but it doesn't inject the backend's uiConfig. This creates an inconsistency: with JS config, developers lose access to the backend's uiConfig as a baseline, which contradicts one of the key benefits mentioned in the PR description ("automatic backend sync").

Consider whether JS config should also have access to backend uiConfig values, perhaps by making them available as a parameter or global variable that the JS config function can reference if needed.

Copilot uses AI. Check for mistakes.
} catch (err) {
console.error('[jaeger-ui-config] Error loading jaeger-ui.config.js:', err);
Comment on lines 100 to 101
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error object 'err' is declared but never used in this catch block. The error should either be logged for debugging purposes (especially helpful during development) or the parameter should be removed if intentionally unused. Consider changing to 'console.error' or adding a comment explaining why the error is deliberately ignored.

Copilot uses AI. Check for mistakes.
}
Comment on lines 91 to 102
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a jaeger-ui.config.js file exists, the code doesn't inject the finalUiConfig into the HTML because it's inside the else block (lines 101-135). This means that even if the backend provides uiConfig, it won't be injected when using the JS config file. The storageCapabilities and version will be injected (lines 137-151), but JAEGER_CONFIG won't be set, potentially breaking the UI. The logic should inject JAEGER_CONFIG regardless of which config path is taken, or document why this is intentional.

Copilot uses AI. Check for mistakes.
}
} else {
// Handle JSON config merged on top of backend UI config
let finalUiConfig = backendUiConfig;

// Check for JSON config
if (fs.existsSync(jsonConfigPath)) {
try {
const jsonContent = fs.readFileSync(jsonConfigPath, 'utf-8');
// Validate it's valid JSON and use stringified result for injection
const parsedConfig = JSON.parse(jsonContent);
// Replace DEFAULT_CONFIG with the JSON content
// This mimics the Go server behavior for .json config files
if (fs.existsSync(jsonConfigPath)) {
try {
const jsonContent = fs.readFileSync(jsonConfigPath, 'utf-8');
const parsedJsonConfig = JSON.parse(jsonContent);

// Shallow merge: JSON on top of backend base
finalUiConfig = { ...backendUiConfig, ...parsedJsonConfig };
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shallow merge approach here differs from how the get-config.ts handles merging. In get-config.ts (lines 42-47), only fields listed in mergeFields are shallow merged, while other fields are completely overwritten. However, this implementation always does a shallow merge of the entire uiConfig object regardless of field semantics.

This could lead to unexpected behavior where nested properties from backendUiConfig inadvertently bleed through when they should be completely replaced. Consider applying the same mergeFields logic here as used in get-config.ts to maintain consistency.

Copilot uses AI. Check for mistakes.

mergeFields.forEach(key => {
if (
parsedJsonConfig &&
typeof parsedJsonConfig[key] === 'object' &&
parsedJsonConfig[key] !== null
) {
const backendValue = backendUiConfig ? backendUiConfig[key] : {};
finalUiConfig[key] = { ...backendValue, ...parsedJsonConfig[key] };
}
});

console.log(
'[jaeger-ui-config] Merged config from jaeger-ui.config.json on top of backend uiConfig'
);
} catch (err) {
console.error('[jaeger-ui-config] Error loading jaeger-ui.config.json:', err);
Comment on lines +129 to +130
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error object 'err' is declared but never used in this catch block. Similar to the issue above, the error should either be logged for debugging or the parameter should be removed. This is especially important here since JSON parsing errors would be helpful to see during development.

Copilot uses AI. Check for mistakes.
}
} else if (backendUiConfig) {
console.log('[jaeger-ui-config] Using backend uiConfig as base');
}

// Inject final UI config into index.html
if (finalUiConfig) {
html = html.replace(
'const JAEGER_CONFIG = DEFAULT_CONFIG;',
`const JAEGER_CONFIG = ${JSON.stringify(parsedConfig)};`
`const JAEGER_CONFIG = ${JSON.stringify(finalUiConfig)};`
);
console.log('[jaeger-ui-config] Loaded config from jaeger-ui.config.json');
return html;
} catch (err) {
console.error('[jaeger-ui-config] Error loading jaeger-ui.config.json:', err);
}
}

// Inject storageCapabilities into index.html
if (storageCapabilities) {
html = html.replace(
'const JAEGER_STORAGE_CAPABILITIES = DEFAULT_STORAGE_CAPABILITIES;',
`const JAEGER_STORAGE_CAPABILITIES = ${JSON.stringify(storageCapabilities)};`
);
}

// Inject version into index.html
if (version) {
html = html.replace(
'const JAEGER_VERSION = DEFAULT_VERSION;',
`const JAEGER_VERSION = ${JSON.stringify(version)};`
Comment on lines +140 to +157
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSON.stringify calls on lines 129, 138, and 146 inject configuration data into a script tag but don't escape the string </script>. If the backend returns configuration containing </script> in any string value, it could prematurely close the script tag. While the risk is low (requires malicious localhost backend), consider using .replace(/<\/script>/gi, '<\\/script>') on the JSON.stringify output as a defense-in-depth measure. This follows best practices for injecting JSON into HTML script contexts.

Copilot uses AI. Check for mistakes.
);
}
Comment on lines +137 to +159
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple JSON.stringify calls (lines 131, 140, 148) are used on data fetched from the backend without error handling. If the backend returns objects with circular references or other non-serializable content, these calls will throw and crash the dev server during HTML transformation. Consider wrapping these operations in try-catch blocks or at minimum documenting the assumption that backend data is always JSON-serializable.

Copilot uses AI. Check for mistakes.

return html;
},
},
Expand Down
5 changes: 5 additions & 0 deletions verify_otel.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* This file previously contained a standalone OpenTelemetry verification script.
* It has been intentionally left empty to avoid keeping unreferenced tooling
* at the repository root.
*/
Comment on lines +2 to +5
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file has been intentionally emptied but not removed. If the file is no longer needed and there are no references to it, consider deleting it entirely rather than leaving an empty file with a comment. An empty file in the repository root can be confusing for future contributors who might wonder if it serves a purpose.

Suggested change
* This file previously contained a standalone OpenTelemetry verification script.
* It has been intentionally left empty to avoid keeping unreferenced tooling
* at the repository root.
*/
* Deprecated OpenTelemetry verification entrypoint.
*
* This script is kept only for backward compatibility with existing tooling
* or documentation that may still reference `verify_otel.cjs`.
* It no longer performs any verification.
*/
if (require.main === module) {
console.warn(
'verify_otel.cjs is deprecated and no longer performs any checks. ' +
'Please remove any references to this script.'
);
}

Copilot uses AI. Check for mistakes.
Loading