Skip to content

Commit 9bd5eea

Browse files
frontend: Add integration with linux2rest journal
Signed-off-by: Patrick José Pereira <[email protected]>
1 parent 63cd1de commit 9bd5eea

File tree

4 files changed

+149
-0
lines changed

4 files changed

+149
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<template>
2+
<v-container fluid>
3+
<v-row>
4+
<v-col>
5+
<v-sheet
6+
min-height="70vh"
7+
rounded="lg"
8+
>
9+
<v-card elevation="0">
10+
<v-virtual-scroll
11+
:item-height="20"
12+
:items="entries"
13+
height="700px"
14+
>
15+
<template #default="{ item }">
16+
<v-list-item>
17+
<v-list-item-content>
18+
<v-list-item-title
19+
class="pa-0"
20+
:class="priorityClass(item.priority)"
21+
>
22+
{{ formatTimestamp(item.timestamp) }}
23+
[{{ priorityLabel(item.priority) }}]
24+
<span v-if="sourceLabel(item)">{{ sourceLabel(item) }}:</span>
25+
{{ item.message }}
26+
</v-list-item-title>
27+
</v-list-item-content>
28+
</v-list-item>
29+
</template>
30+
</v-virtual-scroll>
31+
</v-card>
32+
</v-sheet>
33+
</v-col>
34+
</v-row>
35+
</v-container>
36+
</template>
37+
38+
<script lang="ts">
39+
import Vue from 'vue'
40+
41+
import system_information, { FetchType } from '@/store/system-information'
42+
import { JournalEntry } from '@/types/system-information/journal'
43+
44+
export default Vue.extend({
45+
name: 'Journal',
46+
computed: {
47+
entries(): JournalEntry[] {
48+
return system_information?.journal_entries ?? []
49+
},
50+
},
51+
created() {
52+
system_information.fetchSystemInformation(FetchType.JournalType)
53+
},
54+
methods: {
55+
formatTimestamp(value?: string): string {
56+
if (!value) {
57+
return 'Unknown time'
58+
}
59+
const date = new Date(value)
60+
if (Number.isNaN(date.getTime())) {
61+
return value
62+
}
63+
return date.toLocaleString()
64+
},
65+
sourceLabel(entry: JournalEntry): string | null {
66+
if (entry.identifier) {
67+
return entry.identifier
68+
}
69+
return null
70+
},
71+
priorityLabel(priority?: number): string {
72+
const map: Record<number, string> = {
73+
0: 'Emergency',
74+
1: 'Alert',
75+
2: 'Critical',
76+
3: 'Error',
77+
4: 'Warning',
78+
5: 'Notice',
79+
6: 'Info',
80+
7: 'Debug',
81+
}
82+
if (priority === undefined || priority === null) {
83+
return map[6]
84+
}
85+
return map[priority] ?? map[6]
86+
},
87+
priorityClass(priority?: number): string {
88+
const priorityColors: Record<number, string> = {
89+
0: 'red darken-4 white--text',
90+
1: 'deep-orange darken-3 white--text',
91+
2: 'pink darken-2 white--text',
92+
3: 'red darken-1 white--text',
93+
4: 'amber darken-2 black--text',
94+
5: 'cyan darken-1 white--text',
95+
6: 'indigo lighten-5 black--text',
96+
7: 'green darken-3 white--text',
97+
}
98+
// eslint-disable-next-line eqeqeq
99+
if (priority == undefined) {
100+
return priorityColors[6]
101+
}
102+
return priorityColors[priority] ?? priorityColors[6]
103+
},
104+
},
105+
})
106+
</script>

core/frontend/src/store/system-information.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { OneMoreTime } from '@/one-more-time'
1111
import store from '@/store'
1212
import { system_information_service } from '@/types/frontend_services'
1313
import { KernelMessage } from '@/types/system-information/kernel'
14+
import { JournalEntry, JournalResponse } from '@/types/system-information/journal'
1415
import { Model } from '@/types/system-information/model'
1516
import { Netstat } from '@/types/system-information/netstat'
1617
import { Platform } from '@/types/system-information/platform'
@@ -22,6 +23,7 @@ import back_axios, { isBackendOffline } from '@/utils/api'
2223

2324
export enum FetchType {
2425
KernelType = 'kernel_buffer',
26+
JournalType = 'journal',
2527
ModelType = 'model',
2628
NetstatType = 'netstat',
2729
PlatformType = 'platform',
@@ -49,6 +51,8 @@ class SystemInformationStore extends VuexModule {
4951

5052
kernel_message: KernelMessage[] = []
5153

54+
journal_entries: JournalEntry[] = []
55+
5256
model: Model | null = null
5357

5458
netstat: Netstat | null = null
@@ -78,6 +82,11 @@ class SystemInformationStore extends VuexModule {
7882
this.kernel_message = this.kernel_message.concat(kernel_message)
7983
}
8084

85+
@Mutation
86+
appendJournalEntries(response: JournalResponse): void {
87+
this.journal_entries = this.journal_entries.concat(response.entries)
88+
}
89+
8190
@Mutation
8291
updateModel(model: Model): void {
8392
this.model = model
@@ -88,6 +97,11 @@ class SystemInformationStore extends VuexModule {
8897
this.kernel_message = kernel_message
8998
}
9099

100+
@Mutation
101+
updateJournalEntries(response: JournalResponse): void {
102+
this.journal_entries = response.entries
103+
}
104+
91105
@Mutation
92106
updateNetstat(netstat: Netstat): void {
93107
this.netstat = netstat
@@ -269,6 +283,10 @@ class SystemInformationStore extends VuexModule {
269283
case FetchType.KernelType:
270284
this.updateKernelMessage(response.data)
271285
break
286+
case FetchType.JournalType: {
287+
this.updateJournalEntries(response.data)
288+
break
289+
}
272290
case FetchType.ModelType:
273291
this.updateModel(response.data)
274292
break
@@ -339,4 +357,13 @@ socket.onmessage = (message) => {
339357
system_information.appendKernelMessage(JSON.parse(message.data))
340358
}
341359

360+
const journalWebsocketUrl = `${protocol}://${window.location.host}${system_information.API_URL}/ws/journal`
361+
const journalSocket = new WebSocket(journalWebsocketUrl)
362+
journalSocket.onmessage = (message) => {
363+
const payload = JSON.parse(message.data)
364+
system_information.appendJournalEntries(payload)
365+
}
366+
367+
system_information.fetchSystemInformation(FetchType.JournalType)
368+
342369
export default system_information
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export interface JournalEntry {
2+
cursor?: string,
3+
timestamp?: string,
4+
priority?: number,
5+
identifier?: string,
6+
unit?: string,
7+
pid?: number,
8+
hostname?: string,
9+
message: string,
10+
}

core/frontend/src/views/SystemInformationView.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<system-condition v-else-if="page.value === 'system_condition'" />
2727
<network v-else-if="page.value === 'network'" />
2828
<kernel v-else-if="page.value === 'kernel'" />
29+
<journal v-else-if="page.value === 'journal'" />
2930
<firmware v-else-if="page.value === 'firmware'" />
3031
<about-this-system v-else-if="page.value === 'about'" />
3132
</v-tab-item>
@@ -38,6 +39,7 @@ import Vue from 'vue'
3839
3940
import AboutThisSystem from '@/components/system-information/AboutThisSystem.vue'
4041
import Firmware from '@/components/system-information/Firmware.vue'
42+
import Journal from '@/components/system-information/Journal.vue'
4143
import Kernel from '@/components/system-information/Kernel.vue'
4244
import Network from '@/components/system-information/Network.vue'
4345
import Processes from '@/components/system-information/Processes.vue'
@@ -56,6 +58,7 @@ export default Vue.extend({
5658
components: {
5759
AboutThisSystem,
5860
Firmware,
61+
Journal,
5962
Kernel,
6063
Network,
6164
Processes,
@@ -71,6 +74,9 @@ export default Vue.extend({
7174
{
7275
title: 'Kernel', icon: 'mdi-text-long', value: 'kernel', is_pirate: true,
7376
},
77+
{
78+
title: 'Journal', icon: 'mdi-notebook-outline', value: 'journal', is_pirate: true,
79+
},
7480
{
7581
title: 'Firmware', icon: 'mdi-raspberry-pi', value: 'firmware', is_pirate: true,
7682
},

0 commit comments

Comments
 (0)