119 lines
3.1 KiB
JavaScript
119 lines
3.1 KiB
JavaScript
// Copyright 2018 Red Hat, Inc
|
|
//
|
|
// 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
|
|
//
|
|
// http://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 Axios from 'axios'
|
|
|
|
export const LOGFILE_FETCH_REQUEST = 'LOGFILE_FETCH_REQUEST'
|
|
export const LOGFILE_FETCH_SUCCESS = 'LOGFILE_FETCH_SUCCESS'
|
|
export const LOGFILE_FETCH_FAIL = 'LOGFILE_FETCH_FAIL'
|
|
|
|
export const requestLogfile = (url) => ({
|
|
type: LOGFILE_FETCH_REQUEST,
|
|
url: url,
|
|
})
|
|
|
|
const SYSLOGDATE = '\\w+\\s+\\d+\\s+\\d{2}:\\d{2}:\\d{2}((\\.|\\,)\\d{3,6})?'
|
|
const DATEFMT = '\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}((\\.|\\,)\\d{3,6})?'
|
|
const STATUSFMT = '(DEBUG|INFO|WARNING|ERROR|TRACE|AUDIT|CRITICAL)'
|
|
|
|
const severityMap = {
|
|
DEBUG: 1,
|
|
INFO: 2,
|
|
WARNING: 3,
|
|
ERROR: 4,
|
|
TRACE: 5,
|
|
AUDIT: 6,
|
|
CRITICAL: 7,
|
|
}
|
|
|
|
const OSLO_LOGMATCH = new RegExp(`^(${DATEFMT})(( \\d+)? (${STATUSFMT}).*)`)
|
|
const SYSTEMD_LOGMATCH = new RegExp(`^(${SYSLOGDATE})( (\\S+) \\S+\\[\\d+\\]\\: (${STATUSFMT}).*)`)
|
|
|
|
const receiveLogfile = (buildId, file, data) => {
|
|
|
|
const out = data.split(/\r?\n/).map((line, idx) => {
|
|
let m = null
|
|
let sev = null
|
|
|
|
m = SYSTEMD_LOGMATCH.exec(line)
|
|
if (m) {
|
|
sev = severityMap[m[7]]
|
|
} else {
|
|
OSLO_LOGMATCH.exec(line)
|
|
if (m) {
|
|
sev = severityMap[m[7]]
|
|
}
|
|
}
|
|
|
|
return {
|
|
text: line,
|
|
index: idx+1,
|
|
severity: sev
|
|
}
|
|
})
|
|
return {
|
|
type: LOGFILE_FETCH_SUCCESS,
|
|
buildId,
|
|
fileName: file,
|
|
fileContent: out,
|
|
receivedAt: Date.now()
|
|
}
|
|
}
|
|
|
|
const failedLogfile = (error, url) => {
|
|
error.url = url
|
|
return {
|
|
type: LOGFILE_FETCH_FAIL,
|
|
error
|
|
}
|
|
}
|
|
|
|
export function fetchLogfile(buildId, file, state) {
|
|
return async function (dispatch) {
|
|
// Don't do anything if the logfile is already part of our local state
|
|
if (
|
|
buildId in state.logfile.files &&
|
|
file in state.logfile.files[buildId]
|
|
) {
|
|
return Promise.resolve()
|
|
}
|
|
// Since this method is only called after fetchBuild() and fetchManifest(),
|
|
// we can assume both are there.
|
|
const build = state.build.builds[buildId]
|
|
const manifest = state.build.manifests[buildId]
|
|
const item = manifest.index['/' + file]
|
|
|
|
if (!item) {
|
|
return dispatch(
|
|
failedLogfile(Error(`No manifest entry found for logfile "${file}"`))
|
|
)
|
|
}
|
|
|
|
if (item.mimetype !== 'text/plain') {
|
|
return dispatch(
|
|
failedLogfile(Error(`Logfile "${file}" has invalid mimetype`))
|
|
)
|
|
}
|
|
|
|
const url = build.log_url + file
|
|
dispatch(requestLogfile())
|
|
try {
|
|
const response = await Axios.get(url, { transformResponse: [] })
|
|
dispatch(receiveLogfile(buildId, file, response.data))
|
|
} catch(error) {
|
|
dispatch(failedLogfile(error, url))
|
|
}
|
|
}
|
|
}
|