Example #1
0
func (s *FlowGremlinTraversalStep) addTimeFilter(fsq *flow.FlowSearchQuery, timeContext *time.Time) {
	var timeFilter *flow.Filter
	if s.hasSinceParam() {
		tr := flow.Range{
			From: timeContext.Unix() - s.context.Params[0].(traversal.Since).Seconds,
			To:   timeContext.Unix(),
		}
		// flow need to have at least one metric included in the time range
		timeFilter = flow.NewFilterActiveIn(tr, "Metric.")
	} else {
		// flow having at least one metric at that time meaning being active
		timeFilter = flow.NewFilterActiveAt(timeContext.Unix(), "Metric.")
	}
	fsq.Filter = flow.NewAndFilter(fsq.Filter, timeFilter)
}
Example #2
0
func (f *FlowTraversalStep) Metrics() *MetricsTraversalStep {
	if f.error != nil {
		return &MetricsTraversalStep{error: f.error}
	}

	var metrics map[string][]*flow.FlowMetric

	context := f.GraphTraversal.Graph.GetContext()
	if context.Time != nil {
		metrics = make(map[string][]*flow.FlowMetric)

		// two cases, either we have a flowset and we need to use it in order to filter
		// flows or we don't have flowset but we have the pre-built flowSearchQuery filter
		// if none of these cases it's an error.
		if f.flowset != nil {
			flowFilter := flow.NewFilterForFlowSet(f.flowset)
			f.flowSearchQuery.Filter = flow.NewAndFilter(f.flowSearchQuery.Filter, flowFilter)
		} else if f.flowSearchQuery.Filter == nil {
			return &MetricsTraversalStep{error: errors.New("Unable to filter flows")}
		}

		// contruct metrics filter according to the time context and the since
		// predicate given to Flows.
		fr := flow.Range{To: context.Time.Unix()}
		if f.since.Seconds > 0 {
			fr.From = context.Time.Unix() - f.since.Seconds
		}
		metricFilter := flow.NewFilterIncludedIn(fr, "")

		var err error
		if metrics, err = f.Storage.SearchMetrics(f.flowSearchQuery, metricFilter); err != nil {
			return &MetricsTraversalStep{error: err}
		}
	} else {
		metrics = make(map[string][]*flow.FlowMetric, len(f.flowset.Flows))
		for _, flow := range f.flowset.Flows {
			if flow.LastUpdateMetric.Start != 0 || flow.LastUpdateMetric.Last != 0 {
				metrics[flow.UUID] = append(metrics[flow.UUID], flow.LastUpdateMetric)
			} else {
				metrics[flow.UUID] = append(metrics[flow.UUID], flow.Metric)
			}
		}
	}
	return &MetricsTraversalStep{GraphTraversal: f.GraphTraversal, metrics: metrics}
}
Example #3
0
func (s *FlowGremlinTraversalStep) Exec(last traversal.GraphTraversalStep) (traversal.GraphTraversalStep, error) {
	var graphTraversal *traversal.GraphTraversal
	var err error

	flowSearchQuery, err := s.makeFlowSearchQuery()
	if err != nil {
		return nil, err
	}

	var flowset *flow.FlowSet

	switch tv := last.(type) {
	case *traversal.GraphTraversal:
		graphTraversal = tv
		context := graphTraversal.Graph.GetContext()

		// if Since predicate present in a non time context query
		if s.hasSinceParam() && context.Time == nil {
			return nil, errors.New("Since predicate has to be used with Context step")
		}

		if context.Time != nil {
			if s.Storage == nil {
				return nil, storage.NoStorageConfigured
			}

			s.addTimeFilter(&flowSearchQuery, context.Time)

			// We do nothing as the following step is Metrics
			// and we'll make a request on metrics instead of flows
			if s.metricsNextStep {
				return &FlowTraversalStep{GraphTraversal: graphTraversal, Storage: s.Storage, flowSearchQuery: flowSearchQuery, since: s.sinceParam()}, nil
			}

			if flowset, err = s.Storage.SearchFlows(flowSearchQuery); err != nil {
				return nil, err
			}
		} else {
			flowset, err = s.TableClient.LookupFlows(flowSearchQuery)
		}
	case *traversal.GraphTraversalV:
		graphTraversal = tv.GraphTraversal
		context := graphTraversal.Graph.GetContext()

		// if Since predicate present in a non time context query
		if s.hasSinceParam() && context.Time == nil {
			return nil, errors.New("Since predicate has to be used with Context step")
		}

		// not need to get flows from node not supporting capture
		nodes := captureAllowedNodes(tv.GetNodes())
		if len(nodes) != 0 {
			if context.Time != nil {
				if s.Storage == nil {
					return nil, storage.NoStorageConfigured
				}

				s.addTimeFilter(&flowSearchQuery, context.Time)

				// previously selected nodes then need to filter flow belonging to them
				nodeFilter := flow.NewFilterForNodes(nodes)
				flowSearchQuery.Filter = flow.NewAndFilter(flowSearchQuery.Filter, nodeFilter)

				// We do nothing as the following step is Metrics
				// and we'll make a request on metrics instead of flows
				if s.metricsNextStep {
					return &FlowTraversalStep{GraphTraversal: graphTraversal, Storage: s.Storage, flowSearchQuery: flowSearchQuery, since: s.sinceParam()}, nil
				}

				if flowset, err = s.Storage.SearchFlows(flowSearchQuery); err != nil {
					return nil, err
				}
			} else {
				hnmap := topology.BuildHostNodeTIDMap(nodes)
				flowset, err = s.TableClient.LookupFlowsByNodes(hnmap, flowSearchQuery)
			}
		}
	default:
		return nil, traversal.ExecutionError
	}

	if err != nil {
		logging.GetLogger().Errorf("Error while looking for flows: %s", err.Error())
		return nil, err
	}

	if r := s.context.StepContext.PaginationRange; r != nil {
		flowset.Slice(int(r[0]), int(r[1]))
	}

	return &FlowTraversalStep{GraphTraversal: graphTraversal, Storage: s.Storage, flowset: flowset, flowSearchQuery: flowSearchQuery, since: s.sinceParam()}, nil
}