Skip to content

Commit 430e930

Browse files
Redirect bricks logs to a file as well (#280)
```json {"level":"info","logger":"Bricks","message":"2022/12/05 22:46:15 [INFO] Remote file sync location: /Repos/kartik.gupta@databricks.com/Test","timestamp":1670276775608} {"level":"info","logger":"Bricks","message":"","timestamp":1670276775608} {"level":"info","logger":"Bricks","message":"2022/12/05 22:46:15 [INFO] Loading dogfood profile from /Users/kartik.gupta/.databrickscfg","timestamp":1670276775608} {"level":"debug","logger":"Bricks","message":"2022/12/05 22:46:15 [DEBUG] GET /api/2.0/repos ","timestamp":1670276775608} {"level":"debug","logger":"Bricks","message":"","timestamp":1670276775608} {"level":"debug","logger":"Bricks","message":"2022/12/05 22:46:16 [DEBUG] 200 OK {","timestamp":1670276776498} {"level":"debug","logger":"Bricks","message":" \"repos\": [","timestamp":1670276776499} {"level":"debug","logger":"Bricks","message":" {","timestamp":1670276776500} {"level":"debug","logger":"Bricks","message":" \"id\": 2600307357294504,","timestamp":1670276776500} {"level":"debug","logger":"Bricks","message":" \"path\": \"/Repos/kartik.gupta@databricks.com/Test\"","timestamp":1670276776500} {"level":"debug","logger":"Bricks","message":" }","timestamp":1670276776501} {"level":"debug","logger":"Bricks","message":" ]","timestamp":1670276776501} {"level":"debug","logger":"Bricks","message":"} <- GET /api/2.0/repos?path_prefix=%2FRepos%2Fkartik.gupta%40databricks.com%2FTest","timestamp":1670276776501} {"level":"debug","logger":"Bricks","message":"","timestamp":1670276776502} {"level":"info","logger":"Bricks","message":"2022/12/05 22:46:17 [INFO] Initial Sync Complete","timestamp":1670276777509} {"level":"info","logger":"Bricks","message":"","timestamp":1670276777511} ```
1 parent a542d93 commit 430e930

File tree

6 files changed

+99
-29
lines changed

6 files changed

+99
-29
lines changed

packages/databricks-sdk-js/src/logging/NamedLogger.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ export class NamedLogger {
8989
}
9090

9191
log(level: string, message?: string, meta?: any) {
92+
if (level === "error") {
93+
if (Object(meta) === meta) {
94+
meta = {
95+
...Object.getOwnPropertyNames(meta).reduce((acc, i) => {
96+
acc[i] = (meta as any)[i];
97+
return acc;
98+
}, {} as any),
99+
...(meta as any),
100+
};
101+
}
102+
103+
meta = {error: meta};
104+
}
105+
92106
meta = defaultRedactor.sanitize(
93107
meta,
94108
this._loggerOpts?.fieldNameDenyList
@@ -109,16 +123,7 @@ export class NamedLogger {
109123
}
110124

111125
error(message?: string, obj?: any) {
112-
if (Object(obj) === obj) {
113-
obj = {
114-
...Object.getOwnPropertyNames(obj).reduce((acc, i) => {
115-
acc[i] = (obj as any)[i];
116-
return acc;
117-
}, {} as any),
118-
...(obj as any),
119-
};
120-
}
121-
this.log(LEVELS.error, message, {error: obj});
126+
this.log(LEVELS.error, message, obj);
122127
}
123128

124129
withContext({

packages/databricks-vscode/src/cli/BricksSyncParser.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import "@databricks/databricks-sdk";
12
import assert from "assert";
23
import {mock} from "ts-mockito";
34
import {EventEmitter} from "vscode";

packages/databricks-vscode/src/cli/BricksSyncParser.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
import {LEVELS, NamedLogger} from "@databricks/databricks-sdk/dist/logging";
12
import {EventEmitter} from "vscode";
3+
import {Loggers} from "../logger";
24
import {SyncState} from "../sync";
35

6+
const bricksLogLevelToSdk = new Map<string, LEVELS>([
7+
["DEBUG", LEVELS.debug],
8+
["INFO", LEVELS.info],
9+
["WARN", LEVELS.warn],
10+
["ERROR", LEVELS.error],
11+
]);
12+
413
export class BricksSyncParser {
514
private filesBeingUploaded = new Set<string>();
615
private filesBeingDeleted = new Set<string>();
@@ -118,8 +127,19 @@ export class BricksSyncParser {
118127
// TODO: Use structed logging to compute the sync state here
119128
public process(data: string) {
120129
const logLines = data.split("\n");
130+
let currentLogLevel: LEVELS = LEVELS.info;
121131
for (let i = 0; i < logLines.length; i++) {
122132
const line = logLines[i];
133+
const typeMatch = line.match(
134+
/[0-9]+(?:\/[0-9]+)+ [0-9]+(?::[0-9]+)+ \[(.+)\]/
135+
);
136+
if (typeMatch) {
137+
currentLogLevel =
138+
bricksLogLevelToSdk.get(typeMatch[1]) ?? currentLogLevel;
139+
}
140+
141+
NamedLogger.getOrCreate(Loggers.Bricks).log(currentLogLevel, line);
142+
123143
this.parseForActionsInitiated(line);
124144
this.parseForUploadCompleted(line);
125145
this.parseForDeleteCompleted(line);

packages/databricks-vscode/src/cli/BricksTasks.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import "@databricks/databricks-sdk/dist";
1+
import "@databricks/databricks-sdk";
22
import * as assert from "assert";
33
import {instance, mock, when} from "ts-mockito";
44
import {Uri} from "vscode";

packages/databricks-vscode/src/logger/LoggerManager.test.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,25 @@ describe(__filename, function () {
2626
const manager = new LoggerManager(instance(mockContext));
2727
await manager.initLoggers();
2828
NamedLogger.getOrCreate(Loggers.Extension).debug("test message");
29+
NamedLogger.getOrCreate(Loggers.Bricks).debug("test message");
2930

3031
await new Promise((resolve) =>
3132
setTimeout(
3233
resolve,
3334
new Time(0.5, TimeUnits.seconds).toMillSeconds().value
3435
)
3536
);
36-
37-
const rawLogs = await readFile(path.join(tempDir, "logs.json"), {
38-
encoding: "utf-8",
39-
});
40-
41-
const logs = rawLogs.split("\n");
42-
assert.ok(logs.length !== 0);
43-
assert.ok(logs[0].includes("test message"));
37+
["sdk-and-extension-logs.json", "bricks-logs.json"].forEach(
38+
async (logfile) => {
39+
const rawLogs = await readFile(path.join(tempDir, logfile), {
40+
encoding: "utf-8",
41+
});
42+
43+
const logs = rawLogs.split("\n");
44+
assert.ok(logs.length !== 0);
45+
assert.ok(logs[0].includes("test message"));
46+
}
47+
);
4448
});
4549

4650
afterEach(async () => {

packages/databricks-vscode/src/logger/LoggerManager.ts

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ import path from "path";
1111
export class LoggerManager {
1212
constructor(readonly context: ExtensionContext) {}
1313

14+
private async getLogFile(prefix: string) {
15+
await mkdir(this.context.logUri.fsPath, {recursive: true});
16+
const logFile = path.join(
17+
this.context.logUri.fsPath,
18+
`${prefix}-logs.json`
19+
);
20+
try {
21+
await access(logFile);
22+
await unlink(logFile);
23+
} catch (e) {}
24+
25+
return logFile;
26+
}
27+
1428
private getFileTransport(
1529
filename: string,
1630
extraOptions?: Omit<
@@ -27,15 +41,12 @@ export class LoggerManager {
2741

2842
async initLoggers() {
2943
const outputChannel = window.createOutputChannel("Databricks Logs");
30-
await mkdir(this.context.logUri.fsPath, {recursive: true});
31-
const logFile = path.join(this.context.logUri.fsPath, "logs.json");
32-
try {
33-
await access(logFile);
34-
await unlink(logFile);
35-
} catch (e) {}
36-
3744
outputChannel.clear();
3845

46+
const sdkAndExtensionLogfile = await this.getLogFile(
47+
"sdk-and-extension"
48+
);
49+
3950
NamedLogger.getOrCreate(
4051
ExposedLoggers.SDK,
4152
{
@@ -45,7 +56,9 @@ export class LoggerManager {
4556
getOutputConsoleTransport(outputChannel, {
4657
level: "debug",
4758
}),
48-
this.getFileTransport(logFile, {level: "debug"}),
59+
this.getFileTransport(sdkAndExtensionLogfile, {
60+
level: "debug",
61+
}),
4962
],
5063
});
5164
},
@@ -65,7 +78,32 @@ export class LoggerManager {
6578
getOutputConsoleTransport(outputChannel, {
6679
level: "error",
6780
}),
68-
this.getFileTransport(logFile, {level: "debug"}),
81+
this.getFileTransport(sdkAndExtensionLogfile, {
82+
level: "debug",
83+
}),
84+
],
85+
});
86+
},
87+
},
88+
true
89+
);
90+
91+
const bricksLogFile = await this.getLogFile("bricks");
92+
/**
93+
This logger collects all the output from bricks.
94+
*/
95+
NamedLogger.getOrCreate(
96+
"Bricks",
97+
{
98+
factory: (name) => {
99+
return loggers.add(name, {
100+
transports: [
101+
getOutputConsoleTransport(outputChannel, {
102+
level: "error",
103+
}),
104+
this.getFileTransport(bricksLogFile, {
105+
level: "debug",
106+
}),
69107
],
70108
});
71109
},
@@ -79,7 +117,9 @@ export class LoggerManager {
79117
}
80118
}
81119

120+
/* eslint-disable @typescript-eslint/naming-convention */
82121
export enum Loggers {
83-
// eslint-disable-next-line @typescript-eslint/naming-convention
84122
Extension = "Extension",
123+
Bricks = "Bricks",
85124
}
125+
/* eslint-enable @typescript-eslint/naming-convention */

0 commit comments

Comments
 (0)