Skip to content

Commit fff05bc

Browse files
authored
Merge pull request #86 from austb/logging_class
Add Logger and a setting to manage all log output
2 parents 2ca9344 + 8175ca1 commit fff05bc

File tree

6 files changed

+128
-41
lines changed

6 files changed

+128
-41
lines changed

client/package.json

+5
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@
104104
"type":"string",
105105
"default": "",
106106
"description": "Set the local Puppet Language Server to send debug information to a file"
107+
},
108+
"puppet.languageclient.minimumUserLogLevel": {
109+
"type": "string",
110+
"default": "normal",
111+
"description": "Set the minimum log level that the user will see on the Puppet OutputChannel (Allowed values: verbose, debug, normal, warning, error)"
107112
}
108113
}
109114
}

client/src/commands/puppetResourceCommand.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import * as vscode from 'vscode';
44
import { PuppetResourceRequestParams, PuppetResourceRequest } from '../messages';
55
import { IConnectionManager, ConnectionStatus } from '../connection';
6+
import { Logger } from '../logging';
67

78
class RequestParams implements PuppetResourceRequestParams {
89
typename: string;
@@ -11,9 +12,11 @@ class RequestParams implements PuppetResourceRequestParams {
1112

1213
export class puppetResourceCommand {
1314
private _connectionManager: IConnectionManager = undefined;
15+
private logger: Logger = undefined;
1416

15-
constructor(connMgr: IConnectionManager) {
17+
constructor(connMgr: IConnectionManager, logger: Logger) {
1618
this._connectionManager = connMgr;
19+
this.logger = logger;
1720
}
1821

1922
private pickPuppetResource(): Thenable<string> {
@@ -47,8 +50,7 @@ export class puppetResourceCommand {
4750
.sendRequest(PuppetResourceRequest.type, requestParams)
4851
.then( (resourceResult) => {
4952
if (resourceResult.error != undefined && resourceResult.error.length > 0) {
50-
// TODO Log any errors
51-
console.error(resourceResult.error);
53+
this.logger.error(resourceResult.error);
5254
return;
5355
}
5456
if (resourceResult.data == undefined || resourceResult.data.length == 0) return;

client/src/connection.ts

+26-34
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import net = require('net');
22
import path = require('path');
33
import vscode = require('vscode');
44
import cp = require('child_process');
5+
import { Logger } from '../src/logging';
56
import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient';
67
import { setupPuppetCommands } from '../src/puppetcommands';
78
import * as messages from '../src/messages';
@@ -43,9 +44,9 @@ export class ConnectionManager implements IConnectionManager {
4344
private connectionConfiguration: IConnectionConfiguration;
4445
private languageServerClient: LanguageClient = undefined;
4546
private languageServerProcess = undefined;
46-
private puppetOutputChannel = undefined;
4747
private extensionContext = undefined;
4848
private commandsRegistered = false;
49+
private logger: Logger = undefined;
4950

5051
public get status() : ConnectionStatus {
5152
return this.connectionStatus;
@@ -54,9 +55,8 @@ export class ConnectionManager implements IConnectionManager {
5455
return this.languageServerClient;
5556
}
5657

57-
constructor(context: vscode.ExtensionContext) {
58-
this.puppetOutputChannel = vscode.window.createOutputChannel('Puppet');
59-
58+
constructor(context: vscode.ExtensionContext, logger: Logger) {
59+
this.logger = logger;
6060
this.extensionContext = context;
6161
}
6262

@@ -67,10 +67,9 @@ export class ConnectionManager implements IConnectionManager {
6767
var contextPath = this.extensionContext.asAbsolutePath(path.join('vendor', 'languageserver', 'puppet-languageserver'));
6868

6969
if (!this.commandsRegistered) {
70-
this.puppetOutputChannel.appendLine('Configuring commands');
71-
console.log('Configuring commands');
70+
this.logger.debug('Configuring commands');
7271

73-
setupPuppetCommands(langID, this, this.extensionContext);
72+
setupPuppetCommands(langID, this, this.extensionContext, this.logger);
7473
this.commandsRegistered = true;
7574
}
7675

@@ -89,7 +88,7 @@ export class ConnectionManager implements IConnectionManager {
8988
this.setConnectionStatus("Starting Puppet...", ConnectionStatus.Starting);
9089

9190
if (this.connectionConfiguration.type == ConnectionType.Local) {
92-
this.languageServerProcess = this.createLanguageServerProcess(contextPath, this.puppetOutputChannel);
91+
this.languageServerProcess = this.createLanguageServerProcess(contextPath);
9392
if (this.languageServerProcess == undefined) {
9493
if (this.connectionStatus == ConnectionStatus.Failed) {
9594
// We've already handled this state. Just return
@@ -99,8 +98,7 @@ export class ConnectionManager implements IConnectionManager {
9998
}
10099

101100
this.languageServerProcess.stdout.on('data', (data) => {
102-
console.log("OUTPUT: " + data.toString());
103-
this.puppetOutputChannel.appendLine("OUTPUT: " + data.toString());
101+
this.logger.debug("OUTPUT: " + data.toString());
104102

105103
// If the language client isn't already running and it's sent the trigger text, start up a client
106104
if ( (this.languageServerClient == undefined) && (data.toString().match("LANGUAGE SERVER RUNNING") != null) ) {
@@ -110,22 +108,19 @@ export class ConnectionManager implements IConnectionManager {
110108
});
111109

112110
this.languageServerProcess.on('close', (exitCode) => {
113-
console.log("SERVER terminated with exit code: " + exitCode);
114-
this.puppetOutputChannel.appendLine("SERVER terminated with exit code: " + exitCode);
111+
this.logger.debug("SERVER terminated with exit code: " + exitCode);
115112
});
116113
}
117114
else {
118115
this.languageServerClient = this.startLangClientTCP();
119116
this.extensionContext.subscriptions.push(this.languageServerClient.start());
120117
}
121118

122-
console.log('Congratulations, your extension "vscode-puppet" is now active!');
123-
this.puppetOutputChannel.appendLine('Congratulations, your extension "vscode-puppet" is now active!');
119+
this.logger.debug('Congratulations, your extension "vscode-puppet" is now active!');
124120
}
125121

126122
public stop() {
127-
console.log('Stopping...');
128-
this.puppetOutputChannel.appendLine('Stopping...')
123+
this.logger.debug('Stopping...')
129124

130125
if (this.connectionStatus === ConnectionStatus.Failed) {
131126
this.languageServerClient = undefined;
@@ -150,14 +145,12 @@ export class ConnectionManager implements IConnectionManager {
150145
}
151146

152147
this.connectionStatus = ConnectionStatus.NotStarted;
153-
154-
console.log('Stopped');
155-
this.puppetOutputChannel.appendLine('Stopped');
148+
149+
this.logger.debug('Stopped');
156150
}
157151

158152
public dispose() : void {
159-
console.log('Disposing...');
160-
this.puppetOutputChannel.appendLine('Disposing...');
153+
this.logger.debug('Disposing...');
161154
// Stop the current session
162155
this.stop();
163156

@@ -166,8 +159,8 @@ export class ConnectionManager implements IConnectionManager {
166159
this.extensionContext.subscriptions.clear();
167160
}
168161

169-
private createLanguageServerProcess(serverExe: string, myOutputChannel: vscode.OutputChannel) {
170-
myOutputChannel.appendLine('Language server found at: ' + serverExe)
162+
private createLanguageServerProcess(serverExe: string) {
163+
this.logger.debug('Language server found at: ' + serverExe)
171164

172165
let cmd: string = undefined;
173166
let args = [serverExe];
@@ -208,7 +201,7 @@ export class ConnectionManager implements IConnectionManager {
208201
};
209202
break;
210203
default:
211-
myOutputChannel.appendLine('Starting language server')
204+
this.logger.debug('Starting language server')
212205

213206
// Try and find the puppet-agent ruby
214207
let rubyPath: string = '/opt/puppetlabs/puppet/bin/ruby';
@@ -241,17 +234,15 @@ export class ConnectionManager implements IConnectionManager {
241234
args.push('--debug=' + this.connectionConfiguration.debugFilePath);
242235
}
243236

244-
console.log("Starting the language server with " + cmd + " " + args.join(" "));
245-
myOutputChannel.appendLine("Starting the language server with " + cmd + " " + args.join(" "));
237+
this.logger.debug("Starting the language server with " + cmd + " " + args.join(" "));
246238
var proc = cp.spawn(cmd, args, options)
247-
console.log("ProcID = " + proc.pid);
248-
myOutputChannel.appendLine('Language server PID:' + proc.pid)
239+
this.logger.debug('Language server PID:' + proc.pid)
249240

250241
return proc;
251242
}
252243

253244
private startLangClientTCP(): LanguageClient {
254-
this.puppetOutputChannel.appendLine('Configuring language server options')
245+
this.logger.debug('Configuring language server options')
255246

256247
var connMgr:ConnectionManager = this;
257248
let serverOptions: ServerOptions = function () {
@@ -261,24 +252,25 @@ export class ConnectionManager implements IConnectionManager {
261252
resolve({ reader: client, writer: client });
262253
});
263254
client.on('error', function (err) {
264-
console.log(`[Puppet Lang Server Client] ` + err);
255+
this.logger.error(`[Puppet Lang Server Client] ` + err);
265256
connMgr.setSessionFailure("Could not start language client: ", err.message);
266-
257+
267258
return null;
268259
})
269260
});
270261
}
271262

272-
this.puppetOutputChannel.appendLine('Configuring language server client options')
263+
this.logger.debug('Configuring language server client options')
273264
let clientOptions: LanguageClientOptions = {
274265
documentSelector: [langID],
275266
}
276267

277-
this.puppetOutputChannel.appendLine(`Starting language server client (host ${this.connectionConfiguration.host} port ${this.connectionConfiguration.port})`)
268+
this.logger.debug(`Starting language server client (host ${this.connectionConfiguration.host} port ${this.connectionConfiguration.port})`)
269+
278270
var title = `tcp lang server (host ${this.connectionConfiguration.host} port ${this.connectionConfiguration.port})`;
279271
var languageServerClient = new LanguageClient(title, serverOptions, clientOptions)
280272
languageServerClient.onReady().then(() => {
281-
this.puppetOutputChannel.appendLine('Language server client started, setting puppet version')
273+
this.logger.debug('Language server client started, setting puppet version')
282274
languageServerClient.sendRequest(messages.PuppetVersionRequest.type).then((versionDetails) => {
283275
this.setConnectionStatus(versionDetails.puppetVersion, ConnectionStatus.Running);
284276
});

client/src/extension.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as vscode from 'vscode';
44
import * as path from 'path';
55

66
import { ConnectionManager, IConnectionConfiguration, ConnectionType } from './connection';
7+
import { Logger } from './logging';
78

89
const langID = 'puppet'; // don't change this
910
var statusBarItem;
@@ -31,10 +32,10 @@ export class ConnectionConfiguration implements IConnectionConfiguration {
3132
}
3233

3334
export function activate(context: vscode.ExtensionContext) {
34-
connManager = new ConnectionManager(context);
35+
var logger = new Logger();
36+
connManager = new ConnectionManager(context, logger);
3537

3638
var configSettings = new ConnectionConfiguration(context);
37-
3839
connManager.start(configSettings);
3940
}
4041

client/src/logging.ts

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'use strict';
2+
3+
import * as vscode from 'vscode';
4+
5+
export enum LogLevel {
6+
Verbose,
7+
Debug,
8+
Normal,
9+
Warning,
10+
Error
11+
}
12+
13+
export class Logger {
14+
15+
private logChannel: vscode.OutputChannel;
16+
17+
// Minimum log level that is shown to users on logChannel
18+
private minimumUserLogLevel: LogLevel = undefined;
19+
20+
constructor() {
21+
this.logChannel = vscode.window.createOutputChannel("Puppet");
22+
this.logChannel.show();
23+
24+
let config = vscode.workspace.getConfiguration('puppet');
25+
let logLevelName = config['languageclient']['minimumUserLogLevel'];
26+
let logLevel = this.logLevelFromString(logLevelName);
27+
28+
if(logLevel == undefined) {
29+
this.minimumUserLogLevel = LogLevel.Normal;
30+
this.error("Logger could not interpret " + logLevelName + " as a log level setting");
31+
} else {
32+
this.minimumUserLogLevel = logLevel;
33+
}
34+
}
35+
36+
public verbose(message: string) {
37+
this.logWithLevel(LogLevel.Verbose, message);
38+
}
39+
40+
public debug(message: string) {
41+
this.logWithLevel(LogLevel.Debug, message);
42+
}
43+
44+
public normal(message: string) {
45+
this.logWithLevel(LogLevel.Normal, message);
46+
}
47+
48+
public warning(message: string) {
49+
this.logWithLevel(LogLevel.Warning, message);
50+
}
51+
52+
public error(message: string) {
53+
this.logWithLevel(LogLevel.Error, message);
54+
}
55+
56+
private logWithLevel(level: LogLevel, message) {
57+
let logMessage = this.logLevelPrefixAsString(level) + message
58+
59+
console.log(logMessage);
60+
if (level >= this.minimumUserLogLevel) {
61+
this.logChannel.appendLine(logMessage);
62+
}
63+
}
64+
65+
private logLevelFromString(logLevelName: String): LogLevel {
66+
switch (logLevelName.toLowerCase()) {
67+
case "verbose": return LogLevel.Verbose;
68+
case "debug": return LogLevel.Debug;
69+
case "normal": return LogLevel.Normal;
70+
case "warning": return LogLevel.Warning;
71+
case "error": return LogLevel.Error;
72+
default: return undefined;
73+
}
74+
}
75+
76+
private logLevelPrefixAsString(level: LogLevel): String {
77+
switch (level) {
78+
case LogLevel.Verbose: return "VERBOSE: ";
79+
case LogLevel.Debug: return "DEBUG: ";
80+
case LogLevel.Warning: return "WARNING: ";
81+
case LogLevel.Error: return "ERROR: ";
82+
default: return "";
83+
}
84+
}
85+
}
86+

client/src/puppetcommands.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { puppetResourceCommand } from '../src/commands/puppetResourceCommand';
33
import * as messages from '../src/messages';
44
import { PuppetNodeGraphContentProvider, isNodeGraphFile, getNodeGraphUri, showNodeGraph } from '../src/providers/previewNodeGraphProvider';
55
import { IConnectionManager } from './connection';
6+
import { Logger } from './logging';
67

7-
export function setupPuppetCommands(langID:string, connManager:IConnectionManager, ctx:vscode.ExtensionContext){
8+
export function setupPuppetCommands(langID:string, connManager:IConnectionManager, ctx:vscode.ExtensionContext, logger: Logger){
89

9-
let resourceCommand = new puppetResourceCommand(connManager);
10+
let resourceCommand = new puppetResourceCommand(connManager, logger);
1011
ctx.subscriptions.push(resourceCommand);
1112
ctx.subscriptions.push(vscode.commands.registerCommand(messages.PuppetCommandStrings.PuppetResourceCommandId, () => {
1213
resourceCommand.run();

0 commit comments

Comments
 (0)