-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pw_web: Create log store and enable download logs from it
Fixed: 316966729 Change-Id: I89e406777dbc2aef9baf40e731e9073aab4f966d Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/186874 Presubmit-Verified: CQ Bot Account <[email protected]> Reviewed-by: Luis Flores <[email protected]> Commit-Queue: Amy Hu <[email protected]>
- Loading branch information
Amy Hu
authored and
CQ Bot Account
committed
Feb 23, 2024
1 parent
ff074e7
commit 9c1540d
Showing
6 changed files
with
167 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright 2023 The Pigweed Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy of | ||
// the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations under | ||
// the License. | ||
|
||
import { LogEntry } from './shared/interfaces'; | ||
import { titleCaseToKebabCase } from './utils/strings'; | ||
|
||
export class LogStore { | ||
private logs: LogEntry[]; | ||
|
||
constructor() { | ||
this.logs = []; | ||
} | ||
|
||
addLogEntry(logEntry: LogEntry) { | ||
this.logs.push(logEntry); | ||
} | ||
|
||
downloadLogs(event: CustomEvent) { | ||
const logs = this.getLogs(); | ||
const headers = logs[0]?.fields.map((field) => field.key) || []; | ||
const maxWidths = headers.map((header) => header.length); | ||
const viewTitle = event.detail.viewTitle; | ||
const fileName = viewTitle ? titleCaseToKebabCase(viewTitle) : 'logs'; | ||
|
||
logs.forEach((log) => { | ||
log.fields.forEach((field, columnIndex) => { | ||
maxWidths[columnIndex] = Math.max( | ||
maxWidths[columnIndex], | ||
field.value.toString().length, | ||
); | ||
}); | ||
}); | ||
|
||
const headerRow = headers | ||
.map((header, columnIndex) => header.padEnd(maxWidths[columnIndex])) | ||
.join('\t'); | ||
const separator = ''; | ||
const logRows = logs.map((log) => { | ||
const values = log.fields.map((field, columnIndex) => | ||
field.value.toString().padEnd(maxWidths[columnIndex]), | ||
); | ||
return values.join('\t'); | ||
}); | ||
|
||
const formattedLogs = [headerRow, separator, ...logRows].join('\n'); | ||
const blob = new Blob([formattedLogs], { type: 'text/plain' }); | ||
const downloadLink = document.createElement('a'); | ||
downloadLink.href = URL.createObjectURL(blob); | ||
downloadLink.download = `${fileName}.txt`; | ||
downloadLink.click(); | ||
|
||
URL.revokeObjectURL(downloadLink.href); | ||
} | ||
|
||
getLogs(): LogEntry[] { | ||
return this.logs; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright 2023 The Pigweed Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy of | ||
// the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations under | ||
// the License. | ||
|
||
import { expect } from '@open-wc/testing'; | ||
import { createLogViewer } from '../src/createLogViewer'; | ||
import { MockLogSource } from '../src/custom/mock-log-source'; | ||
import { LogStore } from '../src/log-store'; | ||
|
||
// Initialize the log viewer component with a mock log source | ||
function setUpLogViewer() { | ||
const mockLogSource = new MockLogSource(); | ||
const logStore = new LogStore(); | ||
const destroyLogViewer = createLogViewer( | ||
document.body, | ||
undefined, | ||
logStore, | ||
mockLogSource, | ||
); | ||
const logViewer = document.querySelector('log-viewer'); | ||
return { mockLogSource, destroyLogViewer, logViewer, logStore }; | ||
} | ||
|
||
// Handle benign ResizeObserver error caused by custom log viewer initialization | ||
// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors | ||
function handleResizeObserverError() { | ||
const e = window.onerror; | ||
window.onerror = function (err) { | ||
if ( | ||
err === 'ResizeObserver loop completed with undelivered notifications.' | ||
) { | ||
console.warn( | ||
'Ignored: ResizeObserver loop completed with undelivered notifications.', | ||
); | ||
return false; | ||
} else { | ||
return e(...arguments); | ||
} | ||
}; | ||
} | ||
|
||
describe('log-store', () => { | ||
let mockLogSource; | ||
let destroyLogViewer; | ||
let logViewer; | ||
let logStore; | ||
|
||
beforeEach(() => { | ||
window.localStorage.clear(); | ||
({ mockLogSource, destroyLogViewer, logViewer, logStore } = | ||
setUpLogViewer()); | ||
handleResizeObserverError(); | ||
}); | ||
|
||
afterEach(() => { | ||
mockLogSource.stop(); | ||
destroyLogViewer(); | ||
}); | ||
|
||
it('should maintain log entries emitted', async () => { | ||
const logEntry = mockLogSource.readLogEntryFromHost(); | ||
mockLogSource.publishLogEntry(logEntry); | ||
const logs = logStore.getLogs(); | ||
|
||
expect(logs.length).equal(1); | ||
expect(logs[0]).equal(logEntry); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters