Skip to content

Commit 720ee0d

Browse files
feat: add node logs command (#337)
Signed-off-by: Jeffrey Tang <[email protected]>
1 parent fe727e1 commit 720ee0d

11 files changed

+106
-8
lines changed

.github/workflows/zxc-e2e-test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ jobs:
182182
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
183183
with:
184184
name: solo-${{ inputs.npm-test-script }}.log
185-
path: ~/.solo/logs/solo.log
185+
path: ~/.solo/logs/*
186186
overwrite: true
187187
if-no-files-found: error
188188

src/commands/node.mjs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { Listr } from 'listr2'
2121
import path from 'path'
2222
import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs'
2323
import * as helpers from '../core/helpers.mjs'
24-
import { getTmpDir, sleep, validatePath } from '../core/helpers.mjs'
24+
import { getNodeLogs, getTmpDir, sleep, validatePath } from '../core/helpers.mjs'
2525
import { constants, Templates } from '../core/index.mjs'
2626
import { BaseCommand } from './base.mjs'
2727
import * as flags from './flags.mjs'
@@ -1072,6 +1072,45 @@ export class NodeCommand extends BaseCommand {
10721072
return true
10731073
}
10741074

1075+
async logs (argv) {
1076+
const self = this
1077+
1078+
const tasks = new Listr([
1079+
{
1080+
title: 'Initialize',
1081+
task: async (ctx, task) => {
1082+
await prompts.execute(task, self.configManager, [
1083+
flags.nodeIDs
1084+
])
1085+
1086+
ctx.config = {
1087+
nodeIds: helpers.parseNodeIds(self.configManager.getFlag(flags.nodeIDs))
1088+
}
1089+
self.logger.debug('Initialized config', { config: ctx.config })
1090+
}
1091+
},
1092+
{
1093+
title: 'Copy logs from all nodes',
1094+
task: (ctx, _) => {
1095+
getNodeLogs(this.k8, flags.namespace)
1096+
}
1097+
}
1098+
], {
1099+
concurrent: false,
1100+
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION
1101+
})
1102+
1103+
try {
1104+
await tasks.run()
1105+
} catch (e) {
1106+
throw new FullstackTestingError(`Error in downloading log from nodes: ${e.message}`, e)
1107+
} finally {
1108+
await self.close()
1109+
}
1110+
1111+
return true
1112+
}
1113+
10751114
async add (argv) {
10761115
const self = this
10771116

@@ -1652,6 +1691,25 @@ export class NodeCommand extends BaseCommand {
16521691
})
16531692
}
16541693
})
1694+
.command({
1695+
command: 'logs',
1696+
desc: 'Download application logs from the network nodes and stores them in <SOLO_LOGS_DIR>/<namespace>/<podName>/ directory',
1697+
builder: y => flags.setCommandFlags(y,
1698+
flags.nodeIDs
1699+
),
1700+
handler: argv => {
1701+
nodeCmd.logger.debug('==== Running \'node logs\' ===')
1702+
nodeCmd.logger.debug(argv)
1703+
1704+
nodeCmd.logs(argv).then(r => {
1705+
nodeCmd.logger.debug('==== Finished running `node logs`====')
1706+
if (!r) process.exit(1)
1707+
}).catch(err => {
1708+
nodeCmd.logger.showUserError(err)
1709+
process.exit(1)
1710+
})
1711+
}
1712+
})
16551713
.command({
16561714
command: 'add',
16571715
desc: 'Adds a node with a specific version of Hedera platform',

src/core/helpers.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import * as paths from 'path'
2323
import { fileURLToPath } from 'url'
2424
import * as semver from 'semver'
2525
import { Templates } from './templates.mjs'
26+
import { HEDERA_HAPI_PATH, ROOT_CONTAINER, SOLO_LOGS_DIR } from './constants.mjs'
2627

2728
// cache current directory
2829
const CUR_FILE_DIR = paths.dirname(fileURLToPath(import.meta.url))
@@ -182,3 +183,30 @@ export function validatePath (input) {
182183
}
183184
return input
184185
}
186+
187+
/**
188+
* Download logs files from all network pods and save to local solo log directory
189+
* @param {k8}
190+
* an instance of core/K8
191+
* @returns {Promise<void>} A promise that resolves when the logs are downloaded
192+
*/
193+
export async function getNodeLogs (k8, namespace) {
194+
const pods = await k8.getPodsByLabel(['fullstack.hedera.com/type=network-node'])
195+
196+
for (const pod of pods) {
197+
const podName = pod.metadata.name
198+
const targetDir = `${SOLO_LOGS_DIR}/${namespace}/${podName}`
199+
try {
200+
if (fs.existsSync(targetDir)) {
201+
fs.rmdirSync(targetDir, { recursive: true })
202+
}
203+
fs.mkdirSync(targetDir, { recursive: true })
204+
await k8.copyFrom(podName, ROOT_CONTAINER, `${HEDERA_HAPI_PATH}/output/swirlds.log`, targetDir)
205+
await k8.copyFrom(podName, ROOT_CONTAINER, `${HEDERA_HAPI_PATH}/output/hgcaa.log`, targetDir)
206+
} catch (e) {
207+
// not throw error here, so we can continue to finish downloading logs from other pods
208+
// and also delete namespace in the end
209+
k8.logger.error(`failed to download logs from pod ${podName}`, e)
210+
}
211+
}
212+
}

test/e2e/commands/account.test.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
} from '../../test_util.js'
3838
import { AccountCommand } from '../../../src/commands/account.mjs'
3939
import { flags } from '../../../src/commands/index.mjs'
40+
import { getNodeLogs } from '../../../src/core/helpers.mjs'
4041

4142
describe('AccountCommand', () => {
4243
const testName = 'account-cmd-e2e'
@@ -62,6 +63,7 @@ describe('AccountCommand', () => {
6263
const accountCmd = new AccountCommand(bootstrapResp.opts, testSystemAccounts)
6364

6465
afterAll(async () => {
66+
await getNodeLogs(k8, namespace)
6567
await k8.deleteNamespace(namespace)
6668
await accountManager.close()
6769
await nodeCmd.close()

test/e2e/commands/cluster.test.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
logging
3535
} from '../../../src/core/index.mjs'
3636
import { flags } from '../../../src/commands/index.mjs'
37-
import { sleep } from '../../../src/core/helpers.mjs'
37+
import { getNodeLogs, sleep } from '../../../src/core/helpers.mjs'
3838
import * as version from '../../../version.mjs'
3939

4040
describe('ClusterCommand', () => {
@@ -66,6 +66,7 @@ describe('ClusterCommand', () => {
6666
const clusterCmd = bootstrapResp.cmd.clusterCmd
6767

6868
afterAll(async () => {
69+
await getNodeLogs(k8, namespace)
6970
await k8.deleteNamespace(namespace)
7071
await accountManager.close()
7172
})

test/e2e/commands/mirror_node.test.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
TEST_CLUSTER
3737
} from '../../test_util.js'
3838
import * as version from '../../../version.mjs'
39-
import { sleep } from '../../../src/core/helpers.mjs'
39+
import { getNodeLogs, sleep } from '../../../src/core/helpers.mjs'
4040
import { MirrorNodeCommand } from '../../../src/commands/mirror_node.mjs'
4141
import * as core from '../../../src/core/index.mjs'
4242
import { Status, TopicCreateTransaction, TopicMessageSubmitTransaction } from '@hashgraph/sdk'
@@ -75,6 +75,7 @@ describe('MirrorNodeCommand', () => {
7575
})
7676

7777
afterAll(async () => {
78+
await getNodeLogs(k8, namespace)
7879
await k8.deleteNamespace(namespace)
7980
await accountManager.close()
8081

test/e2e/commands/network.test.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
} from '../../../src/core/index.mjs'
3535
import { flags } from '../../../src/commands/index.mjs'
3636
import * as version from '../../../version.mjs'
37-
import { sleep } from '../../../src/core/helpers.mjs'
37+
import { getNodeLogs, sleep } from '../../../src/core/helpers.mjs'
3838
import path from 'path'
3939
import fs from 'fs'
4040

@@ -67,6 +67,7 @@ describe('NetworkCommand', () => {
6767
const clusterCmd = bootstrapResp.cmd.clusterCmd
6868

6969
afterAll(async () => {
70+
await getNodeLogs(k8, namespace)
7071
await k8.deleteNamespace(namespace)
7172
await accountManager.close()
7273
})

test/e2e/commands/node-local-hedera.test.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
getDefaultArgv,
2828
TEST_CLUSTER
2929
} from '../../test_util.js'
30+
import { getNodeLogs } from '../../../src/core/helpers.mjs'
3031

3132
describe('Node local build', () => {
3233
const LOCAL_HEDERA = 'local-hedera-app'
@@ -41,6 +42,7 @@ describe('Node local build', () => {
4142

4243
let hederaK8
4344
afterAll(async () => {
45+
await getNodeLogs(hederaK8, LOCAL_HEDERA)
4446
await hederaK8.deleteNamespace(LOCAL_HEDERA)
4547
}, 120000)
4648

test/e2e/commands/node-local-ptt.test.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
getDefaultArgv,
2828
TEST_CLUSTER
2929
} from '../../test_util.js'
30+
import { getNodeLogs } from '../../../src/core/helpers.mjs'
3031

3132
describe('Node local build', () => {
3233
const LOCAL_PTT = 'local-ptt-app'
@@ -41,6 +42,7 @@ describe('Node local build', () => {
4142

4243
let pttK8
4344
afterAll(async () => {
45+
await getNodeLogs(pttK8, LOCAL_PTT)
4446
await pttK8.deleteNamespace(LOCAL_PTT)
4547
}, 120000)
4648

test/e2e/commands/relay.test.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
TEST_CLUSTER
3434
} from '../../test_util.js'
3535
import * as version from '../../../version.mjs'
36-
import { sleep } from '../../../src/core/helpers.mjs'
36+
import { getNodeLogs, sleep } from '../../../src/core/helpers.mjs'
3737
import { RelayCommand } from '../../../src/commands/relay.mjs'
3838

3939
describe('RelayCommand', () => {
@@ -58,6 +58,7 @@ describe('RelayCommand', () => {
5858
const relayCmd = new RelayCommand(bootstrapResp.opts)
5959

6060
afterAll(async () => {
61+
await getNodeLogs(k8, namespace)
6162
await k8.deleteNamespace(namespace)
6263
})
6364

test/e2e/e2e_node_util.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ import {
4343
HEDERA_PLATFORM_VERSION_TAG,
4444
TEST_CLUSTER
4545
} from '../test_util.js'
46-
import { sleep } from '../../src/core/helpers.mjs'
46+
import { getNodeLogs, sleep } from '../../src/core/helpers.mjs'
4747
import path from 'path'
4848
import fs from 'fs'
4949
import crypto from 'crypto'
50+
import { ROOT_CONTAINER } from '../../src/core/constants.mjs'
5051

5152
export function e2eNodeKeyRefreshAddTest (keyFormat, testName, mode, releaseTag = HEDERA_PLATFORM_VERSION_TAG) {
5253
const defaultTimeout = 120000
@@ -75,6 +76,7 @@ export function e2eNodeKeyRefreshAddTest (keyFormat, testName, mode, releaseTag
7576
}, defaultTimeout)
7677

7778
afterAll(async () => {
79+
await getNodeLogs(k8, namespace)
7880
await k8.deleteNamespace(namespace)
7981
}, defaultTimeout)
8082

@@ -308,7 +310,7 @@ export function e2eNodeKeyRefreshAddTest (keyFormat, testName, mode, releaseTag
308310
async function addKeyHashToMap (k8, nodeId, keyDir, uniqueNodeDestDir, keyHashMap, privateKeyFileName) {
309311
await k8.copyFrom(
310312
Templates.renderNetworkPodName(nodeId),
311-
'root-container',
313+
ROOT_CONTAINER,
312314
path.join(keyDir, privateKeyFileName),
313315
uniqueNodeDestDir)
314316
const keyBytes = await fs.readFileSync(path.join(uniqueNodeDestDir, privateKeyFileName))

0 commit comments

Comments
 (0)