Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import stripAnsi from 'strip-ansi';

import Logger from 'teleterm/logger';
import { RootClusterUri } from 'teleterm/ui/uri';
import { createFileLoggerService, LoggerColor } from 'teleterm/services/logger';

import { generateAgentConfigPaths } from '../createAgentConfigFile';
import { AgentProcessState, RuntimeSettings } from '../types';
Expand Down Expand Up @@ -131,6 +132,19 @@ export class AgentRunner {
});

const spawnHandler = () => {
const { logsDirectory } = generateAgentConfigPaths(
this.settings,
rootClusterUri
);
createFileLoggerService({
dev: this.settings.dev,
dir: logsDirectory,
name: 'teleport',
loggerNameColor: LoggerColor.Green,
passThroughMode: true,
omitTimestamp: true,
}).pipeProcessOutputIntoLogger(process);

this.updateProcessState(rootClusterUri, {
status: 'running',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export function generateAgentConfigPaths(
): {
agentDirectory: string;
configFile: string;
logsDirectory: string;
dataDirectory: string;
} {
const parsed = routing.parseClusterUri(rootClusterUri);
Expand All @@ -123,11 +124,13 @@ export function generateAgentConfigPaths(
);
const configFile = path.resolve(agentDirectory, 'config.yaml');
const dataDirectory = path.resolve(agentDirectory, 'data');
const logsDirectory = path.resolve(agentDirectory, 'logs');

return {
agentDirectory,
configFile,
dataDirectory,
logsDirectory,
};
}

Expand Down
4 changes: 4 additions & 0 deletions web/packages/teleterm/src/mainProcess/fixtures/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ export class MockMainProcessClient implements MainProcessClient {
return Promise.resolve(false);
}

openAgentLogsDirectory() {
return Promise.resolve();
}

killAgent(): Promise<void> {
return Promise.resolve();
}
Expand Down
36 changes: 34 additions & 2 deletions web/packages/teleterm/src/mainProcess/mainProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
createAgentConfigFile,
isAgentConfigFileCreated,
removeAgentDirectory,
generateAgentConfigPaths,
} from './createAgentConfigFile';
import { AgentRunner } from './agentRunner';
import { terminateWithTimeout } from './terminateWithTimeout';
Expand Down Expand Up @@ -384,6 +385,25 @@ export default class MainProcess {
}
);

ipcMain.handle(
'main-process-open-agent-logs-directory',
async (
_,
args: {
rootClusterUri: RootClusterUri;
}
) => {
const { logsDirectory } = generateAgentConfigPaths(
this.settings,
args.rootClusterUri
);
const error = await shell.openPath(logsDirectory);
Comment thread
ravicious marked this conversation as resolved.
if (error) {
throw new Error(error);
}
Comment thread
ravicious marked this conversation as resolved.
}
);

subscribeToTerminalContextMenuEvent();
subscribeToTabContextMenuEvent();
subscribeToConfigServiceEvents(this.configService);
Expand All @@ -392,6 +412,13 @@ export default class MainProcess {

private _setAppMenu() {
const isMac = this.settings.platform === 'darwin';
const commonHelpTemplate: MenuItemConstructorOptions[] = [
{ label: 'Open Documentation', click: openDocsUrl },
{
label: 'Open Logs Directory',
click: () => openLogsDirectory(this.settings),
},
];

// Enable actions like reload or toggle dev tools only in dev mode.
const viewMenuTemplate: MenuItemConstructorOptions = this.settings.dev
Expand All @@ -417,7 +444,7 @@ export default class MainProcess {
},
{
role: 'help',
submenu: [{ label: 'Learn More', click: openDocsUrl }],
submenu: commonHelpTemplate,
},
];

Expand All @@ -429,7 +456,8 @@ export default class MainProcess {
{
role: 'help',
submenu: [
{ label: 'Learn More', click: openDocsUrl },
...commonHelpTemplate,
{ type: 'separator' },
{ role: 'about' },
],
},
Expand Down Expand Up @@ -509,6 +537,10 @@ function openDocsUrl() {
shell.openExternal(DOCS_URL);
}

function openLogsDirectory(settings: RuntimeSettings) {
shell.openPath(settings.logsDir);
}

/** Shares promise returned from `promiseFn` across multiple concurrent callers. */
function sharePromise<T>(promiseFn: () => Promise<T>): () => Promise<T> {
let pending: Promise<T> | undefined = undefined;
Expand Down
8 changes: 8 additions & 0 deletions web/packages/teleterm/src/mainProcess/mainProcessClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ export default function createMainProcessClient(): MainProcessClient {
clusterProperties
);
},
openAgentLogsDirectory(clusterProperties: {
rootClusterUri: RootClusterUri;
}) {
return ipcRenderer.invoke(
'main-process-open-agent-logs-directory',
clusterProperties
);
},
killAgent(clusterProperties: { rootClusterUri: RootClusterUri }) {
return ipcRenderer.invoke(
'main-process-connect-my-computer-kill-agent',
Expand Down
3 changes: 3 additions & 0 deletions web/packages/teleterm/src/mainProcess/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export type MainProcessClient = {
createAgentConfigFile(
properties: AgentConfigFileClusterProperties
): Promise<void>;
openAgentLogsDirectory(args: {
rootClusterUri: RootClusterUri;
}): Promise<void>;
runAgent(args: { rootClusterUri: RootClusterUri }): Promise<void>;
isAgentConfigFileCreated(args: {
rootClusterUri: RootClusterUri;
Expand Down
11 changes: 10 additions & 1 deletion web/packages/teleterm/src/services/logger/loggerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ export function createFileLoggerService(
const contextAndLevel = opts.passThroughMode
? ''
: ` [${context}] ${level}:`;
return `[${timestamp}]${contextAndLevel} ${text}`;
const contextLevelAndText = `${contextAndLevel} ${text}`;
return opts.omitTimestamp
? contextLevelAndText
: `[${timestamp}]${contextLevelAndText}`;
})
),
transports: [
Expand Down Expand Up @@ -137,6 +140,7 @@ export enum LoggerColor {
Magenta = '45',
Cyan = '46',
Yellow = '43',
Green = '42',
}

function createLoggerFromWinston(logger: winston.Logger): Logger {
Expand Down Expand Up @@ -181,4 +185,9 @@ type FileLoggerOptions = {
* Mode for logger handling logs from other sources. Log level and context are not included in the log message.
*/
passThroughMode?: boolean;
/**
* Does not add timestamp to log entries.
* This has no effect on dev (console) logs, where timestamps are never added.
* */
omitTimestamp?: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { assertUnreachable } from 'teleterm/ui/utils';
import { codeOrSignal } from 'teleterm/ui/utils/process';
import { connectToServer } from 'teleterm/ui/services/workspacesService';
import { useAppContext } from 'teleterm/ui/appContextProvider';
import { useWorkspaceContext } from 'teleterm/ui/Documents';

import { useAgentProperties } from '../useAgentProperties';
import { Logs } from '../Logs';
Expand Down Expand Up @@ -75,6 +76,7 @@ export function DocumentConnectMyComputerStatus(
removeAgent,
isAgentCompatible,
} = useConnectMyComputerContext();
const { rootClusterUri } = useWorkspaceContext();
const { roleName, systemUsername, hostname } = useAgentProperties();
const { proxyVersion, appVersion, isLocalBuild } = useVersions();

Expand All @@ -100,6 +102,17 @@ export function DocumentConnectMyComputerStatus(
props.closeDocument();
}

async function openAgentLogs(): Promise<void> {
try {
await ctx.mainProcessClient.openAgentLogsDirectory({ rootClusterUri });
} catch (e) {
ctx.notificationsService.notifyError({
title: 'Failed to open agent logs directory',
description: `${e.message}\n\nNote: the logs directory is created only after the agent process successfully spawns.`,
});
}
}

const isRunning =
currentAction.kind === 'observe-process' &&
currentAction.agentProcessState.status === 'running';
Expand Down Expand Up @@ -184,6 +197,7 @@ export function DocumentConnectMyComputerStatus(
},
}}
>
<MenuItem onClick={openAgentLogs}>Open agent logs directory</MenuItem>
<MenuItem onClick={removeAgentAndClose}>Remove agent</MenuItem>
</MenuIcon>
</Flex>
Expand Down