import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import { withContext } from './util/AppContext.jsx';
import { Col, Icon, Row, Table } from 'antd';
import { directionColumn, srcDstColumn } from './util/TapUtils.jsx';
import { formatLatencySec, formatWithComma } from './util/Utils.js';
// https://godoc.org/google.golang.org/grpc/codes#Code
const grpcStatusCodes = {
0: "OK",
1: "Canceled",
2: "Unknown",
3: "InvalidArgument",
4: "DeadlineExceeded",
5: "NotFound",
6: "AlreadyExists",
7: "PermissionDenied",
8: "ResourceExhausted",
9: "FailedPrecondition",
10: "Aborted",
11: "OutOfRange",
12: "Unimplemented",
13: "Internal",
14: "Unavailable",
15: "DataLoss",
16: "Unauthenticated"
};
const smallMetricColWidth = "120px";
const httpStatusCol = {
title: "HTTP status",
key: "http-status",
width: smallMetricColWidth,
dataIndex: "responseInit.http.responseInit",
render: d => !d ? : d.httpStatus
};
const responseInitLatencyCol = {
title: "Latency",
key: "rsp-latency",
width: smallMetricColWidth,
dataIndex: "responseInit.http.responseInit",
render: d => !d ? : formatTapLatency(d.sinceRequestInit)
};
const grpcStatusCol = {
title: "GRPC status",
key: "grpc-status",
width: smallMetricColWidth,
dataIndex: "responseEnd.http.responseEnd",
render: d => !d ? :
_.isNull(d.eos) ? "---" : grpcStatusCodes[_.get(d, "eos.grpcStatusCode")]
};
const pathCol = {
title: "Path",
key: "path",
dataIndex: "requestInit.http.requestInit",
render: d => !d ? : d.path
};
const methodCol = {
title: "Method",
key: "method",
dataIndex: "requestInit.http.requestInit",
render: d => !d ? : _.get(d, "method.registered")
};
const topLevelColumns = (resourceType, ResourceLink) => [
{
title: "Direction",
key: "direction",
dataIndex: "base.proxyDirection",
width: "98px",
filters: [
{ text: "FROM", value: "INBOUND" },
{ text: "TO", value: "OUTBOUND" }
],
render: directionColumn,
onFilter: (value, row) => _.get(row, "base.proxyDirection").includes(value)
},
{
title: "Name",
key: "src-dst",
render: d => {
let datum = {
direction: _.get(d, "base.proxyDirection"),
source: _.get(d, "base.source"),
destination: _.get(d, "base.destination"),
sourceLabels: _.get(d, "base.sourceMeta.labels", {}),
destinationLabels: _.get(d, "base.destinationMeta.labels", {})
};
return srcDstColumn(datum, resourceType, ResourceLink);
}
}
];
const tapColumns = (resourceType, ResourceLink) => {
return _.concat(
topLevelColumns(resourceType, ResourceLink),
[ methodCol, pathCol, responseInitLatencyCol, httpStatusCol, grpcStatusCol ]
);
};
const formatTapLatency = str => {
return formatLatencySec(str.replace("s", ""));
};
const requestInitSection = d => (
Request Init
Authority
Path
Scheme
Method
TLS
{_.get(d, "requestInit.http.requestInit.authority")}
{_.get(d, "requestInit.http.requestInit.path")}
{_.get(d, "requestInit.http.requestInit.scheme.registered")}
{_.get(d, "requestInit.http.requestInit.method.registered")}
{_.get(d, "base.tls")}
);
const responseInitSection = d => _.isEmpty(d.responseInit) ? null : (
Response Init
HTTP Status
Latency
{_.get(d, "responseInit.http.responseInit.httpStatus")}
{formatTapLatency(_.get(d, "responseInit.http.responseInit.sinceRequestInit"))}
);
const responseEndSection = d => _.isEmpty(d.responseEnd) ? null : (
Response End
GRPC Status
Latency
Response Length (B)
{_.isNull(_.get(d, "responseEnd.http.responseEnd.eos")) ? "N/A" : grpcStatusCodes[_.get(d, "responseEnd.http.responseEnd.eos.grpcStatusCode")]}
{formatTapLatency(_.get(d, "responseEnd.http.responseEnd.sinceResponseInit"))}
{formatWithComma(_.get(d, "responseEnd.http.responseEnd.responseBytes"))}
);
// hide verbose information
const expandedRowRender = d => {
return (
{requestInitSection(d)}
{responseInitSection(d)}
{responseEndSection(d)}
);
};
class TapEventTable extends React.Component {
static propTypes = {
api: PropTypes.shape({
ResourceLink: PropTypes.func.isRequired,
}).isRequired,
resource: PropTypes.string,
tableRows: PropTypes.arrayOf(PropTypes.shape({})),
}
static defaultProps = {
resource: "",
tableRows: []
}
render() {
let resourceType = this.props.resource.split("/")[0];
return (
r.base.id}
pagination={false}
className="tap-event-table"
size="middle" />
);
}
}
export default withContext(TapEventTable);