Analytical queries

Intro

StackState’s 3T (Topology, Telemetry and Time) can be queried via it’s analytical function executor. Analytical functions can be written in Groovy and have support voor Gremlin queries. StackState analytical functions can be tested via the analytical playground which can be found at: http://hostname:port/#/playground

Examples:

Get all components which are related to a specific component.

//Define a name for the component where we start the search.
def selectedComponent = "Invoicing"

//Open the graph
return Sts.graph().V()

  //Filter on component name
  .has("name", selectedComponent)

  //Hold a reference to the sub result
  .as("components")

  //Follow the component till the is no dependend component anymore
  .until(__.inE("HAS_SOURCE").count().is(0))

  //Repeat this step for all Component->HAS_SOURCE->Relation->HAS_TARGET->Component relations.
  .repeat(__.in("HAS_SOURCE").in("HAS_TARGET").simplePath().as("components"))

  //Select all "components"
  .select("components")

  //Unfold the arrays in arrays from the result 
  .unfold()

  //Remove duplicates
  .dedup()

List all components which depend on a specific component and have the state CRITICAL

//Define a name for the component where we start the search.
def selectedComponent = "srv02"

//Open the graph
return Sts.graph().V()

  //Filter on component name
  .has("name", selectedComponent)

  //Hold a reference to the sub result
  .as("components")

  //Follow the component till the is no dependend component anymore
  .until(__.inE("HAS_SOURCE").count().is(0))

  //Repeat this step for all Component->HAS_SOURCE->Relation->HAS_TARGET->Component relations.
  .repeat(__.in("HAS_SOURCE").in("HAS_TARGET").simplePath().as("components"))

  //Select all "components"
  .select("components")

  //Unfold the arrays in arrays from the result 
  .unfold()

  //Remove duplicates
  .dedup()

  //Filter on components with the healthState attribute "CRITICAL"
  .where(__.out("HAS_HEALTH_STATE").has("healthState", "CRITICAL"))

List the value of a particular Vertex in the graph.

return Sts.graph().V()
  //Select all Vertexes with the label Component (=Class Component)
  .hasLabel("Component")

  //Get 1 sample
  .sample(1)

  //Show the values
  .valueMap()

List the outgoing edges in the graph.

return Sts.graph().V()
  //Select all Vertexes with the label Component (=Class Component)
  .hasLabel('Component')
  
  //Outgoing edges
  .outE()

  //Group and count them
  .groupCount()

  //By EDGE label
  .by(label)

List a job with it’s upstream jobs upto N levels of dependencies

//NOTE: Upstream/downstream is the information-flow direction which for batch jobs is opposite to the
// dependency direction that is modeled in StackState.
def jobNames = ["sl2-INTACC"];
def maxDepth = 1;

// Dependencies / upstream dataflow:
def upstream = Sts.graph().V().hasLabel("Component").has("name", within(jobNames))
  .where(__.out("HAS_LABEL").has("name", "autosys"))
  .as("elements")
  .until(__.outE("HAS_TARGET").count().is(0).or().loops().is(gt(maxDepth-1)))
  .repeat(__.out("HAS_TARGET").as("elements").out("HAS_SOURCE").simplePath().as("elements"))
  .select("elements").unfold().dedup();

return upstream;

List a job with it’s upstream jobs upto N levels of dependencies Optionally project only name + states + streamIds Optionally filter the subgraph on some properties like: name, having a run state or having some streams

//NOTE: Upstream/downstream is the information-flow direction which for batch jobs is opposite to the
// dependency direction that is modeled in StackState.
def jobNames = ["sl2-INTACC"];
def maxDepth = 1;

// Dependents / downstream dataflow:
def downstream = Sts.graph().V().hasLabel("Component").has("name", within(jobNames))
  .where(__.out("HAS_LABEL").has("name", "autosys"))
  .as("elements")
  .until(__.inE("HAS_SOURCE").count().is(0).or().loops().is(gt(maxDepth-1)))
  .repeat(__.in("HAS_SOURCE").as("elements").in("HAS_TARGET").simplePath().as("elements"))
  .select("elements").unfold().dedup();

return upstream;

// To project only name + states + streamIds append this projection:
.project("runState", "healthState", "name", "streams")
  .by(__.out("HAS_RUN_STATE").values("runState"))
  .by(__.out("HAS_HEALTH_STATE").values("healthState"))
  .by(__.values("name"))
  .by(__.out("HAS_DATA_STREAM").project("id", "name").by(__.id()).by(__.values("name")).fold());

// Use match instead of project to add additional filtering, example for only elements with streams:
.match(
      __.as("element").values("name").as("name"),
      __.as("element").out("HAS_DATA_STREAM"),
      __.as("element").out("HAS_RUN_STATE").values("runState").as("runState")
      )
  .select("name", "runState")

Give a disjoint graph listing all DBs (filtered by some basic parameters - only Sybase, only DB2 etc..) and their basic health information and telemetry

return Sts.graph().V().hasLabel("Component")
  .where(__.out("HAS_LABEL").has("name", "database")); //Add other where steps for other filters on labels and related nodes