Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Logger util #36

Merged
merged 6 commits into from
Jul 15, 2024
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
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@typescript-eslint/semi": "warn",
"curly": "warn",
"eqeqeq": ["warn", "always", { "null": "ignore" }],
"no-console": "warn",
"no-throw-literal": "warn",
"semi": "off"
},
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
{
"command": "vscode-deephaven.selectConnection",
"title": "Deephaven: Select Connection"
},
{
"command": "vscode-deephaven.downloadLogs",
"title": "Deephaven: Download Logs"
}
],
"menus": {
Expand Down
3 changes: 3 additions & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ export const CONFIG_KEY = 'vscode-deephaven';
export const CONFIG_CORE_SERVERS = 'core-servers';

// export const DHFS_SCHEME = 'dhfs';
export const DOWNLOAD_LOGS_CMD = `${CONFIG_KEY}.downloadLogs`;
export const RUN_CODE_COMMAND = `${CONFIG_KEY}.runCode`;
export const RUN_SELECTION_COMMAND = `${CONFIG_KEY}.runSelection`;
export const SELECT_CONNECTION_COMMAND = `${CONFIG_KEY}.selectConnection`;

export const STATUS_BAR_DISCONNECTED_TEXT = 'Deephaven: Disconnected';
export const STATUS_BAR_DISCONNECT_TEXT = 'Deephaven: Disconnect';
export const STATUS_BAR_CONNECTING_TEXT = 'Deephaven: Connecting...';

export const DOWNLOAD_LOGS_TEXT = 'Download Logs';
67 changes: 52 additions & 15 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,41 @@ import {
createConnectionOptions,
createConnectionQuickPick,
getTempDir,
Logger,
Toaster,
} from './util';
import { DhcService } from './services';
import { DhServiceRegistry } from './services';
import {
DOWNLOAD_LOGS_CMD,
RUN_CODE_COMMAND,
RUN_SELECTION_COMMAND,
SELECT_CONNECTION_COMMAND,
} from './common';
import { OutputChannelWithHistory } from './util/OutputChannelWithHistory';

export function activate(context: vscode.ExtensionContext) {
console.log(
'Congratulations, your extension "vscode-deephaven" is now active!'
);
const logger = new Logger('extension');

export function activate(context: vscode.ExtensionContext) {
let selectedConnectionUrl: string | null = null;
let selectedDhService: DhcService | null = null;
let connectionOptions = createConnectionOptions();

const outputChannel = vscode.window.createOutputChannel('Deephaven', 'log');
const debugOutputChannel = new OutputChannelWithHistory(
context,
vscode.window.createOutputChannel('Deephaven Debug', 'log')
);
const toaster = new Toaster();

// Configure log handlers
Logger.addConsoleHandler();
Logger.addOutputChannelHandler(debugOutputChannel);

logger.info(
'Congratulations, your extension "vscode-deephaven" is now active!'
);

outputChannel.appendLine('Deephaven extension activated');

// Update connection options when configuration changes
Expand All @@ -41,13 +57,12 @@ export function activate(context: vscode.ExtensionContext) {
const dhcServiceRegistry = new DhServiceRegistry(
DhcService,
new ExtendedMap<string, vscode.WebviewPanel>(),
outputChannel
outputChannel,
toaster
);

dhcServiceRegistry.addEventListener('disconnect', serverUrl => {
vscode.window.showInformationMessage(
`Disconnected from Deephaven server: ${serverUrl}`
);
toaster.info(`Disconnected from Deephaven server: ${serverUrl}`);
clearConnection();
});

Expand Down Expand Up @@ -79,15 +94,19 @@ export function activate(context: vscode.ExtensionContext) {
}

/** Register extension commands */
const { runCodeCmd, runSelectionCmd, selectConnectionCmd } = registerCommands(
() => connectionOptions,
getActiveDhService,
onConnectionSelected
);
const { downloadLogsCmd, runCodeCmd, runSelectionCmd, selectConnectionCmd } =
registerCommands(
() => connectionOptions,
getActiveDhService,
onConnectionSelected,
onDownloadLogs
);

const connectStatusBarItem = createConnectStatusBarItem();

context.subscriptions.push(
debugOutputChannel,
downloadLogsCmd,
dhcServiceRegistry,
outputChannel,
runCodeCmd,
Expand All @@ -99,6 +118,18 @@ export function activate(context: vscode.ExtensionContext) {
// recreate tmp dir that will be used to dowload JS Apis
getTempDir(true /*recreate*/);

/**
* Handle download logs command
*/
async function onDownloadLogs() {
const uri = await debugOutputChannel.downloadHistoryToFile();

if (uri != null) {
toaster.info(`Downloaded logs to ${uri.fsPath}`);
vscode.window.showTextDocument(uri);
}
}

/**
* Handle connection selection
*/
Expand Down Expand Up @@ -163,8 +194,14 @@ async function ensureUriEditorIsActive(uri: vscode.Uri) {
function registerCommands(
getConnectionOptions: () => ConnectionOption[],
getActiveDhService: (autoActivate: boolean) => Promise<DhcService | null>,
onConnectionSelected: (connectionUrl: string | null) => void
onConnectionSelected: (connectionUrl: string | null) => void,
onDownloadLogs: () => void
) {
const downloadLogsCmd = vscode.commands.registerCommand(
DOWNLOAD_LOGS_CMD,
onDownloadLogs
);

/** Run all code in active editor */
const runCodeCmd = vscode.commands.registerCommand(
RUN_CODE_COMMAND,
Expand Down Expand Up @@ -213,5 +250,5 @@ function registerCommands(
}
);

return { runCodeCmd, runSelectionCmd, selectConnectionCmd };
return { downloadLogsCmd, runCodeCmd, runSelectionCmd, selectConnectionCmd };
}
8 changes: 5 additions & 3 deletions src/services/CacheService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Disposable } from '../common';
import { isDisposable } from '../util';
import { isDisposable, Logger } from '../util';
import { EventDispatcher } from './EventDispatcher';

const logger = new Logger('CacheService');

export class CacheService<T, TEventName extends string>
extends EventDispatcher<TEventName>
implements Disposable
Expand All @@ -27,7 +29,7 @@ export class CacheService<T, TEventName extends string>
const normalizeKey = this.normalizeKey(key);

if (!this.cachedPromises.has(normalizeKey)) {
console.log(`${this.label}: caching key: ${normalizeKey}`);
logger.info(`${this.label}: caching key: ${normalizeKey}`);
// Note that we cache the promise itself, not the result of the promise.
// This helps ensure the loader is only called the first time `get` is
// called.
Expand All @@ -49,7 +51,7 @@ export class CacheService<T, TEventName extends string>
}
});
} catch (err) {
console.error('An error occurred while disposing cached values:', err);
logger.error('An error occurred while disposing cached values:', err);
}

this.cachedPromises.clear();
Expand Down
31 changes: 16 additions & 15 deletions src/services/DhService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import * as vscode from 'vscode';
import type { dh as DhcType } from '../dh/dhc-types';
import { hasErrorCode } from '../util/typeUtils';
import { ConnectionAndSession, Disposable } from '../common';
import { ExtendedMap, formatTimestamp } from '../util';
import { ExtendedMap, formatTimestamp, Logger, Toaster } from '../util';
import { EventDispatcher } from './EventDispatcher';

const logger = new Logger('DhService');

/* eslint-disable @typescript-eslint/naming-convention */
const icons = {
Figure: '📈',
Expand Down Expand Up @@ -33,19 +35,22 @@ export abstract class DhService<TDH, TClient>
constructor(
serverUrl: string,
panelRegistry: ExtendedMap<string, vscode.WebviewPanel>,
outputChannel: vscode.OutputChannel
outputChannel: vscode.OutputChannel,
toaster: Toaster
) {
super();

this.serverUrl = serverUrl;
this.panelRegistry = panelRegistry;
this.outputChannel = outputChannel;
this.toaster = toaster;
}

public readonly serverUrl: string;
protected readonly subscriptions: (() => void)[] = [];

protected outputChannel: vscode.OutputChannel;
protected toaster: Toaster;
private panelRegistry: ExtendedMap<string, vscode.WebviewPanel>;
private cachedCreateClient: Promise<TClient> | null = null;
private cachedCreateSession: Promise<ConnectionAndSession<
Expand Down Expand Up @@ -118,11 +123,11 @@ export abstract class DhService<TDH, TClient>
);
} catch (err) {
this.clearCaches();
console.error(err);
logger.error(err);
this.outputChannel.appendLine(
`Failed to initialize Deephaven API${err == null ? '.' : `: ${err}`}`
);
vscode.window.showErrorMessage('Failed to initialize Deephaven API');
this.toaster.error('Failed to initialize Deephaven API');
return false;
}

Expand Down Expand Up @@ -172,15 +177,13 @@ export abstract class DhService<TDH, TClient>
if (this.cn == null || this.session == null) {
this.clearCaches();

vscode.window.showErrorMessage(
this.toaster.error(
`Failed to create Deephaven session: ${this.serverUrl}`
);

return false;
} else {
vscode.window.showInformationMessage(
`Created Deephaven session: ${this.serverUrl}`
);
this.toaster.info(`Created Deephaven session: ${this.serverUrl}`);

return true;
}
Expand All @@ -192,7 +195,7 @@ export abstract class DhService<TDH, TClient>
): Promise<void> {
if (editor.document.languageId !== 'python') {
// This should not actually happen
console.log(`languageId '${editor.document.languageId}' not supported.`);
logger.info(`languageId '${editor.document.languageId}' not supported.`);
return;
}

Expand Down Expand Up @@ -220,7 +223,7 @@ export abstract class DhService<TDH, TClient>

const text = editor.document.getText(selectionRange);

console.log('Sending text to dh:', text);
logger.info('Sending text to dh:', text);

let result: CommandResultBase;
let error: string | null = null;
Expand All @@ -235,20 +238,18 @@ export abstract class DhService<TDH, TClient>
// clear the caches on connection disconnect
if (hasErrorCode(err, 16)) {
this.clearCaches();
vscode.window.showErrorMessage(
this.toaster.error(
'Session is no longer invalid. Please re-run the command to reconnect.'
);
return;
}
}

if (error) {
console.error(error);
logger.error(error);
this.outputChannel.show(true);
this.outputChannel.appendLine(error);
vscode.window.showErrorMessage(
'An error occurred when running a command'
);
this.toaster.error('An error occurred when running a command');

return;
}
Expand Down
8 changes: 5 additions & 3 deletions src/services/DhServiceRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as vscode from 'vscode';
import { CacheService } from './CacheService';
import { DhcService, DhcServiceConstructor } from './DhcService';
import { ensureHasTrailingSlash, ExtendedMap } from '../util';
import { ensureHasTrailingSlash, ExtendedMap, Toaster } from '../util';

export class DhServiceRegistry<T extends DhcService> extends CacheService<
T,
Expand All @@ -10,7 +10,8 @@ export class DhServiceRegistry<T extends DhcService> extends CacheService<
constructor(
serviceFactory: DhcServiceConstructor<T>,
panelRegistry: ExtendedMap<string, vscode.WebviewPanel>,
outputChannel: vscode.OutputChannel
outputChannel: vscode.OutputChannel,
toaster: Toaster
) {
super(
serviceFactory.name,
Expand All @@ -22,7 +23,8 @@ export class DhServiceRegistry<T extends DhcService> extends CacheService<
const dhService = new serviceFactory(
serverUrl,
panelRegistry,
outputChannel
outputChannel,
toaster
);

// Propagate service events as registry events.
Expand Down
11 changes: 7 additions & 4 deletions src/services/DhcService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import {
initDhcApi,
initDhcSession,
} from '../dh/dhc';
import { ExtendedMap, getPanelHtml } from '../util';
import { ExtendedMap, getPanelHtml, Logger, Toaster } from '../util';
import { ConnectionAndSession } from '../common';

const logger = new Logger('DhcService');

export type DhcServiceConstructor<T extends DhcService> = new (
serverUrl: string,
panelRegistry: ExtendedMap<string, vscode.WebviewPanel>,
outputChannel: vscode.OutputChannel
outputChannel: vscode.OutputChannel,
toaster: Toaster
) => T;

export class DhcService extends DhService<typeof DhcType, DhcType.CoreClient> {
Expand All @@ -30,7 +33,7 @@ export class DhcService extends DhService<typeof DhcType, DhcType.CoreClient> {
try {
return new dh.CoreClient(this.serverUrl);
} catch (err) {
console.error(err);
logger.error(err);
throw err;
}
}
Expand Down Expand Up @@ -68,7 +71,7 @@ export class DhcService extends DhService<typeof DhcType, DhcType.CoreClient> {
this.psk = token;
}
} catch (err) {
console.error(err);
logger.error(err);
}

return connectionAndSession;
Expand Down
7 changes: 5 additions & 2 deletions src/services/PanelFocusManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import * as vscode from 'vscode';
import { Logger } from '../util';

const logger = new Logger('PanelFocusManager');

/*
* Panels steal focus when they finish loading which causes the run
Expand Down Expand Up @@ -26,7 +29,7 @@ export class PanelFocusManager {
>();

initialize(panel: vscode.WebviewPanel): void {
console.log('Initializing panel:', panel.title, 2);
logger.info('Initializing panel:', panel.title, 2);

// Only count the last panel initialized
this.panelsPendingInitialFocus = new WeakMap();
Expand Down Expand Up @@ -59,7 +62,7 @@ export class PanelFocusManager {

const pendingChangeCount = this.panelsPendingInitialFocus.get(panel) ?? 0;

console.log('Panel view state changed:', {
logger.info('Panel view state changed:', {
panelTitle: panel.title,
activeEditorViewColumn,
activeTabGroupViewColumn,
Expand Down
Loading