diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fa295cdc..19f0efb6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,64 @@ +## Release 1.5.0 + +Highlights: +- More accurate and cheaper connection tracking with eBPF, which now is enabled by default. +- Bug fixes and performance improvements. + +New features and enhancements: +- Enable eBPF tracking by default + [#2535](https://github.com/weaveworks/scope/pull/2535) +- Elide url passwords in cli arguments + [#2568](https://github.com/weaveworks/scope/pull/2568) + +Performance improvements: +- drop addr and port from Endpoint.Latest map + [#2581](https://github.com/weaveworks/scope/pull/2581) +- parallel reduce + [#2561](https://github.com/weaveworks/scope/pull/2561) +- don't read all of /proc when probe.proc.spy=false + [#2557](https://github.com/weaveworks/scope/pull/2557) +- optimise: don't sort in NodeSet.ForEach + [#2548](https://github.com/weaveworks/scope/pull/2548) +- encode empty ps.Maps as nil + [#2547](https://github.com/weaveworks/scope/pull/2547) + +Bug fixes: +- re-target app clients when name resolution changes + [#2579](https://github.com/weaveworks/scope/pull/2579) +- correct type for "Observed Gen." + [#2572](https://github.com/weaveworks/scope/pull/2572) +- Back off upon errored kubernetes api requests + [#2562](https://github.com/weaveworks/scope/pull/2562) +- Close eBPF tracker cleanly + [#2541](https://github.com/weaveworks/scope/pull/2541) +- Simplify connection tracker init and fix procfs scan fallback + [#2539](https://github.com/weaveworks/scope/pull/2539) +- Guard against null DaemonSet store + [#2538](https://github.com/weaveworks/scope/pull/2538) + +Internal improvements and cleanup: +- es6ify server.js and include in eslint + [#2560](https://github.com/weaveworks/scope/pull/2560) +- Fix prog/main_test.go + [#2567](https://github.com/weaveworks/scope/pull/2567) +- Fix incomplete dependencies for `make scope/prog` + [#2563](https://github.com/weaveworks/scope/pull/2563) +- bump package.json version to current scope version + [#2555](https://github.com/weaveworks/scope/pull/2555) +- simplify connection join + [#2559](https://github.com/weaveworks/scope/pull/2559) +- Use map helpers + [#2546](https://github.com/weaveworks/scope/pull/2546) +- add copyreport utility + [#2542](https://github.com/weaveworks/scope/pull/2542) + +Weave Cloud related changes: +- Time travel control + [#2524](https://github.com/weaveworks/scope/pull/2524) +- Add app capabilities to /api endpoint + [#2575](https://github.com/weaveworks/scope/pull/2575) + + ## Release 1.4.0 Highlights: diff --git a/client/app/scripts/actions/app-actions.js b/client/app/scripts/actions/app-actions.js index 83465b63c..359ea5fbb 100644 --- a/client/app/scripts/actions/app-actions.js +++ b/client/app/scripts/actions/app-actions.js @@ -635,13 +635,15 @@ function updateFromNodesDeltaBuffer(dispatch, state) { } export function clickResumeUpdate() { - return (dispatch, getServiceState) => { + return (dispatch, getState) => { dispatch({ type: ActionTypes.CLICK_RESUME_UPDATE }); + // TODO: Find a better way to do this (see the comment above). + const state = getState().scope || getState(); // Periodically merge buffered nodes deltas until the buffer is emptied. nodesDeltaBufferUpdateTimer = setInterval( - () => updateFromNodesDeltaBuffer(dispatch, getServiceState().scope), + () => updateFromNodesDeltaBuffer(dispatch, state), NODES_DELTA_BUFFER_FEED_INTERVAL, ); }; diff --git a/client/app/scripts/components/footer.js b/client/app/scripts/components/footer.js index 410edc45f..d23f5685c 100644 --- a/client/app/scripts/components/footer.js +++ b/client/app/scripts/components/footer.js @@ -2,6 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import Plugins from './plugins'; +import PauseButton from './pause-button'; import { trackMixpanelEvent } from '../utils/tracking-utils'; import { clickDownloadGraph, @@ -65,6 +66,7 @@ class Footer extends React.Component {
); @@ -271,7 +269,7 @@ function mapStateToProps({ scope, root }, { params }) { const cloudInstance = root.instances[params.orgId] || {}; const featureFlags = cloudInstance.featureFlags || []; return { - hasTimeTravel: featureFlags.includes('timeline-control'), + hasTimeTravel: featureFlags.includes('time-travel'), websocketTransitioning: scope.get('websocketTransitioning'), topologyViewMode: scope.get('topologyViewMode'), currentTopology: scope.get('currentTopology'), diff --git a/client/app/scripts/reducers/__tests__/root-test.js b/client/app/scripts/reducers/__tests__/root-test.js index aec34cc77..1bc3fb7a3 100644 --- a/client/app/scripts/reducers/__tests__/root-test.js +++ b/client/app/scripts/reducers/__tests__/root-test.js @@ -16,7 +16,8 @@ describe('RootReducer', () => { // TODO maybe extract those to topology-utils tests? const activeTopologyOptionsSelector = topologySelectors.activeTopologyOptionsSelector; const getAdjacentNodes = topologyUtils.getAdjacentNodes; - const isTopologyEmpty = topologyUtils.isTopologyEmpty; + const isNodesDisplayEmpty = topologyUtils.isNodesDisplayEmpty; + const isTopologyNodeCountZero = topologyUtils.isTopologyNodeCountZero; const getUrlState = require('../../utils/router-utils').getUrlState; // fixtures @@ -534,24 +535,36 @@ describe('RootReducer', () => { // empty topology - it('detects that the topology is empty', () => { + it('detects that the nodes display is empty', () => { let nextState = initialState; nextState = reducer(nextState, ReceiveTopologiesAction); nextState = reducer(nextState, ClickTopologyAction); - expect(isTopologyEmpty(nextState)).toBeTruthy(); + expect(isNodesDisplayEmpty(nextState)).toBeTruthy(); nextState = reducer(nextState, ReceiveNodesDeltaAction); - expect(isTopologyEmpty(nextState)).toBeFalsy(); + expect(isNodesDisplayEmpty(nextState)).toBeFalsy(); nextState = reducer(nextState, ClickTopology2Action); + expect(isNodesDisplayEmpty(nextState)).toBeTruthy(); + nextState = reducer(nextState, ReceiveNodesDeltaAction); - expect(isTopologyEmpty(nextState)).toBeTruthy(); + expect(isNodesDisplayEmpty(nextState)).toBeFalsy(); + }); + + it('detects that the topo stats are empty', () => { + let nextState = initialState; + nextState = reducer(nextState, ReceiveTopologiesAction); + nextState = reducer(nextState, ClickTopologyAction); + expect(isTopologyNodeCountZero(nextState)).toBeFalsy(); + + nextState = reducer(nextState, ReceiveNodesDeltaAction); + expect(isTopologyNodeCountZero(nextState)).toBeFalsy(); + + nextState = reducer(nextState, ClickTopology2Action); + expect(isTopologyNodeCountZero(nextState)).toBeTruthy(); nextState = reducer(nextState, ClickTopologyAction); - expect(isTopologyEmpty(nextState)).toBeTruthy(); - - nextState = reducer(nextState, ReceiveNodesDeltaAction); - expect(isTopologyEmpty(nextState)).toBeFalsy(); + expect(isTopologyNodeCountZero(nextState)).toBeFalsy(); }); // selection of relatives diff --git a/client/app/scripts/utils/topology-utils.js b/client/app/scripts/utils/topology-utils.js index d67c3d530..e10d9c157 100644 --- a/client/app/scripts/utils/topology-utils.js +++ b/client/app/scripts/utils/topology-utils.js @@ -4,6 +4,7 @@ import { Set as makeSet, List as makeList } from 'immutable'; import { isWebsocketQueryingCurrentSelector } from '../selectors/time-travel'; import { isResourceViewModeSelector } from '../selectors/topology'; import { pinnedMetricSelector } from '../selectors/node-metric'; +import { shownNodesSelector } from '../selectors/node-filters'; // // top priority first @@ -145,11 +146,7 @@ export function isNodesDisplayEmpty(state) { return !pinnedMetricSelector(state); } // Otherwise (in graph and table view), we only look at the nodes content. - return state.get('nodes').isEmpty(); -} - -export function isTopologyEmpty(state) { - return isTopologyNodeCountZero(state) || isNodesDisplayEmpty(state); + return shownNodesSelector(state).isEmpty(); } export function getAdjacentNodes(state, originNodeId) { diff --git a/client/app/styles/_base.scss b/client/app/styles/_base.scss index 3f08b66cf..0d8654752 100644 --- a/client/app/styles/_base.scss +++ b/client/app/styles/_base.scss @@ -184,7 +184,7 @@ margin-right: 1em; } - &-label { + &-label, .pause-text { text-transform: uppercase; margin: 0 0.25em; } diff --git a/client/package.json b/client/package.json index 3eeb62c73..dd9e45315 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "weave-scope", - "version": "1.4.0", + "version": "1.5.0", "description": "SPA JS app for Weave Scope visualising the application network.", "repository": "weaveworks/scope", "license": "Apache-2.0", diff --git a/site/installing.md b/site/installing.md index b7bd389dd..7331381fa 100644 --- a/site/installing.md +++ b/site/installing.md @@ -125,7 +125,7 @@ After it’s been launched, open your browser to `http://localhost:4040`. **Docker Compose Format Version 1:** scope: - image: weaveworks/scope:1.3.0 + image: weaveworks/scope:1.5.0 net: "host" pid: "host" privileged: true @@ -141,7 +141,7 @@ After it’s been launched, open your browser to `http://localhost:4040`. version: '2' services: scope: - image: weaveworks/scope:1.3.0 + image: weaveworks/scope:1.5.0 network_mode: "host" pid: "host" privileged: true @@ -165,7 +165,7 @@ Version 2 of this YAML file supports networks and volumes as defined by any plug **Docker Compose Format Version 1:** probe: - image: weaveworks/scope:1.3.0 + image: weaveworks/scope:1.5.0 net: "host" pid: "host" privileged: true @@ -182,7 +182,7 @@ Version 2 of this YAML file supports networks and volumes as defined by any plug version: '2' services: probe: - image: weaveworks/scope:1.3.0 + image: weaveworks/scope:1.5.0 network_mode: "host" pid: "host" privileged: true