Skip to content

Commit

Permalink
Merge pull request #1465 from weaveworks/truncate-container-envs
Browse files Browse the repository at this point in the history
Limit tables to 20 rows
  • Loading branch information
davkal committed May 11, 2016
2 parents 23c5e9f + c265a57 commit 715003e
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 16 deletions.
21 changes: 17 additions & 4 deletions client/app/scripts/components/node-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ import _ from 'lodash';
import React from 'react';
import { connect } from 'react-redux';

import { clickCloseDetails, clickShowTopologyForNode } from '../actions/app-actions';
import { brightenColor, getNeutralColor, getNodeColorDark } from '../utils/color-utils';
import { resetDocumentTitle, setDocumentTitle } from '../utils/title-utils';

import NodeDetailsControls from './node-details/node-details-controls';
import NodeDetailsHealth from './node-details/node-details-health';
import NodeDetailsInfo from './node-details/node-details-info';
import NodeDetailsLabels from './node-details/node-details-labels';
import NodeDetailsRelatives from './node-details/node-details-relatives';
import NodeDetailsTable from './node-details/node-details-table';
import { clickCloseDetails, clickShowTopologyForNode } from '../actions/app-actions';
import { brightenColor, getNeutralColor, getNodeColorDark } from '../utils/color-utils';
import { resetDocumentTitle, setDocumentTitle } from '../utils/title-utils';
import Warning from './warning';

function getTruncationText(count) {
return 'This section was too long to be handled efficiently and has been truncated'
+ ` (${count} extra entries not included). We are working to remove this limitation.`;
}

export class NodeDetails extends React.Component {

Expand Down Expand Up @@ -196,7 +203,13 @@ export class NodeDetails extends React.Component {
if (table.rows.length > 0) {
return (
<div className="node-details-content-section" key={table.id}>
<div className="node-details-content-section-header">{table.label}</div>
<div className="node-details-content-section-header">
{table.label}
{table.truncationCount > 0 && <span
className="node-details-content-section-header-warning">
<Warning text={getTruncationText(table.truncationCount)} />
</span>}
</div>
<NodeDetailsLabels rows={table.rows} />
</div>
);
Expand Down
39 changes: 39 additions & 0 deletions client/app/scripts/components/warning.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import classnames from 'classnames';


class Warning extends React.Component {

constructor(props, context) {
super(props, context);
this.handleClick = this.handleClick.bind(this);
this.state = {
expanded: false
};
}

handleClick() {
const expanded = !this.state.expanded;
this.setState({ expanded });
}

render() {
const { text } = this.props;
const { expanded } = this.state;

const className = classnames('warning', {
'warning-expanded': expanded
});

return (
<div className={className} onClick={this.handleClick}>
<div className="warning-wrapper">
<span className="warning-icon fa fa-warning" title={text} />
{expanded && <span className="warning-text">{text}</span>}
</div>
</div>
);
}
}

export default Warning;
36 changes: 36 additions & 0 deletions client/app/styles/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,42 @@ h2 {
}
}

.warning {
display: inline-block;
cursor: pointer;
border: 1px dashed transparent;
text-transform: none;
border-radius: @border-radius;
margin-left: 4px;

&-wrapper {
display: flex;
}

&-text {
display: inline-block;
color: @text-secondary-color;
padding-left: 0.5em;
}

&-icon {
.btn-opacity;
}

&-expanded {
margin-left: 0;
padding: 2px 4px;
border-color: @text-tertiary-color;
}

&-expanded &-icon {
position: relative;
top: 4px;
left: 2px;
}

}

.sidebar {
position: fixed;
bottom: 16px;
Expand Down
48 changes: 37 additions & 11 deletions report/table.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
package report

import (
"fmt"
"sort"
"strings"

log "github.com/Sirupsen/logrus"
"github.com/weaveworks/scope/common/mtime"
)

// MaxTableRows sets the limit on the table size to render
// TODO: this won't be needed once we send reports incrementally
const (
MaxTableRows = 20
TruncationCountPrefix = "table_truncation_count_"
)

// AddTable appends arbirary key-value pairs to the Node, returning a new node.
func (node Node) AddTable(prefix string, labels map[string]string) Node {
count := 0
for key, value := range labels {
if count >= MaxTableRows {
break
}
node = node.WithLatest(prefix+key, mtime.Now(), value)
count++
}
if len(labels) > MaxTableRows {
truncationCount := fmt.Sprintf("%d", len(labels)-MaxTableRows)
node = node.WithLatest(TruncationCountPrefix+prefix, mtime.Now(), truncationCount)
}
return node
}

// ExtractTable returns the key-value pairs with the given prefix from this Node,
func (node Node) ExtractTable(prefix string) map[string]string {
result := map[string]string{}
func (node Node) ExtractTable(prefix string) (rows map[string]string, truncationCount int) {
rows = map[string]string{}
truncationCount = 0
node.Latest.ForEach(func(key, value string) {
if strings.HasPrefix(key, prefix) {
label := key[len(prefix):]
result[label] = value
rows[label] = value
}
})
return result
if str, ok := node.Latest.Lookup(TruncationCountPrefix + prefix); ok {
if n, err := fmt.Sscanf(str, "%d", &truncationCount); n != 1 || err != nil {
log.Warn("Unexpected truncation count format %q", str)
}
}
return rows, truncationCount
}

// Table is the type for a table in the UI.
type Table struct {
ID string `json:"id"`
Label string `json:"label"`
Rows []MetadataRow `json:"rows"`
ID string `json:"id"`
Label string `json:"label"`
Rows []MetadataRow `json:"rows"`
TruncationCount int `json:"truncationCount,omitempty"`
}

type tablesByID []Table
Expand Down Expand Up @@ -90,12 +115,13 @@ type TableTemplates map[string]TableTemplate
func (t TableTemplates) Tables(node Node) []Table {
var result []Table
for _, template := range t {
rows, truncationCount := node.ExtractTable(template.Prefix)
table := Table{
ID: template.ID,
Label: template.Label,
Rows: []MetadataRow{},
ID: template.ID,
Label: template.Label,
Rows: []MetadataRow{},
TruncationCount: truncationCount,
}
rows := node.ExtractTable(template.Prefix)
keys := make([]string, 0, len(rows))
for k := range rows {
keys = append(keys, k)
Expand Down
31 changes: 30 additions & 1 deletion report/table_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package report_test

import (
"fmt"
"reflect"
"testing"

Expand All @@ -16,9 +17,37 @@ func TestTables(t *testing.T) {
nmd := report.MakeNode("foo1")

nmd = nmd.AddTable("foo_", want)
have := nmd.ExtractTable("foo_")
have, truncationCount := nmd.ExtractTable("foo_")

if truncationCount != 0 {
t.Error("Table shouldn't had been truncated")
}

if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
}
}

func TestTruncation(t *testing.T) {
wantTruncationCount := 1
want := map[string]string{}
for i := 0; i < report.MaxTableRows+wantTruncationCount; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
want[key] = value
}

nmd := report.MakeNode("foo1")

nmd = nmd.AddTable("foo_", want)
_, truncationCount := nmd.ExtractTable("foo_")

if truncationCount != wantTruncationCount {
t.Error(
"Table should had been truncated by",
wantTruncationCount,
"and not",
truncationCount,
)
}
}

0 comments on commit 715003e

Please sign in to comment.