Skip to content

Commit

Permalink
V0.14.3 (#146)
Browse files Browse the repository at this point in the history
* pre-populate dbms with available jmx entries

* version parsing for aura4

* place clusterTimeseries in an error state when all underlying datafeeds fail

* COMMITTED heap is shown, not max heap setting

* improved aura version parsing

* halin does not support Neo4j 4 on Aura

* v0.14.3 release notes
  • Loading branch information
moxious authored Jul 21, 2020
1 parent 58b14e7 commit f411d12
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 9 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "halin",
"description": "Halin helps you monitor and improve your Neo4j graph",
"version": "0.14.2",
"version": "0.14.3",
"neo4jDesktop": {
"apiVersion": "^1.2.0"
},
Expand Down
7 changes: 7 additions & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Halin Release Notes

## 0.14.3 Minor Fixes

- Halin now shows *committed* heap in the overview, not configured heap
- Improved version parsing for the various kinds of neo4j encountered
- Cluster timeseries charts can be paused when all underlying data feeds are in an error state
- Halin does not support Neo4j 4 on Aura

## 0.14.2 Bugfix Release

- Halin can now connect to and monitor clusters with (partially) broken routing tables, which
Expand Down
5 changes: 5 additions & 0 deletions src/api/HalinContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,11 @@ export default class HalinContext {
})
// Checking databases must be after checking for a cluster, since we need to know who leader is
.then(() => this.dbSet.initialize(this))
.then(() => {
if (this.getVersion().major >= 4 && this.isNeo4jAura()) {
throw new Error('Halin does not support Neo4j 4 on Aura at this time');
}
})
.then(() => {
this.getClusterManager().addEvent({
type: 'halin',
Expand Down
11 changes: 9 additions & 2 deletions src/api/cluster/ClusterMember.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,13 +378,20 @@ export default class ClusterMember {
sentry.warn("This ClusterMember has more than one version installed; only using the first");
}

const v = this.dbms.versions[0] || '';
const [v, extra] = (this.dbms.versions[0] || '').split('-');

const parts = v.split('.');
return {
const ver = {
major: parts[0] || 'unknown',
minor: parts[1] || 'unknown',
patch: parts[2] || 'unknown',
};

if (extra) {
ver.extra = extra;
}

return ver;
}

getMaxPhysicalMemory() {
Expand Down
4 changes: 2 additions & 2 deletions src/api/data/DataFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@ export default class DataFeed extends Metric {
if (err) {
if (`${this.state.error}` !== `${err}`) {
sentry.reportError(err, 'Failed to execute timeseries query (first time)');
} else {
} /*else {
sentry.fine(`Duplicate polled error in timeseries ${err}`);
}
}*/

this.state.lastDataArrived = this.feedStartTime;
this.state.error = err;
Expand Down
15 changes: 15 additions & 0 deletions src/api/feature/probes.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,16 @@ const usesFabric = member => {
})
};

const getAvailableJMXEntries = member => {
const prom = member.run(queryLibrary.JMX_ALL.query, {})
.then(results => results.records.map(r => r.get('name')))
.catch(err => {
sentry.reportError('Failed to list JMX entries', err);
return [];
});
return prom;
};

/**
* @returns Array of { name, lastUpdated } metrics supported by the server.
*/
Expand Down Expand Up @@ -298,6 +308,11 @@ const runAllProbes = member => {
.then(result => { dbms.logStreaming = result; }),
() => getAvailableMetrics(member)
.then(metrics => { member.metrics = metrics; }),
() => getAvailableJMXEntries(member)
.then(jmxEntries => {
dbms.jmxEntries = jmxEntries.sort();
console.log('JMX entries', dbms);
}),
() => hasDBStats(member)
.then(result => { dbms.hasDBStats = result }),
() => hasMultiDatabase(member)
Expand Down
5 changes: 5 additions & 0 deletions src/api/knowledgebase/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ export default {
too many times`,
links.authMaxFailedAttempts,
]),
HalinNotSupported: render([
`This error means that the underlying version of Neo4j does not provide facilities
necessary for Halin to function properly. Please raise an issue with your Neo4j support,
or open an issue at the Halin github repository.`,
]),
UnknownError: render([
`Unfortunately, no troubleshooting is available for this particular error.
Consider checking the Neo4j community site for more information.`
Expand Down
2 changes: 1 addition & 1 deletion src/api/sentry/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const reportError = (err, message=null) => {
return err;
}

console.log('Sentry skipped reporting error');
// console.log('Sentry skipped reporting error');
return err;
};

Expand Down
4 changes: 4 additions & 0 deletions src/components/initialConnection/Troubleshooting.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export default class Troubleshooting extends PureComponent {
detector: err => `${err}`.match(/Failed to connect to any valid cluster members/),
suggestions: kb.BrokenRoutingTable,
},
{
detector: err => `${err}`.match(/Halin does not support/),
suggestions: kb.HalinNotSupported,
},
{
detector: err => `${err}`.match(/./),
suggestions: kb.UnknownError,
Expand Down
8 changes: 7 additions & 1 deletion src/components/overview/ClusterMemory/ClusterMemory.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import ClusterTimeseries from '../../timeseries/ClusterTimeseries';
import uuid from 'uuid';
import queryLibrary from '../../../api/data/queries/query-library';
import HalinCard from '../../ui/scaffold/HalinCard/HalinCard';
import util from '../../../api/data/util';
import _ from 'lodash';

class ClusterMemory extends Component {
state = {
Expand All @@ -12,8 +14,12 @@ class ClusterMemory extends Component {
};

render() {
const stats = window.halinContext.getMemberSet().getStats() || {};
const writerStats = stats[window.halinContext.getWriteMember().getBoltAddress()];
const heapCommitted = _.get(writerStats, 'heapCommitted');

const header = 'Heap Size (' +
(window.halinContext.getWriteMember().dbms.maxHeap || 'unknown') + ' max)';
(heapCommitted ? util.humanDataSize(heapCommitted) : 'unknown') + ' committed)';

return (
<HalinCard header={header} knowledgebase='ClusterMemory' owner={this}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class DetectedSettings extends PureComponent {
const version = ctx.getSystemDBWriter().getVersion();

const items = [
this.lineItem(true, `Neo4j v${version.major}.${version.minor}.${version.patch}`),
this.lineItem(true, `Neo4j v${version.major}.${version.minor}.${version.patch}` + (version.extra ? '-' + version.extra : '')),
ctx.isCommunity() ? this.lineItem(true, 'Community Edition') : this.lineItem(true, 'Enterprise Edition'),
this.item(ctx.getBaseURI(), 'home'),
this.item(ctx.getCurrentUser().username, 'user circle'),
Expand Down
24 changes: 23 additions & 1 deletion src/components/timeseries/ClusterTimeseries.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import _ from 'lodash';
import { Grid, Label } from 'semantic-ui-react';
import { Grid, Label, Message } from 'semantic-ui-react';
import {
TimeSeries,
TimeRange,
Expand Down Expand Up @@ -32,6 +32,7 @@ class ClusterTimeseries extends Component {
startTime: new Date(),
query: null,
data: null,
error: null,
events: null,
time: new Date(),
lastDataArrived: new Date(),
Expand Down Expand Up @@ -219,6 +220,7 @@ class ClusterTimeseries extends Component {

// And attach that to the feed.
this.feeds[addr].on('data', this.onDataCallbacks[addr]);
this.feeds[addr].on('error', (err, dataFeed) => this.onError(err, dataFeed));

const curState = this.feeds[addr].currentState();
this.onDataCallbacks[addr](curState, this.feeds[addr]);
Expand Down Expand Up @@ -249,6 +251,20 @@ class ClusterTimeseries extends Component {
this.mounted = false;
}

onError(err, dataFeed) {
const feeds = Object.values(this.feeds);

// The timeseries is only in an error state if *all feeds* have errored.
// If only one has, the machine could be restarting or just under load.
const error = feeds.map(f => _.get(f.currentState(), 'error'))
.reduce((a, b) => a && b, true);

if (error) {
this.setState({ error });
console.fine('All feeds are in an error state');
}
}

onData(clusterMember, database, newData, dataFeed) {
const addr = clusterMember.getBoltAddress();

Expand Down Expand Up @@ -308,6 +324,7 @@ class ClusterTimeseries extends Component {
maxObservedValue,
minObservedValue,
timeRange,
error: null,
};

// Each address has unique data state.
Expand Down Expand Up @@ -455,6 +472,11 @@ class ClusterTimeseries extends Component {

if (!this.mounted || !hasData) {
return <Spinner active={true} />;
} else if(this.state.error) {
return <Message negative>
<Message.Header>Error Retrieving Data</Message.Header>
<p>Data feeds are in an error state, and no data can be shown.</p>
</Message>;
}

// For both the yAxis and the container, define some defaults, permitting overrides to be
Expand Down

1 comment on commit f411d12

@vercel
Copy link

@vercel vercel bot commented on f411d12 Jul 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.