Skip to content

Commit

Permalink
Load pipeline actions and stores through a provider (Graylog2#4830)
Browse files Browse the repository at this point in the history
* Load pipeline actions and stores through a provider

Inject actions and stores from `CombinedProvider`, ensuring they are all
singleton and behaving like other actions and stores.

Fixes Graylog2#4829

* Fix linter errors

* Fix additional linter errors
  • Loading branch information
edmundoa authored and dennisoelkers committed Jun 11, 2018
1 parent 14856fc commit 70af512
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ import naturalSort from 'javascript-natural-sort';

import { DataTable, Spinner } from 'components/common';
import { MetricContainer, CounterRate } from 'components/metrics';
import PipelineConnectionsList from './PipelineConnectionsList';

import PipelinesActions from 'actions/pipelines/PipelinesActions';
import PipelinesStore from 'stores/pipelines/PipelinesStore';
import PipelineConnectionsActions from 'actions/pipelines/PipelineConnectionsActions';
import PipelineConnectionsStore from 'stores/pipelines/PipelineConnectionsStore';
import Routes from 'routing/Routes';
import CombinedProvider from 'injection/CombinedProvider';

import StoreProvider from 'injection/StoreProvider';
const StreamsStore = StoreProvider.getStore('Streams');
import PipelineConnectionsList from './PipelineConnectionsList';

import Routes from 'routing/Routes';
const { PipelinesStore, PipelinesActions } = CombinedProvider.get('Pipelines');
const { PipelineConnectionsStore, PipelineConnectionsActions } = CombinedProvider.get('PipelineConnections');
const { StreamsStore } = CombinedProvider.get('Streams');

const ProcessingTimelineComponent = createReactClass({
displayName: 'ProcessingTimelineComponent',
Expand All @@ -38,6 +36,7 @@ const ProcessingTimelineComponent = createReactClass({
this.style.unuse();
},

// eslint-disable-next-line
style: require('!style/useable!css!./ProcessingTimelineComponent.css'),

_calculateUsedStages(pipelines) {
Expand Down Expand Up @@ -67,14 +66,14 @@ const ProcessingTimelineComponent = createReactClass({
const formattedStages = [];
const stageNumbers = stages.map(stage => stage.stage);

this.usedStages.forEach(usedStage => {
this.usedStages.forEach((usedStage) => {
if (stageNumbers.indexOf(usedStage) === -1) {
formattedStages.push(
<div key={`${pipeline.id}-stage${usedStage}`} className="pipeline-stage idle-stage">Idle</div>
<div key={`${pipeline.id}-stage${usedStage}`} className="pipeline-stage idle-stage">Idle</div>,
);
} else {
formattedStages.push(
<div key={`${pipeline.id}-stage${usedStage}`} className="pipeline-stage used-stage">Stage {usedStage}</div>
<div key={`${pipeline.id}-stage${usedStage}`} className="pipeline-stage used-stage">Stage {usedStage}</div>,
);
}
}, this);
Expand All @@ -94,7 +93,9 @@ const ProcessingTimelineComponent = createReactClass({
</MetricContainer>
</td>
<td className="stream-list">
<PipelineConnectionsList pipeline={pipeline} connections={this.state.connections} streams={this.state.streams}
<PipelineConnectionsList pipeline={pipeline}
connections={this.state.connections}
streams={this.state.streams}
streamsFormatter={this._formatConnectedStreams}
noConnectionsMessage={<em>Not connected</em>} />
</td>
Expand Down
17 changes: 10 additions & 7 deletions graylog2-web-interface/src/components/pipelines/Stage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ import { Col, Button } from 'react-bootstrap';
import { Link } from 'react-router';

import { DataTable, EntityListItem, Spinner } from 'components/common';
import RulesStore from 'stores/rules/RulesStore';
import StageForm from './StageForm';
import { MetricContainer, CounterRate } from 'components/metrics';

import Routes from 'routing/Routes';
import CombinedProvider from 'injection/CombinedProvider';

import StageForm from './StageForm';

const { RulesStore } = CombinedProvider.get('Rules');

const Stage = createReactClass({
displayName: 'Stage',

propTypes: {
stage: PropTypes.object.isRequired,
pipeline: PropTypes.object.isRequired,
isLastStage: PropTypes.bool,
isLastStage: PropTypes.bool.isRequired,
onUpdate: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
},
Expand All @@ -39,7 +42,7 @@ const Stage = createReactClass({
id: `invalid-${ruleIdx}`,
description: `Rule ${stage.rules[ruleIdx]} has been renamed or removed. This rule will be skipped.`,
};
ruleTitle = <span><i className="fa fa-warning text-danger"/> {stage.rules[ruleIdx]}</span>;
ruleTitle = <span><i className="fa fa-warning text-danger" /> {stage.rules[ruleIdx]}</span>;
} else {
ruleTitle = (
<Link to={Routes.SYSTEM.PIPELINES.RULE(rule.id)}>
Expand All @@ -60,7 +63,7 @@ const Stage = createReactClass({
</td>
<td>
<MetricContainer name={`org.graylog.plugins.pipelineprocessor.ast.Rule.${rule.id}.${this.props.pipeline.id}.${stage.stage}.failed`}>
<CounterRate showTotal zeroOnMissing suffix="errors/s"/>
<CounterRate showTotal zeroOnMissing suffix="errors/s" />
</MetricContainer>
</td>
</tr>
Expand All @@ -86,7 +89,7 @@ const Stage = createReactClass({
render() {
const stage = this.props.stage;

let suffix = `Contains ${(stage.rules.length === 1 ? '1 rule' : `${stage.rules.length} rules`)}`;
const suffix = `Contains ${(stage.rules.length === 1 ? '1 rule' : `${stage.rules.length} rules`)}`;

const throughput = (<MetricContainer name={`org.graylog.plugins.pipelineprocessor.ast.Pipeline.${this.props.pipeline.id}.stage.${stage.stage}.executed`}>
<CounterRate showTotal={false} prefix="Throughput: " suffix="msg/s" />
Expand All @@ -109,7 +112,7 @@ const Stage = createReactClass({
);
}

let block = (<span>
const block = (<span>
{description}
<br />
{throughput}
Expand Down
47 changes: 26 additions & 21 deletions graylog2-web-interface/src/components/pipelines/StageForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import PropTypes from 'prop-types';
import React from 'react';
import createReactClass from 'create-react-class';
import Reflux from 'reflux';
import { Button } from 'react-bootstrap';
import { Button, FormGroup, ControlLabel } from 'react-bootstrap';
import { Link } from 'react-router';

import { SelectableList } from 'components/common';
import { BootstrapModalForm, Input } from 'components/bootstrap';
import ObjectUtils from 'util/ObjectUtils';
import FormsUtils from 'util/FormsUtils';

import RulesStore from 'stores/rules/RulesStore';

import Routes from 'routing/Routes';
import CombinedProvider from 'injection/CombinedProvider';

const { RulesStore } = CombinedProvider.get('Rules');

const StageForm = createReactClass({
displayName: 'StageForm',
Expand All @@ -21,13 +22,13 @@ const StageForm = createReactClass({
stage: PropTypes.object,
create: PropTypes.bool,
save: PropTypes.func.isRequired,
validateStage: PropTypes.func.isRequired,
},

mixins: [Reflux.connect(RulesStore)],

getDefaultProps() {
return {
create: false,
stage: {
stage: 0,
match_all: false,
Expand Down Expand Up @@ -80,7 +81,7 @@ const StageForm = createReactClass({
},

_getFormattedOptions(rules) {
return rules ? rules.map(rule => {
return rules ? rules.map((rule) => {
return { value: rule.title, label: rule.title };
}) : [];
},
Expand Down Expand Up @@ -120,29 +121,33 @@ const StageForm = createReactClass({
help="Stage priority. The lower the number, the earlier it will execute."
value={this.state.stage.stage} />

<Input label="Continue processing on next stage when">
<Input type="radio"
<FormGroup>
<ControlLabel>Continue processing on next stage when</ControlLabel>
</FormGroup>

<Input type="radio"
id="match_all"
name="match_all"
value="true"
label="All rules on this stage match the message"
onChange={this._onChange}
checked={this.state.stage.match_all} />

<Input type="radio"
id="match_any"
name="match_all"
value="false"
label="At least one of the rules on this stage matches the message"
onChange={this._onChange}
checked={!this.state.stage.match_all} />

<Input id="stage-rules-select"
label="Stage rules"
help={rulesHelp}>
<SelectableList options={this._getFormattedOptions(this.state.rules)} isLoading={!this.state.rules}
onChange={this._onRulesChange} selectedOptions={this.state.stage.rules} />
</Input>
<Input type="radio"
id="match_any"
name="match_all"
value="false"
label="At least one of the rules on this stage matches the message"
onChange={this._onChange}
checked={!this.state.stage.match_all} />

<Input id="stage-rules-select"
label="Stage rules"
help={rulesHelp}>
<SelectableList options={this._getFormattedOptions(this.state.rules)}
isLoading={!this.state.rules}
onChange={this._onRulesChange}
selectedOptions={this.state.stage.rules} />
</Input>
</fieldset>
</BootstrapModalForm>
Expand Down
5 changes: 3 additions & 2 deletions graylog2-web-interface/src/components/rules/RuleHelper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ import { Row, Col, Panel, Table, Tabs, Tab } from 'react-bootstrap';

import Reflux from 'reflux';

import RulesStore from 'stores/rules/RulesStore';
import RulesActions from 'actions/rules/RulesActions';
import ObjectUtils from 'util/ObjectUtils';

import DocumentationLink from 'components/support/DocumentationLink';
import { PaginatedList, Spinner, SearchForm } from 'components/common';

import DocsHelper from 'util/DocsHelper';
import CombinedProvider from 'injection/CombinedProvider';

import RuleHelperStyle from './RuleHelper.css';

const { RulesStore, RulesActions } = CombinedProvider.get('Rules');

const RuleHelper = createReactClass({
displayName: 'RuleHelper',

Expand Down
10 changes: 5 additions & 5 deletions graylog2-web-interface/src/components/rules/RuleList.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import PropTypes from 'prop-types';
import React from 'react';
import { DataTable, Timestamp } from 'components/common';

import { Button } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';
import { Link } from 'react-router';

import RulesActions from 'actions/rules/RulesActions';

import { DataTable, Timestamp } from 'components/common';
import { MetricContainer, CounterRate } from 'components/metrics';

import Routes from 'routing/Routes';
import CombinedProvider from 'injection/CombinedProvider';

const { RulesActions } = CombinedProvider.get('Rules');

class RuleList extends React.Component {
static propTypes = {
Expand Down Expand Up @@ -75,7 +75,7 @@ class RuleList extends React.Component {
className="table-hover"
headers={headers}
headerCellFormatter={this._headerCellFormatter}
sortByKey={"title"}
sortByKey="title"
rows={this.props.rules}
filterBy="Title"
dataRowFormatter={this._ruleInfoFormatter}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { Link } from 'react-router';

import { Select } from 'components/common';
import RawMessageLoader from 'components/messageloaders/RawMessageLoader';
import SimulationResults from './SimulationResults';

import Routes from 'routing/Routes';
import CombinedProvider from 'injection/CombinedProvider';

import SimulationResults from './SimulationResults';

import SimulatorActions from 'actions/simulator/SimulatorActions';
// eslint-disable-next-line no-unused-vars
import SimulatorStore from 'stores/simulator/SimulatorStore';
const { SimulatorActions } = CombinedProvider.get('Simulator');

const DEFAULT_STREAM_ID = '000000000000000000000001';

Expand Down Expand Up @@ -41,12 +41,12 @@ class ProcessorSimulator extends React.Component {
SimulatorActions.simulate
.triggerPromise(this.state.stream, message.fields, options.inputId)
.then(
response => {
(response) => {
this.setState({ simulation: response, loading: false });
},
error => {
(error) => {
this.setState({ loading: false, error: error });
}
},
);
};

Expand All @@ -56,8 +56,8 @@ class ProcessorSimulator extends React.Component {
}

return streams
.map(s => {
return { value: s.id, label: s.title };
.map((stream) => {
return { value: stream.id, label: stream.title };
})
.sort((s1, s2) => naturalSort(s1.label, s2.label));
};
Expand Down
8 changes: 8 additions & 0 deletions graylog2-web-interface/src/injection/CombinedProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@ class CombinedProvider {
Metrics: () => require('actions/metrics/MetricsActions'),
Nodes: () => require('actions/nodes/NodesActions'),
Notifications: () => require('actions/notifications/NotificationsActions'),
PipelineConnections: () => require('actions/pipelines/PipelineConnectionsActions'),
Pipelines: () => require('actions/pipelines/PipelinesActions'),
Refresh: () => require('actions/tools/RefreshActions'),
Rules: () => require('actions/rules/RulesActions'),
SavedSearches: () => require('actions/search/SavedSearchesActions'),
ServerAvailability: () => require('actions/sessions/ServerAvailabilityActions'),
Session: () => require('actions/sessions/SessionActions'),
Sidecars: () => require('actions/sidecars/SidecarsActions'),
SidecarsAdministration: () => require('actions/sidecars/SidecarsAdministrationActions'),
Simulator: () => require('actions/simulator/SimulatorActions'),
SingleNode: () => require('actions/nodes/SingleNodeActions'),
Streams: () => require('actions/streams/StreamsActions'),
SystemJobs: () => require('actions/systemjobs/SystemJobsActions'),
Expand Down Expand Up @@ -104,16 +108,20 @@ class CombinedProvider {
Nodes: () => require('stores/nodes/NodesStore'),
Notifications: () => require('stores/notifications/NotificationsStore'),
Outputs: () => require('stores/outputs/OutputsStore'),
PipelineConnections: () => require('stores/pipelines/PipelineConnectionsStore'),
Pipelines: () => require('stores/pipelines/PipelinesStore'),
Plugins: () => require('stores/plugins/PluginsStore'),
Preferences: () => require('stores/users/PreferencesStore'),
Refresh: () => require('stores/tools/RefreshStore'),
Roles: () => require('stores/users/RolesStore'),
Rules: () => require('stores/rules/RulesStore'),
SavedSearches: () => require('stores/search/SavedSearchesStore'),
Search: () => require('stores/search/SearchStore'),
ServerAvailability: () => require('stores/sessions/ServerAvailabilityStore'),
Session: () => require('stores/sessions/SessionStore'),
Sidecars: () => require('stores/sidecars/SidecarsStore'),
SidecarsAdministration: () => require('stores/sidecars/SidecarsAdministrationStore'),
Simulator: () => require('stores/simulator/SimulatorStore'),
SingleNode: () => require('stores/nodes/SingleNodeStore'),
Sources: () => require('stores/sources/SourcesStore'),
Startpage: () => require('stores/users/StartpageStore'),
Expand Down
Loading

0 comments on commit 70af512

Please sign in to comment.