Skip to content

Commit

Permalink
fix(dashboard): limit number of log lines that are fetched (#461)
Browse files Browse the repository at this point in the history
  • Loading branch information
eysi09 committed Jan 25, 2019
1 parent b06eb4a commit 41390a1
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 101 deletions.
12 changes: 8 additions & 4 deletions dashboard/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ import axios from "axios"
import {
FetchConfigResponse,
FetchStatusResponse,
FetchLogResponse,
FetchLogsResponse,
ApiRequest,
FetchGraphResponse,
} from "./types"

export type FetchLogsParam = string[]

const MAX_LOG_LINES = 5000

export async function fetchConfig(): Promise<FetchConfigResponse> {
return apiPost<FetchConfigResponse>("get.config")
}
Expand All @@ -28,9 +32,9 @@ export async function fetchStatus(): Promise<FetchStatusResponse> {
return apiPost<FetchStatusResponse>("get.status")
}

export async function fetchLogs(services?: string[]): Promise<FetchLogResponse> {
const params = services ? { service: services } : {}
return apiPost<FetchLogResponse>("logs", params)
export async function fetchLogs(services: FetchLogsParam): Promise<FetchLogsResponse> {
const tail = Math.floor(MAX_LOG_LINES / services.length)
return apiPost<FetchLogsResponse>("logs", { services, tail })
}

async function apiPost<T>(command: string, parameters: {} = {}): Promise<T> {
Expand Down
2 changes: 1 addition & 1 deletion dashboard/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export interface ServiceLogEntry {
msg: string
}

export type FetchLogResponse = ServiceLogEntry[]
export type FetchLogsResponse = ServiceLogEntry[]

export interface ApiRequest {
command: string
Expand Down
4 changes: 2 additions & 2 deletions dashboard/src/components/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Wrapper = styled.div`
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
`

const Title = styled.h3`
export const CardTitle = styled.h3`
${fontMedium};
font-size: 1.3rem;
margin: 0;
Expand All @@ -32,7 +32,7 @@ const Card: React.SFC<CardProps> = ({ children, title }) => {
const titleEl = title
? (
<div className="pl-1 pr-1 pb-1">
<Title>{title}</Title>
<CardTitle>{title}</CardTitle>
</div>
)
: null
Expand Down
50 changes: 25 additions & 25 deletions dashboard/src/components/graph/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ const Status = styled.p`
`

const ProcessSpinner = styled(Spinner)`
margin: 20px 0 0 20px;
font-size: 12px;
margin: 16px 0 0 20px;
`

class Chart extends Component<Props, State> {
Expand Down Expand Up @@ -296,44 +295,45 @@ class Chart extends Component<Props, State> {
const chartHeightEstimate = `100vh - 15rem`

let spinner = null
let status = "Ready"
let status = ""
if (message && message.name !== "taskGraphComplete") {
status = "Processing..."
spinner = <ProcessSpinner />
spinner = <ProcessSpinner background={colors.white} fontSize="2px" />
}

return (
<Card>
<div>
<div>
<p>
<Span><span className={css`color: ${colors.gardenGreen};`}></span>Ready</Span>
<Span><span className={css`color: ${colors.gardenPink};`}>-- </span>Pending</Span>
<Span><span className={css`color: red;`}></span>Error</Span>
</p>
<div>
{taskTypes.map(type => (
<label className="ml-1" key={type}>
{capitalize(type)}
<input
type={"checkbox"}
name={type}
checked={!this.state.filters[type]}
onChange={this.onCheckboxChange}
/>
</label>
))}
</div>
{taskTypes.map(type => (
<label className="ml-1" key={type}>
{capitalize(type)}
<input
type={"checkbox"}
name={type}
checked={!this.state.filters[type]}
onChange={this.onCheckboxChange}
/>
</label>
))}
</div>
<div className={css`
height: calc(${chartHeightEstimate});
`} ref={this._chartRef} id="chart">
</div>
<div className={cls(css`
display: flex;
`, "ml-1 pb-1")}>
<Status>{status}</Status>
{spinner}
justify-content: space-between;
`, "ml-1 mr-1 pb-1")}>
<div>
<Status>{status}</Status>
{spinner}
</div>
<p>
<Span><span className={css`color: ${colors.gardenGreen};`}></span>Ready</Span>
<Span><span className={css`color: ${colors.gardenPink};`}>-- </span>Pending</Span>
<Span><span className={css`color: red;`}></span>Error</Span>
</p>
</div>
</div>
</Card>
Expand Down
49 changes: 41 additions & 8 deletions dashboard/src/components/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,40 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import styled from "@emotion/styled/macro"
import { flatten, max } from "lodash"
import React, { Component } from "react"

import Terminal from "./terminal"
import { FetchConfigResponse, FetchLogResponse } from "../api/types"
import { FetchConfigResponse, FetchLogsResponse } from "../api/types"
import Card, { CardTitle } from "./card"
import { colors } from "../styles/variables"
import { LoadLogs } from "../context/data"

interface Props {
config: FetchConfigResponse
logs: FetchLogResponse
logs: FetchLogsResponse
loadLogs: LoadLogs
}

interface State {
selectedService: string
}

const Header = styled.div`
display: flex;
justify-content: space-between;
`

const Icon = styled.i`
color: ${colors.gardenPink};
font-size: 1.5rem;
cursor: pointer;
:active {
color: ${colors.gardenPinkLighten(0.7)}
}
`

class Logs extends Component<Props, State> {

constructor(props) {
Expand All @@ -31,12 +50,18 @@ class Logs extends Component<Props, State> {
selectedService: "all",
}
this.handleChange = this.handleChange.bind(this)
this.refresh = this.refresh.bind(this)
}

handleChange(event) {
this.setState({ selectedService: event.target.value })
}

refresh() {
const serviceNames = flatten(this.props.config.modules.map(m => m.serviceNames))
this.props.loadLogs(serviceNames, true)
}

render() {
const { config, logs } = this.props
const { selectedService } = this.state
Expand All @@ -58,12 +83,20 @@ class Logs extends Component<Props, State> {
))}
</select>
</div>
<Terminal
entries={filteredLogs}
sectionPad={maxServiceName}
title={title}
showServiceName={selectedService === "all"}
/>
<Card>
<div>
<Header className="pl-1 pr-1 pb-1">
<CardTitle>{title}</CardTitle>
<Icon className={"fas fa-sync-alt"} onClick={this.refresh} />
</Header>
<Terminal
entries={filteredLogs}
sectionPad={maxServiceName}
title={title}
showServiceName={selectedService === "all"}
/>
</div>
</Card>
</div>
)
}
Expand Down
39 changes: 18 additions & 21 deletions dashboard/src/components/terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import styled from "@emotion/styled/macro"
import { padEnd } from "lodash"
import React from "react"

import Card from "./card"
import { colors } from "../styles/variables"
import { ServiceLogEntry } from "../api/types"

Expand All @@ -24,7 +23,7 @@ interface Props {
const Term = styled.div`
background-color: ${colors.lightBlack};
border-radius: 2px;
max-height: 25rem;
max-height: 45rem;
overflow-y: auto;
`

Expand All @@ -44,26 +43,24 @@ const Timestamp = styled.span`

// FIXME Use whitespace instead of dots for the sectinon padding.
// For some reason whitespace is not rendered inside spans.
const Terminal: React.SFC<Props> = ({ entries, sectionPad, showServiceName, title }) => {
const Terminal: React.SFC<Props> = ({ entries, sectionPad, showServiceName }) => {
return (
<Card title={title}>
<Term className="p-1">
<code>
{entries.map((e, idx) => {
const service = showServiceName
? <Service>{padEnd(e.serviceName, sectionPad + 3, ".")}</Service>
: ""
return (
<P key={idx}>
{service}
<Timestamp>[{e.timestamp}] </Timestamp>
{e.msg}
</P>
)
})}
</code>
</Term>
</Card>
<Term className="p-1">
<code>
{entries.map((e, idx) => {
const service = showServiceName
? <Service>{padEnd(e.serviceName, sectionPad + 3, ".")}</Service>
: ""
return (
<P key={idx}>
{service}
<Timestamp>[{e.timestamp}] </Timestamp>
{e.msg}
</P>
)
})}
</code>
</Term>
)
}

Expand Down
34 changes: 27 additions & 7 deletions dashboard/src/containers/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { flatten } from "lodash"
import React, { useContext, useEffect } from "react"

import PageError from "../components/page-error"
Expand All @@ -15,19 +16,38 @@ import { DataContext } from "../context/data"

export default () => {
const {
actions: { loadLogs, loadConfig },
store: { config, logs },
actions: { loadConfig },
store: { config },
} = useContext(DataContext)

useEffect(loadConfig, [])
useEffect(loadLogs, [])

const isLoading = !config.data || !logs.data || config.loading || logs.loading
const error = config.error || logs.error
const isLoading = !config.data || config.loading

return (
<LoadWrapper error={error} ErrorComponent={PageError} loading={isLoading}>
<Logs config={config.data} logs={logs.data} />
<LoadWrapper error={config.error} ErrorComponent={PageError} loading={isLoading}>
<LogsContainer />
</LoadWrapper>
)
}

const LogsContainer = () => {
const {
actions: { loadLogs },
store: { config, logs },
} = useContext(DataContext)

const serviceNames = flatten(config.data.modules.map(m => m.serviceNames))
useEffect(() => {
loadLogs(serviceNames)
}, [])

const isLoading = !logs.data

return (
<LoadWrapper error={logs.error} ErrorComponent={PageError} loading={isLoading}>
<Logs loadLogs={loadLogs} config={config.data} logs={logs.data} />
</LoadWrapper>
)

}
Loading

0 comments on commit 41390a1

Please sign in to comment.