Search

Impact Analysis

Layouts

Reveal the dependencies and significance of nodes.

Impact Analysis
View live example →

In most networks it’s important to know which nodes have the greatest impact, and consider what the effects would be if they failed.

In the Impact view, all nodes are sized based on how many nodes depend on them. In the Alerts view, only nodes with warnings or errors are sized by their dependencies.

By interacting with the chart, you can focus on a single node and examine its dependencies.

Styling in KeyLines can also improve the flow of the chart. For example, gradients on links matching the node colours on each end can smooth the transitions between areas on the graph and curved links applied to sequential layout enhance the directionality of links.

Key functions used:

import KeyLines from "keylines";
import {
  data,
  fontIcons,
  errorColour,
  warningColour,
  dimmedColour,
  bgColour,
  annotationsState,
} from "./data.js";

// declaring global vars
let chart;
let impactAlertsSelection = document.querySelector('input[name="dependencyView"]:checked').value;
let showNodes = null;
let selectedNodeId = null;
const squareNodeText = {};
const rectangleNodeText = {};
const initialNodeStyles = [];
const alertsItems = [];
let hoveredGlyphId = null;
let hoveredAnnotationGlyphId = null;

const graph = KeyLines.getGraphEngine();
graph.load(data);

const impactAlertsRadios = Array.from(document.querySelectorAll('input[name="dependencyView"]'));
const alertsList = document.getElementById("alerts");
const resetButton = document.getElementById("reset");

function getScaleFactor(numOfDeps) {
  return numOfDeps ** (1 / 3);
}

function highlightErrorsAndWarnings() {
  const colourItems = [];
  const warnings = [];
  let errors = [];

  chart.each({ type: "node" }, (item) => {
    if (item.d.logLevel === "error") {
      errors.push(item.id);
      let neighbours = graph.neighbours(item.id, { direction: "from", hops: 5 }).nodes;
      errors = errors.concat(neighbours);
    } else if (item.d.logLevel !== "warning") {
      colourItems.push({ id: item.id, c: dimmedColour });
    }
  });
  chart.each({ type: "node" }, (item) => {
    if (item.d.logLevel === "warning") {
      warnings.push(item.id);
      let neighbours = graph.neighbours(item.id, { direction: "from", hops: 5 }).nodes;
      neighbours.forEach((id) => {
        if (!errors.includes(id)) {
          warnings.push(id);
        }
      });
    }
  });
  errors.forEach((id) => colourItems.push({ id, c: errorColour }));
  warnings.forEach((id) => colourItems.push({ id, c: warningColour }));

  chart.each({ type: "link" }, (item) => {
    if (errors.includes(item.id2)) {
      colourItems.push({ id: item.id, c: errorColour, c2: errorColour });
    } else if (warnings.includes(item.id2)) {
      colourItems.push({ id: item.id, c: warningColour, c2: warningColour });
    } else {
      colourItems.push({ id: item.id, c: dimmedColour, c2: dimmedColour });
    }
  });
  chart.setProperties(colourItems);
  applyAnnotationStateUpdateToChart();
}

function applyAnnotationStateUpdateToChart() {
  const annotations = [];
  for (const [_, value] of Object.entries(annotationsState)) {
    if (value.hidden) continue;
    annotations.push(value.annotation);
  }
  chart.merge(annotations);
}

function removeAnnotationFromChart(id) {
  chart.removeItem(id);
}

function constructTable() {
  const tableBody = document.querySelector(".alertsTableBody");
  alertsItems.forEach((item) => {
    const label = document.createElement("td");
    const labelText = document.createTextNode(item.label);
    label.appendChild(labelText);

    const type = document.createElement("td");
    const typeText = document.createTextNode(
      item.type.charAt(0).toUpperCase() + item.type.slice(1)
    );
    type.appendChild(typeText);

    const description = document.createElement("td");
    const descriptionText = document.createTextNode(item.description);
    description.appendChild(descriptionText);

    const row = document.createElement("tr");
    row.id = item.nodeId;
    row.setAttribute("name", "alertRow");
    row.appendChild(label);
    row.appendChild(type);
    row.appendChild(description);
    row.onclick = function () {
      setSelection({ id: item.nodeId });
    };

    tableBody.appendChild(row);
  });
}

function clearTableStyling() {
  const alertsTableRows = document.querySelectorAll('tr[name="alertRow"]');
  alertsTableRows.forEach((row) => {
    row.classList.remove("selected-row");
  });
}

function showHideAlertsList() {
  impactAlertsSelection = document.querySelector('input[name="dependencyView"]:checked').value;

  if (impactAlertsSelection === "impact") {
    chart.each({ type: "annotation" }, (annotation) => {
      chart.removeItem(annotation.id);
    });
    chart.setProperties(initialNodeStyles);
    alertsList.classList.add("hidden");
  } else {
    highlightErrorsAndWarnings();
    alertsList.classList.remove("hidden");
  }
}

async function applyFilters() {
  chart.lock(true);
  const result = await chart.filter(
    (item) => {
      if (item.type === "node" && showNodes) {
        return showNodes[item.id] !== undefined;
      }
      return true;
    },
    { time: 300 }
  );
  chart.lock(false);
  return result;
}

async function doLayout() {
  const layoutOptions = {
    consistent: true,
    mode: "adaptive",
  };
  let layoutName;
  // A node needs to be selected for the selected layout to be run
  if (selectedNodeId) {
    // Set the top node to be the selected one
    layoutName = "sequential";

    // Increase the space between levels for gentler curves in the links
    // but reduce the space between nodes within the same level
    layoutOptions.stretch = 2;
    layoutOptions.tightness = 8;
    layoutOptions.orientation = "right";
    layoutOptions.linkShape = "curved";
  } else {
    layoutName = "organic";
    layoutOptions.tightness = 6;
  }
  await chart.layout(layoutName, layoutOptions);
}

function hoverReaction({ id, subItem }) {
  const item = chart.getItem(id);
  const isAnnotation = id && id.includes("annotation");
  const changes = [];

  // Clear any existing hover styling
  if (hoveredGlyphId) {
    const node = chart.getItem(hoveredGlyphId);
    chart.setProperties({
      id: hoveredGlyphId,
      g: [
        {
          ...node.g[0],
          border: {
            width: 1.5,
            colour: bgColour,
          },
        },
      ],
    });
    hoveredGlyphId = null;
  }

  if (hoveredAnnotationGlyphId) {
    const annotation = chart.getItem(hoveredAnnotationGlyphId);
    if (annotation) {
      changes.push({
        id: hoveredAnnotationGlyphId,
        g: [
          annotation.g[0],
          {
            ...annotation.g[1],
            border: {
              width: 1.5,
              colour: bgColour,
            },
          },
        ],
      });
    }
    hoveredAnnotationGlyphId = null;
  }

  // Add any new glyph hover styling
  if (subItem.type === "glyph" && !isAnnotation) {
    hoveredGlyphId = id;
    chart.setProperties({
      id,
      g: [
        {
          ...item.g[0],
          border: {
            width: 1.5,
            colour: "white",
          },
        },
      ],
    });
  }

  if (isAnnotation && subItem.type === "glyph" && subItem.index === 1) {
    chart.setProperties({
      id,
      g: [
        item.g[0],
        {
          ...item.g[1],
          border: {
            width: 1.5,
            colour: "white",
          },
        },
      ],
    });
    hoveredAnnotationGlyphId = id;
    return;
  }

  // Handle node + node's tree hover styling and clearing
  const tree = item && item.type === "node" ? graph.distances(id, { direction: "from" }) : [];
  chart.each({ type: "node" }, (node) => {
    // don't overwrite selected node styling
    if (node.id !== selectedNodeId) {
      const highlight = node.id in tree && !hoveredGlyphId;
      const borderWidth = node.w === 300 ? node.w / 40 : node.w / 20;
      changes.push({
        id: node.id,
        b: highlight ? "white" : undefined,
        bw: highlight ? borderWidth : 0,
      });
    }
  });

  chart.setProperties(changes);
}

async function setSelection({ id, subItem }) {
  const isAnnotation = id && id.includes("annotation");
  if (id && subItem?.type === "glyph" && !isAnnotation) {
    annotationsState[id].hidden = false;
    applyAnnotationStateUpdateToChart();
    chart.setProperties({ id, g: [] });
    return;
  }

  if (isAnnotation && subItem?.type === "glyph" && subItem.index === 1) {
    const subjectId = chart.getItem(id).subject;
    annotationsState[subjectId].hidden = true;
    removeAnnotationFromChart(id);
    chart.setProperties({ id: subjectId, g: [annotationsState[subjectId].glyphStyling] });
    return;
  }

  if (isAnnotation) {
    // annotations are not selectable
    return;
  }

  clearTableStyling();
  // Update the selected node with the one passed in
  if (id === null) {
    const prevSelectedNodeId = selectedNodeId;
    selectedNodeId = null;
    resetButton.disabled = true;
    setNodeStyling("square");

    // click on chart background or network button - reshow hidden items
    showNodes = null;
    if (prevSelectedNodeId) {
      const result = await applyFilters();
      // Only layout if any nodes were shown or hidden
      if (result.shown.nodes.length > 0 || result.hidden.nodes.length > 0) {
        doLayout();
      }
    }
  } else {
    selectedNodeId = id;
    const item = chart.getItem(id);
    chart.selection(id);
    if (item && item.type === "node") {
      resetButton.disabled = false;
      const alertTableRow = document.getElementById(id);
      if (alertTableRow) {
        alertTableRow.classList.add("selected-row");
      }

      showNodes = {
        ...graph.distances(id, { direction: "to" }),
        ...graph.distances(id, { direction: "from" }),
      };
      if (item.d.dependencies.length) {
        item.d.dependencies.forEach((id) => (showNodes[id] = 1));
      }
      await applyFilters();
      setNodeStyling("rectangle");
      doLayout();
    }
  }
}

function storeNodeStyling() {
  const fontColour = bgColour;
  const backgroundColour = "rgba(0,0,0,0)";
  // set and store label styling for square and rectanglular nodes
  data.items.forEach((item) => {
    if (item.type === "node") {
      squareNodeText[item.id] = {
        t: [
          {
            fi: {
              t: fontIcons[item.d.type],
            },
            position: {
              vertical: "top",
            },
            fc: fontColour,
            fbc: backgroundColour,
          },
          {
            t: item.t.replace("-", "\n"),
            position: {
              vertical: "middle",
            },
            fc: fontColour,
            fbc: backgroundColour,
            fb: true,
          },
        ],
      };
      rectangleNodeText[item.id] = {
        fi: null,
        t: [
          {
            fi: {
              t: fontIcons[item.d.type],
            },
            position: {
              vertical: "middle",
              horizontal: "left",
            },
            fc: fontColour,
            fbc: backgroundColour,
            fs: 30,
            padding: {
              left: 13,
            },
          },
          {
            t: item.t,
            fc: fontColour,
            fbc: backgroundColour,
            position: {
              vertical: "top",
              horizontal: 45,
            },
            padding: {
              top: item.d.logMessage ? 19 : 24,
            },
            fb: true,
          },
          {
            fc: fontColour,
            fbc: backgroundColour,
            t: item.d.logMessage,
            fs: 9,
          },
        ],
      };
      initialNodeStyles.push({ id: item.id, c: item.c });
    } else if (item.type === "link") {
      initialNodeStyles.push({ id: item.id, c: item.c, c2: item.c2 });
    }
  });
}

function setNodeStyling(shape) {
  const isRectangle = shape === "rectangle";
  const styles = [];

  chart.each({ type: "node" }, (node) => {
    const id = node.id;
    const logLevel = node.d.logLevel;
    const b = id === selectedNodeId ? "white" : node.c;
    const bw = 6;
    let scaleFactor = 1;
    let w = 40;
    let h = 50;
    let borderRadius = 10;
    let t;
    let g = [];

    const dependencies = Object.keys(graph.distances(id, { direction: "from" })).length;

    if (impactAlertsSelection === "impact" || logLevel) {
      if (dependencies > 0) {
        scaleFactor = getScaleFactor(dependencies);
      }
    }

    if (isRectangle) {
      t = [...rectangleNodeText[node.id].t];
      w = 300;
      h = 60;

      t[0].fs = 48;
      t[0].padding = { right: 30, left: 15 };
      t[1].margin = { left: 14 };
      if (t[2]) {
        t[2].margin = { left: 14 };
      }
    } else {
      t = [...squareNodeText[node.id].t];
      w = h *= scaleFactor;
      borderRadius *= scaleFactor;
      t[0].fs = 22 * scaleFactor;
      t[0].padding = { top: 7 * scaleFactor };
      t[1].fs = 5 * scaleFactor;
      t[1].padding = { top: 17 * scaleFactor };
    }

    if (impactAlertsSelection === "alerts" && logLevel) {
      const icon = fontIcons.exclamationTriangle;
      const iconSize = isRectangle ? 2 : 1.2 * scaleFactor;
      const glyphStyling = {
        c: "white",
        p: "ne",
        fi: {
          t: icon,
          c: bgColour,
        },
        e: iconSize,
        border: {
          width: 1.5,
          colour: bgColour,
        },
      };

      if (annotationsState[id].hidden) {
        g.push(glyphStyling);
      }
      annotationsState[id].glyphStyling = glyphStyling;
    }

    styles.push({ id, t, w, h, b, bw, borderRadius, g });
  });
  chart.setProperties(styles);
}

function initialiseInteractions() {
  // On hover, foreground connected nodes
  chart.on("hover", hoverReaction);
  // On click, focus on the selected node
  chart.on("click", setSelection);
  // Hide/show alerts list based on radio selection
  impactAlertsRadios.forEach((radio) => {
    radio.addEventListener("click", () => {
      showHideAlertsList();
      const isAnnotation = selectedNodeId && selectedNodeId.includes("annotation");
      setSelection({ id: isAnnotation ? null : selectedNodeId });
      doLayout();
    });
  });
  resetButton.addEventListener("click", () => setSelection({ id: null }));
}

function initialiseTableData() {
  data.items.forEach((item) => {
    if (item.type == "node" && item.d.logLevel) {
      alertsItems.push({
        label: item.t,
        type: item.d.logLevel,
        description: item.d.logMessage,
        nodeId: item.id,
      });
    }
  });
}

async function startKeyLines() {
  const imageAlignment = {
    "fas fa-server": { e: 0.75 },
    "fas fa-desktop": { e: 0.75 },
    "fas fa-exclamation-triangle": { dy: -11 },
  };

  const options = {
    arrows: "large",
    backColour: bgColour,
    navigation: false,
    overview: false,
    drag: {
      links: false,
    },
    hover: 0,
    handMode: true,
    minZoom: 0.02,
    iconFontFamily: "Font Awesome 5 Free",
    imageAlignment,
    // Disable chart selection styles
    selectedNode: {},
    selectedLink: {},
  };

  chart = await KeyLines.create({
    container: "klchart",
    options,
  });

  chart.load(data);
  initialiseInteractions();
  initialiseTableData();
  constructTable();
  storeNodeStyling();
  setNodeStyling("square");
  doLayout();
}

function loadKeyLines() {
  document.fonts.load('24px "Font Awesome 5 Free"').then(startKeyLines);
}

window.addEventListener("DOMContentLoaded", loadKeyLines);
import KeyLines from "keylines";
export const fontIcons = {
  switch: "fas fa-exchange-alt",
  server: "fas fa-server ",
  vhost: "fas fa-server",
  service: "fas fa-desktop",
  exclamationTriangle: "fas fa-exclamation-triangle",
  eyeSlash: "fas fa-eye-slash",
};

export const errorColour = "#FF6052";
export const warningColour = "rgba(254,221,0,1)";
export const dimmedColour = "#969696";
export const bgColour = "#212121";

const virtualHostColour = "#75D8FF";
const serverColour = "#2CE0C2";
const serviceColour = "#4598F7";
const switchColour = "#56F580";

const errorColourLight = "rgb(255, 140, 130)";
const warningColourLight = "rgb(236, 223, 138)";

export const data = {
  type: "LinkChart",
  items: [
    {
      type: "link",
      id: "svr-a-plg-c",
      id1: "svr-a",
      id2: "plg-c",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-b-plg-d",
      id1: "svr-b",
      id2: "plg-d",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-c-plg-b",
      id1: "svr-c",
      id2: "plg-b",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-c-plg-d",
      id1: "svr-c",
      id2: "plg-d",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-d-plg-c",
      id1: "svr-d",
      id2: "plg-c",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-d-plg-b",
      id1: "svr-d",
      id2: "plg-b",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-e-plg-c",
      id1: "svr-e",
      id2: "plg-c",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-f-plg-d",
      id1: "svr-f",
      id2: "plg-d",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-g-plg-a",
      id1: "svr-g",
      id2: "plg-a",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-h-plg-c",
      id1: "svr-h",
      id2: "plg-c",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-i-plg-a",
      id1: "svr-i",
      id2: "plg-a",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-j-plg-a",
      id1: "svr-j",
      id2: "plg-a",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-k-plg-a",
      id1: "svr-k",
      id2: "plg-a",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "svr-k-plg-c",
      id1: "svr-k",
      id2: "plg-c",
      a1: true,
      w: 4,
      off: 0,
      c: serverColour,
      c2: switchColour,
    },
    {
      type: "link",
      id: "vh-a-svr-e",
      id1: "vh-a",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-a-svr-b",
      id1: "vh-a",
      id2: "svr-b",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-a-svr-f",
      id1: "vh-a",
      id2: "svr-f",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-b-svr-i",
      id1: "vh-b",
      id2: "svr-i",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-c-svr-c",
      id1: "vh-c",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-c-svr-j",
      id1: "vh-c",
      id2: "svr-j",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-d-svr-k",
      id1: "vh-d",
      id2: "svr-k",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-d-svr-a",
      id1: "vh-d",
      id2: "svr-a",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-e-svr-i",
      id1: "vh-e",
      id2: "svr-i",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-e-svr-d",
      id1: "vh-e",
      id2: "svr-d",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-f-svr-c",
      id1: "vh-f",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-f-svr-b",
      id1: "vh-f",
      id2: "svr-b",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-g-svr-b",
      id1: "vh-g",
      id2: "svr-b",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-h-svr-d",
      id1: "vh-h",
      id2: "svr-d",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-i-svr-c",
      id1: "vh-i",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-j-svr-e",
      id1: "vh-j",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-k-svr-j",
      id1: "vh-k",
      id2: "svr-j",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-l-svr-e",
      id1: "vh-l",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-l-svr-f",
      id1: "vh-l",
      id2: "svr-f",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-l-svr-h",
      id1: "vh-l",
      id2: "svr-h",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-m-svr-j",
      id1: "vh-m",
      id2: "svr-j",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-n-svr-h",
      id1: "vh-n",
      id2: "svr-h",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-n-svr-e",
      id1: "vh-n",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-o-svr-b",
      id1: "vh-o",
      id2: "svr-b",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-p-svr-e",
      id1: "vh-p",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-p-svr-a",
      id1: "vh-p",
      id2: "svr-a",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-q-svr-b",
      id1: "vh-q",
      id2: "svr-b",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-q-svr-g",
      id1: "vh-q",
      id2: "svr-g",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-r-svr-c",
      id1: "vh-r",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-r-svr-k",
      id1: "vh-r",
      id2: "svr-k",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-s-svr-f",
      id1: "vh-s",
      id2: "svr-f",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-s-svr-k",
      id1: "vh-s",
      id2: "svr-k",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-t-svr-g",
      id1: "vh-t",
      id2: "svr-g",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-u-svr-f",
      id1: "vh-u",
      id2: "svr-f",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-u-svr-e",
      id1: "vh-u",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-v-svr-h",
      id1: "vh-v",
      id2: "svr-h",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-w-svr-i",
      id1: "vh-w",
      id2: "svr-i",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-w-svr-c",
      id1: "vh-w",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-x-svr-d",
      id1: "vh-x",
      id2: "svr-d",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-y-svr-j",
      id1: "vh-y",
      id2: "svr-j",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-y-svr-b",
      id1: "vh-y",
      id2: "svr-b",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-z-svr-k",
      id1: "vh-z",
      id2: "svr-k",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-z-svr-e",
      id1: "vh-z",
      id2: "svr-e",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ab-svr-c",
      id1: "vh-ab",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ab-svr-j",
      id1: "vh-ab",
      id2: "svr-j",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ac-svr-f",
      id1: "vh-ac",
      id2: "svr-f",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ac-svr-d",
      id1: "vh-ac",
      id2: "svr-d",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ad-svr-j",
      id1: "vh-ad",
      id2: "svr-j",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ae-svr-h",
      id1: "vh-ae",
      id2: "svr-h",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-af-svr-c",
      id1: "vh-af",
      id2: "svr-c",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-af-svr-i",
      id1: "vh-af",
      id2: "svr-i",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ag-svr-f",
      id1: "vh-ag",
      id2: "svr-f",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "vh-ah-svr-i",
      id1: "vh-ah",
      id2: "svr-i",
      a1: true,
      w: 4,
      off: 0,
      c: virtualHostColour,
      c2: serverColour,
    },
    {
      type: "link",
      id: "srvc-a-vh-q",
      id1: "srvc-a",
      id2: "vh-q",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-b-vh-j",
      id1: "srvc-b",
      id2: "vh-j",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-c-vh-f",
      id1: "srvc-c",
      id2: "vh-f",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-c-vh-m",
      id1: "srvc-c",
      id2: "vh-m",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-d-vh-c",
      id1: "srvc-d",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-e-vh-af",
      id1: "srvc-e",
      id2: "vh-af",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-e-vh-v",
      id1: "srvc-e",
      id2: "vh-v",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-f-vh-h",
      id1: "srvc-f",
      id2: "vh-h",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-f-vh-m",
      id1: "srvc-f",
      id2: "vh-m",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-g-vh-k",
      id1: "srvc-g",
      id2: "vh-k",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-g-vh-d",
      id1: "srvc-g",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-h-vh-d",
      id1: "srvc-h",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-i-vh-d",
      id1: "srvc-i",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-i-vh-i",
      id1: "srvc-i",
      id2: "vh-i",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-j-vh-c",
      id1: "srvc-j",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-j-vh-j",
      id1: "srvc-j",
      id2: "vh-j",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-k-vh-v",
      id1: "srvc-k",
      id2: "vh-v",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-l-vh-ab",
      id1: "srvc-l",
      id2: "vh-ab",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-m-vh-e",
      id1: "srvc-m",
      id2: "vh-e",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-n-vh-s",
      id1: "srvc-n",
      id2: "vh-s",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-n-vh-i",
      id1: "srvc-n",
      id2: "vh-i",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-o-vh-o",
      id1: "srvc-o",
      id2: "vh-o",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-o-vh-af",
      id1: "srvc-o",
      id2: "vh-af",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-p-vh-c",
      id1: "srvc-p",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-q-vh-u",
      id1: "srvc-q",
      id2: "vh-u",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-r-vh-l",
      id1: "srvc-r",
      id2: "vh-l",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-s-vh-v",
      id1: "srvc-s",
      id2: "vh-v",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-t-vh-d",
      id1: "srvc-t",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-u-vh-l",
      id1: "srvc-u",
      id2: "vh-l",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-v-vh-n",
      id1: "srvc-v",
      id2: "vh-n",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-w-vh-a",
      id1: "srvc-w",
      id2: "vh-a",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-w-vh-c",
      id1: "srvc-w",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-x-vh-o",
      id1: "srvc-x",
      id2: "vh-o",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-y-vh-s",
      id1: "srvc-y",
      id2: "vh-s",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-z-vh-m",
      id1: "srvc-z",
      id2: "vh-m",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-z-vh-ae",
      id1: "srvc-z",
      id2: "vh-ae",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-z-vh-h",
      id1: "srvc-z",
      id2: "vh-h",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aa-vh-j",
      id1: "srvc-aa",
      id2: "vh-j",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aa-vh-c",
      id1: "srvc-aa",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ab-vh-e",
      id1: "srvc-ab",
      id2: "vh-e",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ac-vh-h",
      id1: "srvc-ac",
      id2: "vh-h",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ac-vh-b",
      id1: "srvc-ac",
      id2: "vh-b",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ac-vh-j",
      id1: "srvc-ac",
      id2: "vh-j",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ad-vh-d",
      id1: "srvc-ad",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ae-vh-ae",
      id1: "srvc-ae",
      id2: "vh-ae",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-af-vh-a",
      id1: "srvc-af",
      id2: "vh-a",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ag-vh-af",
      id1: "srvc-ag",
      id2: "vh-af",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ah-vh-r",
      id1: "srvc-ah",
      id2: "vh-r",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ah-vh-ag",
      id1: "srvc-ah",
      id2: "vh-ag",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ai-vh-w",
      id1: "srvc-ai",
      id2: "vh-w",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aj-vh-h",
      id1: "srvc-aj",
      id2: "vh-h",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aj-vh-b",
      id1: "srvc-aj",
      id2: "vh-b",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ak-vh-l",
      id1: "srvc-ak",
      id2: "vh-l",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-al-vh-w",
      id1: "srvc-al",
      id2: "vh-w",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-al-vh-h",
      id1: "srvc-al",
      id2: "vh-h",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-am-vh-r",
      id1: "srvc-am",
      id2: "vh-r",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-am-vh-c",
      id1: "srvc-am",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-an-vh-y",
      id1: "srvc-an",
      id2: "vh-y",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-an-vh-d",
      id1: "srvc-an",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-an-vh-k",
      id1: "srvc-an",
      id2: "vh-k",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ao-vh-i",
      id1: "srvc-ao",
      id2: "vh-i",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ao-vh-p",
      id1: "srvc-ao",
      id2: "vh-p",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ap-vh-s",
      id1: "srvc-ap",
      id2: "vh-s",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ap-vh-d",
      id1: "srvc-ap",
      id2: "vh-d",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aq-vh-l",
      id1: "srvc-aq",
      id2: "vh-l",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aq-vh-ac",
      id1: "srvc-aq",
      id2: "vh-ac",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ar-vh-r",
      id1: "srvc-ar",
      id2: "vh-r",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-as-vh-t",
      id1: "srvc-as",
      id2: "vh-t",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-as-vh-ae",
      id1: "srvc-as",
      id2: "vh-ae",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-at-vh-af",
      id1: "srvc-at",
      id2: "vh-af",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-au-vh-ae",
      id1: "srvc-au",
      id2: "vh-ae",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-au-vh-y",
      id1: "srvc-au",
      id2: "vh-y",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-av-vh-s",
      id1: "srvc-av",
      id2: "vh-s",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-av-vh-ah",
      id1: "srvc-av",
      id2: "vh-ah",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aw-vh-k",
      id1: "srvc-aw",
      id2: "vh-k",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-aw-vh-af",
      id1: "srvc-aw",
      id2: "vh-af",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ax-vh-g",
      id1: "srvc-ax",
      id2: "vh-g",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ax-vh-j",
      id1: "srvc-ax",
      id2: "vh-j",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ay-vh-af",
      id1: "srvc-ay",
      id2: "vh-af",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ay-vh-z",
      id1: "srvc-ay",
      id2: "vh-z",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-az-vh-ad",
      id1: "srvc-az",
      id2: "vh-ad",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-ba-vh-m",
      id1: "srvc-ba",
      id2: "vh-m",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bb-vh-o",
      id1: "srvc-bb",
      id2: "vh-o",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bb-vh-n",
      id1: "srvc-bb",
      id2: "vh-n",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bc-vh-o",
      id1: "srvc-bc",
      id2: "vh-o",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bc-vh-ac",
      id1: "srvc-bc",
      id2: "vh-ac",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bd-vh-ac",
      id1: "srvc-bd",
      id2: "vh-ac",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-be-vh-u",
      id1: "srvc-be",
      id2: "vh-u",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bf-vh-c",
      id1: "srvc-bf",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bg-vh-q",
      id1: "srvc-bg",
      id2: "vh-q",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bh-vh-ag",
      id1: "srvc-bh",
      id2: "vh-ag",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bi-vh-q",
      id1: "srvc-bi",
      id2: "vh-q",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bj-vh-o",
      id1: "srvc-bj",
      id2: "vh-o",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bk-vh-g",
      id1: "srvc-bk",
      id2: "vh-g",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bl-vh-ag",
      id1: "srvc-bl",
      id2: "vh-ag",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bl-vh-j",
      id1: "srvc-bl",
      id2: "vh-j",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bm-vh-x",
      id1: "srvc-bm",
      id2: "vh-x",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bn-vh-b",
      id1: "srvc-bn",
      id2: "vh-b",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bo-vh-c",
      id1: "srvc-bo",
      id2: "vh-c",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bp-vh-r",
      id1: "srvc-bp",
      id2: "vh-r",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bp-vh-ae",
      id1: "srvc-bp",
      id2: "vh-ae",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bp-vh-y",
      id1: "srvc-bp",
      id2: "vh-y",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bq-vh-h",
      id1: "srvc-bq",
      id2: "vh-h",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-br-vh-o",
      id1: "srvc-br",
      id2: "vh-o",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-br-vh-z",
      id1: "srvc-br",
      id2: "vh-z",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bs-vh-r",
      id1: "srvc-bs",
      id2: "vh-r",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bt-vh-p",
      id1: "srvc-bt",
      id2: "vh-p",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bu-vh-ac",
      id1: "srvc-bu",
      id2: "vh-ac",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bu-vh-ae",
      id1: "srvc-bu",
      id2: "vh-ae",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bv-vh-p",
      id1: "srvc-bv",
      id2: "vh-p",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bw-vh-q",
      id1: "srvc-bw",
      id2: "vh-q",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "link",
      id: "srvc-bw-vh-e",
      id1: "srvc-bw",
      id2: "vh-e",
      a1: true,
      w: 4,
      off: 0,
      c: serviceColour,
      c2: virtualHostColour,
    },
    {
      type: "node",
      id: "plg-a",
      d: {
        dependencies: [],
        type: "switch",
      },
      t: "FabricSwitch-VD437S",
      c: switchColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 36.293919476815745,
      y: -326.6685655173378,
    },
    {
      type: "node",
      id: "plg-b",
      d: {
        dependencies: [],
        type: "switch",
      },
      t: "CoreSwitch-LEEVT1",
      c: switchColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 170.17075764666856,
      y: -97.63155036141916,
    },
    {
      type: "node",
      id: "plg-c",
      d: {
        dependencies: [],
        type: "switch",
      },
      t: "DistributionSwitch-35PIFE",
      c: switchColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 23.041640436129,
      y: 300.1910167514777,
    },
    {
      type: "node",
      id: "plg-d",
      d: {
        dependencies: [],
        type: "switch",
      },
      t: "DistributionSwitch-27JYV2",
      c: switchColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 39.68718775331786,
      y: 45.89615865799851,
    },
    {
      type: "node",
      id: "svr-a",
      d: {
        dependencies: ["plg-c"],
        type: "server",
      },
      t: "DatabaseServer-57T5EK",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -467.39816954142555,
      y: 390.215678910688,
    },
    {
      type: "node",
      id: "svr-b",
      d: {
        dependencies: ["plg-d"],
        type: "server",
      },
      t: "BackupServer-BIGKYQ",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 276.6181944396176,
      y: -214.95726398739407,
    },
    {
      type: "node",
      id: "svr-c",
      d: {
        dependencies: ["plg-b", "plg-d"],
        type: "server",
      },
      t: "CacheNode-WWT0M0",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -201.04870729816207,
      y: -233.65609608511113,
    },
    {
      type: "node",
      id: "svr-d",
      d: {
        dependencies: ["plg-c", "plg-b"],
        logLevel: "error",
        logMessage: "Alert Status: Error",
        type: "server",
        generatedErrorMessage: "Filesystem corruption detected.",
      },
      t: "BackupServer-9G4T9R",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 504.50400977174377,
      y: 50.22944419582768,
    },
    {
      type: "node",
      id: "svr-e",
      d: {
        dependencies: ["plg-c"],
        type: "server",
      },
      t: "AppServer-GKV9WY",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -71.40906428503922,
      y: 540.189024532847,
    },
    {
      type: "node",
      id: "svr-f",
      d: {
        dependencies: ["plg-d"],
        logLevel: "warning",
        logMessage: "Alert Status: Warning",
        type: "server",
        generatedErrorMessage: "High load average over past 15 minutes.",
      },
      t: "DatabaseServer-CUSH1U",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 0.7764675999626434,
      y: 495.133234493715,
    },
    {
      type: "node",
      id: "svr-g",
      d: {
        dependencies: ["plg-a"],
        type: "server",
      },
      t: "BackupServer-ZPO9VO",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 434.43532649996473,
      y: -530.0771515772517,
    },
    {
      type: "node",
      id: "svr-h",
      d: {
        dependencies: ["plg-c"],
        type: "server",
      },
      t: "StorageNode-6WM5O8",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 292.52370799749747,
      y: 521.7110172205962,
    },
    {
      type: "node",
      id: "svr-i",
      d: {
        dependencies: ["plg-a"],
        type: "server",
      },
      t: "DatabaseServer-XZU81P",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 327.4417521141045,
      y: -128.99087832395207,
    },
    {
      type: "node",
      id: "svr-j",
      d: {
        dependencies: ["plg-a"],
        type: "server",
      },
      t: "DatabaseServer-5DM4J4",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -223.80189572379732,
      y: -633.1666210667211,
    },
    {
      type: "node",
      id: "svr-k",
      d: {
        dependencies: ["plg-a", "plg-c"],
        type: "server",
      },
      t: "ComputeNode-1TRAAJ",
      c: serverColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -303.4384984301439,
      y: 82.910369848556,
    },
    {
      type: "node",
      id: "vh-a",
      d: {
        dependencies: ["svr-e", "svr-b", "svr-f"],
        type: "vhost",
      },
      t: "FrontendProxy-7YXELJ",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -21.63747980753942,
      y: 125.84073666271229,
    },
    {
      type: "node",
      id: "vh-b",
      d: {
        dependencies: ["svr-i"],
        type: "vhost",
      },
      t: "RoutingProxy-PZPFTP",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 620.651025880278,
      y: -315.19753764585334,
    },
    {
      type: "node",
      id: "vh-c",
      d: {
        dependencies: ["svr-c", "svr-j"],
        logLevel: "warning",
        logMessage: "Alert Status: Warning",
        type: "server",
        generatedErrorMessage: "Available disk space below 10%.",
      },
      t: "APIServer-PMH81I",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -581.2472380312047,
      y: -522.6597560929174,
    },
    {
      type: "node",
      id: "vh-d",
      d: {
        dependencies: ["svr-k", "svr-a"],
        type: "vhost",
      },
      t: "StaticContentHost-5Z285B",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -794.1735252661058,
      y: 135.51083326363005,
    },
    {
      type: "node",
      id: "vh-e",
      d: {
        dependencies: ["svr-i", "svr-d"],
        type: "vhost",
      },
      t: "TLSOffloader-1I7E3S",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 794.3216232702387,
      y: -165.8911745010139,
    },
    {
      type: "node",
      id: "vh-f",
      d: {
        dependencies: ["svr-c", "svr-b"],
        type: "vhost",
      },
      t: "EdgeProxy-4BD94D",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 34.314044886223655,
      y: -511.3459741589014,
    },
    {
      type: "node",
      id: "vh-g",
      d: {
        dependencies: ["svr-b"],
        type: "vhost",
      },
      t: "CDNNode-CZNHQF",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 201.02429190843577,
      y: -563.6028990644295,
    },
    {
      type: "node",
      id: "vh-h",
      d: {
        dependencies: ["svr-d"],
        type: "vhost",
      },
      t: "APIGateway-OJFQJQ",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 594.1755547793603,
      y: -434.97526751164946,
    },
    {
      type: "node",
      id: "vh-i",
      d: {
        dependencies: ["svr-c"],
        type: "vhost",
      },
      t: "LoadBalancer-5GR6HP",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -619.4072295688568,
      y: 160.30227227767227,
    },
    {
      type: "node",
      id: "vh-j",
      d: {
        dependencies: ["svr-e"],
        type: "vhost",
      },
      t: "FrontendProxy-RWMD9V",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -200.0939970870363,
      y: -57.68433549645101,
    },
    {
      type: "node",
      id: "vh-k",
      d: {
        dependencies: ["svr-j"],
        type: "vhost",
      },
      t: "FrontendProxy-RPENX8",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -538.5393589226572,
      y: -366.13034072960204,
    },
    {
      type: "node",
      id: "vh-l",
      d: {
        dependencies: ["svr-e", "svr-f", "svr-h"],
        logLevel: "warning",
        logMessage: "Alert Status: Warning",
        type: "vhost",
        generatedErrorMessage: "High number of unsecure connections.",
      },
      t: "RoutingProxy-JUJQH7",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 225.71715469644732,
      y: 837.247163197907,
    },
    {
      type: "node",
      id: "vh-m",
      d: {
        dependencies: ["svr-j"],
        type: "vhost",
      },
      t: "RoutingProxy-0045VM",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 188.53417577903656,
      y: -808.1290200356626,
    },
    {
      type: "node",
      id: "vh-n",
      d: {
        dependencies: ["svr-h", "svr-e"],
        type: "vhost",
      },
      t: "TLSOffloader-6NHNFK",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 282.3215980361233,
      y: 745.7821275140136,
    },
    {
      type: "node",
      id: "vh-o",
      d: {
        dependencies: ["svr-b"],
        type: "vhost",
      },
      t: "TLSOffloader-D0YJ9H",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 598.954775030094,
      y: 299.42050831987945,
    },
    {
      type: "node",
      id: "vh-p",
      d: {
        dependencies: ["svr-e", "svr-a"],
        type: "vhost",
      },
      t: "APIGateway-ZLV81P",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -483.33551271787724,
      y: 727.2634905412433,
    },
    {
      type: "node",
      id: "vh-q",
      d: {
        dependencies: ["svr-b", "svr-g"],
        type: "vhost",
      },
      t: "APIGateway-RENQBD",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 711.7612193765278,
      y: -615.6283851999094,
    },
    {
      type: "node",
      id: "vh-r",
      d: {
        dependencies: ["svr-c", "svr-k"],
        type: "vhost",
      },
      t: "TLSOffloader-IJFM3V",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -418.59199887761315,
      y: -322.43416227594344,
    },
    {
      type: "node",
      id: "vh-s",
      d: {
        dependencies: ["svr-f", "svr-k"],
        logLevel: "error",
        logMessage: "Alert Status: Error",
        type: "vhost",
        generatedErrorMessage: "Misconfiguration in virtual host routing rules.",
      },
      t: "CDNNode-O33N1R",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -433.2746048846154,
      y: 449.22540251266355,
    },
    {
      type: "node",
      id: "vh-t",
      d: {
        dependencies: ["svr-g"],
        type: "vhost",
      },
      t: "FrontendProxy-EO7IMW",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 715.4919940670036,
      y: -497.48673204767636,
    },
    {
      type: "node",
      id: "vh-u",
      d: {
        dependencies: ["svr-f", "svr-e"],
        type: "vhost",
      },
      t: "LoadBalancer-CY2WM3",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -120.7097598196026,
      y: 869.8129908132705,
    },
    {
      type: "node",
      id: "vh-v",
      d: {
        dependencies: ["svr-h"],
        type: "vhost",
      },
      t: "APIGateway-UVX5GY",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 253.08581483837975,
      y: 932.3611430887349,
    },
    {
      type: "node",
      id: "vh-w",
      d: {
        dependencies: ["svr-i", "svr-c"],
        type: "vhost",
      },
      t: "CDNNode-JPZ6NW",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 172.59176932850028,
      y: -446.3717868218623,
    },
    {
      type: "node",
      id: "vh-x",
      d: {
        dependencies: ["svr-d"],
        type: "vhost",
      },
      t: "FrontendProxy-AB017J",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 866.7255064261483,
      y: 125.62287743253137,
    },
    {
      type: "node",
      id: "vh-y",
      d: {
        dependencies: ["svr-j", "svr-b"],
        type: "vhost",
      },
      t: "LoadBalancer-BHJTPJ",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -134.0386119265729,
      y: -334.81782231588454,
    },
    {
      type: "node",
      id: "vh-z",
      d: {
        dependencies: ["svr-k", "svr-e"],
        type: "vhost",
      },
      t: "StaticContentHost-MDQGF5",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -22.146432732307176,
      y: 356.2827540807566,
    },
    {
      type: "node",
      id: "vh-ab",
      d: {
        dependencies: ["svr-c", "svr-j"],
        type: "vhost",
      },
      t: "APIGateway-IGLNP8",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -366.86966806876944,
      y: -632.597437415036,
    },
    {
      type: "node",
      id: "vh-ac",
      d: {
        dependencies: ["svr-f", "svr-d"],
        type: "vhost",
      },
      t: "APIGateway-BMW8V1",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 497.45615327630117,
      y: 477.07178036589767,
    },
    {
      type: "node",
      id: "vh-ad",
      d: {
        dependencies: ["svr-j"],
        type: "vhost",
      },
      t: "RoutingProxy-L0YQWR",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -331.67648358484394,
      y: -993.546511363348,
    },
    {
      type: "node",
      id: "vh-ae",
      d: {
        dependencies: ["svr-h"],
        type: "vhost",
      },
      t: "LoadBalancer-W8JQI0",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 408.4329620141973,
      y: -32.558634660315874,
    },
    {
      type: "node",
      id: "vh-af",
      d: {
        dependencies: ["svr-c", "svr-i"],
        type: "vhost",
      },
      t: "RoutingProxy-2R8UNQ",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -13.54801279680828,
      y: 193.51596651403906,
    },
    {
      type: "node",
      id: "vh-ag",
      d: {
        dependencies: ["svr-f"],
        type: "vhost",
      },
      t: "TLSOffloader-DXPVXG",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -377.540120526667,
      y: 393.8451385050648,
    },
    {
      type: "node",
      id: "vh-ah",
      d: {
        dependencies: ["svr-i"],
        type: "vhost",
      },
      t: "StaticContentHost-0XCYDM",
      c: virtualHostColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 80.37723253243507,
      y: 144.6161844951846,
    },
    {
      type: "node",
      id: "srvc-a",
      d: {
        dependencies: ["vh-q"],
        type: "service",
      },
      t: "BillingService-Z45I33",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 971.9384483056399,
      y: -794.5240807603758,
    },
    {
      type: "node",
      id: "srvc-b",
      d: {
        dependencies: ["vh-j"],
        type: "service",
      },
      t: "BillingService-6U22YT",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -495.9006422666299,
      y: -75.63943248060468,
    },
    {
      type: "node",
      id: "srvc-c",
      d: {
        dependencies: ["vh-f", "vh-m"],
        type: "service",
      },
      t: "AuthService-2Y0531",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 15.26367339274043,
      y: -836.1262970547808,
    },
    {
      type: "node",
      id: "srvc-d",
      d: {
        dependencies: ["vh-c"],
        logLevel: "warning",
        logMessage: "Alert Status: Warning",
        type: "service",
        generatedErrorMessage: "Response time is above normal thresholds.",
      },
      t: "PaymentGateway-J9BKDD",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -906.3394860616543,
      y: -622.7914950262004,
    },
    {
      type: "node",
      id: "srvc-e",
      d: {
        dependencies: ["vh-af", "vh-v"],
        type: "service",
      },
      t: "AnalyticsEngine-6WWBI2",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 121.21463520126258,
      y: 616.3779348789308,
    },
    {
      type: "node",
      id: "srvc-f",
      d: {
        dependencies: ["vh-h", "vh-m"],
        type: "service",
      },
      t: "BillingService-LDQ6ES",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 499.17586208438547,
      y: -777.591408447119,
    },
    {
      type: "node",
      id: "srvc-g",
      d: {
        dependencies: ["vh-k", "vh-d"],
        type: "service",
      },
      t: "PaymentGateway-J4G2YJ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -840.3697037544814,
      y: -175.46787997423144,
    },
    {
      type: "node",
      id: "srvc-h",
      d: {
        dependencies: ["vh-d"],
        type: "service",
      },
      t: "OrderProcessing-IN6O8K",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -1110.18244736736,
      y: 245.40277961111883,
    },
    {
      type: "node",
      id: "srvc-i",
      d: {
        dependencies: ["vh-d", "vh-i"],
        type: "service",
      },
      t: "AuthService-DNPL7S",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -942.0471058197295,
      y: 250.81832932029738,
    },
    {
      type: "node",
      id: "srvc-j",
      d: {
        dependencies: ["vh-c", "vh-j"],
        type: "service",
      },
      t: "NotificationService-N18ZAO",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -480.4423577021529,
      y: -294.21334569212354,
    },
    {
      type: "node",
      id: "srvc-k",
      d: {
        dependencies: ["vh-v"],
        type: "service",
      },
      t: "OrderProcessing-SIN1JP",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 226.03985928848465,
      y: 1233.2985819024743,
    },
    {
      type: "node",
      id: "srvc-l",
      d: {
        dependencies: ["vh-ab"],
        logLevel: "warning",
        logMessage: "Alert Status: Warning",
        type: "service",
        generatedErrorMessage: "Service memory usage is high.",
      },
      t: "SessionManager-6KV1AQ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -451.53193997726,
      y: -908.2699104434819,
    },
    {
      type: "node",
      id: "srvc-m",
      d: {
        dependencies: ["vh-e"],
        type: "service",
      },
      t: "UserProfileService-7UIM46",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 1098.6238325404813,
      y: -145.03273794590268,
    },
    {
      type: "node",
      id: "srvc-n",
      d: {
        dependencies: ["vh-s", "vh-i"],
        type: "service",
      },
      t: "OrderProcessing-TUX2EJ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -711.2682301911314,
      y: 414.46081565647546,
    },
    {
      type: "node",
      id: "srvc-o",
      d: {
        dependencies: ["vh-o", "vh-af"],
        type: "service",
      },
      t: "BillingService-2G7WUJ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 330.2939839509663,
      y: 289.1089938086743,
    },
    {
      type: "node",
      id: "srvc-p",
      d: {
        dependencies: ["vh-c"],
        type: "service",
      },
      t: "ReportGenerator-QF6G7V",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -834.6993613106752,
      y: -757.2632838524146,
    },
    {
      type: "node",
      id: "srvc-q",
      d: {
        dependencies: ["vh-u"],
        type: "service",
      },
      t: "AuthService-JBEWBQ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -232.40909975438603,
      y: 1141.8484735135776,
    },
    {
      type: "node",
      id: "srvc-r",
      d: {
        dependencies: ["vh-l"],
        logLevel: "error",
        logMessage: "Alert Status: Error",
        type: "service",
        generatedErrorMessage: "Service failed to connect to upstream dependency.",
      },
      t: "UserProfileService-TNSF04",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 278.9974865847537,
      y: 1141.3073641857036,
    },
    {
      type: "node",
      id: "srvc-s",
      d: {
        dependencies: ["vh-v"],
        type: "service",
      },
      t: "OrderProcessing-KT952G",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 305.76119896422006,
      y: 1239.7041329403164,
    },
    {
      type: "node",
      id: "srvc-t",
      d: {
        dependencies: ["vh-d"],
        type: "service",
      },
      t: "InventoryService-GJYJP0",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -1126.703078520317,
      y: 164.67132233430675,
    },
    {
      type: "node",
      id: "srvc-u",
      d: {
        dependencies: ["vh-l"],
        type: "service",
      },
      t: "SearchService-H6CPU1",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 360.18937551874,
      y: 1135.6384572143106,
    },
    {
      type: "node",
      id: "srvc-v",
      d: {
        dependencies: ["vh-n"],
        type: "service",
      },
      t: "NotificationService-DJB1XT",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 390.88829647486205,
      y: 1007.7890880559562,
    },
    {
      type: "node",
      id: "srvc-w",
      d: {
        dependencies: ["vh-a", "vh-c"],
        type: "service",
      },
      t: "ReportGenerator-7WXY3E",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -338.0090941657402,
      y: -207.33809260208614,
    },
    {
      type: "node",
      id: "srvc-x",
      d: {
        dependencies: ["vh-o"],
        type: "service",
      },
      t: "NotificationService-PBWZK4",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 906.800179856971,
      y: 373.1906018579075,
    },
    {
      type: "node",
      id: "srvc-y",
      d: {
        dependencies: ["vh-s"],
        type: "service",
      },
      t: "SearchService-OD939D",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -661.8771641177814,
      y: 684.6465717922347,
    },
    {
      type: "node",
      id: "srvc-z",
      d: {
        dependencies: ["vh-m", "vh-ae", "vh-h"],
        type: "service",
      },
      t: "NotificationService-4J5RO3",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 389.81547304459446,
      y: -472.41272254604087,
    },
    {
      type: "node",
      id: "srvc-aa",
      d: {
        dependencies: ["vh-j", "vh-c"],
        type: "service",
      },
      t: "BillingService-E2VZZJ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -535.4022386887195,
      y: -254.0505689165218,
    },
    {
      type: "node",
      id: "srvc-ab",
      d: {
        dependencies: ["vh-e"],
        type: "service",
      },
      t: "OrderProcessing-OWVTDD",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 1096.7025277704831,
      y: -219.95486259177187,
    },
    {
      type: "node",
      id: "srvc-ac",
      d: {
        dependencies: ["vh-h", "vh-b", "vh-j"],
        type: "service",
      },
      t: "PaymentGateway-UFSNNP",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 285.276051710096,
      y: -293.08276466215057,
    },
    {
      type: "node",
      id: "srvc-ad",
      d: {
        dependencies: ["vh-d"],
        type: "service",
      },
      t: "OrderProcessing-PT931S",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -1119.2023490262393,
      y: 83.80865937220187,
    },
    {
      type: "node",
      id: "srvc-ae",
      d: {
        dependencies: ["vh-ae"],
        type: "service",
      },
      t: "PaymentGateway-ZM3HTG",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 715.8920000821124,
      y: -8.875066890630706,
    },
    {
      type: "node",
      id: "srvc-af",
      d: {
        dependencies: ["vh-a"],
        logLevel: "error",
        logMessage: "Alert Status: Error",
        type: "service",
        generatedErrorMessage: "Critical dependency not responding.",
      },
      t: "AuthService-G2YPL5",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 214.3790230364557,
      y: 232.24702416946457,
    },
    {
      type: "node",
      id: "srvc-ag",
      d: {
        dependencies: ["vh-af"],
        type: "service",
      },
      t: "OrderProcessing-SV2QMV",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -185.5953009460968,
      y: 429.72983871467795,
    },
    {
      type: "node",
      id: "srvc-ah",
      d: {
        dependencies: ["vh-r", "vh-ag"],
        type: "service",
      },
      t: "InventoryService-YW05QC",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -512.5135224906047,
      y: 46.27442392033777,
    },
    {
      type: "node",
      id: "srvc-ai",
      d: {
        dependencies: ["vh-w"],
        type: "service",
      },
      t: "AuthService-202471",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 193.82453278729986,
      y: -725.8233284168202,
    },
    {
      type: "node",
      id: "srvc-aj",
      d: {
        dependencies: ["vh-h", "vh-b"],
        type: "service",
      },
      t: "BillingService-77BM1Q",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 847.9679142892899,
      y: -479.1158533418559,
    },
    {
      type: "node",
      id: "srvc-ak",
      d: {
        dependencies: ["vh-l"],
        type: "service",
      },
      t: "InventoryService-MY5VHA",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 426.20321012297995,
      y: 1096.5567965836321,
    },
    {
      type: "node",
      id: "srvc-al",
      d: {
        dependencies: ["vh-w", "vh-h"],
        type: "service",
      },
      t: "InventoryService-0J7JGO",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 433.73056962665464,
      y: -642.6822131640802,
    },
    {
      type: "node",
      id: "srvc-am",
      d: {
        dependencies: ["vh-r", "vh-c"],
        type: "service",
      },
      t: "AuthService-8JDEPQ",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -677.5093408204032,
      y: -624.5223375924644,
    },
    {
      type: "node",
      id: "srvc-an",
      d: {
        dependencies: ["vh-y", "vh-d", "vh-k"],
        type: "service",
      },
      t: "AnalyticsEngine-0WAUHN",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -569.048617969811,
      y: -159.6726833398361,
    },
    {
      type: "node",
      id: "srvc-ao",
      d: {
        dependencies: ["vh-i", "vh-p"],
        type: "service",
      },
      t: "InventoryService-KCVT64",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -688.200603656818,
      y: 510.9760280000405,
    },
    {
      type: "node",
      id: "srvc-ap",
      d: {
        dependencies: ["vh-s", "vh-d"],
        type: "service",
      },
      t: "BillingService-UTQGDL",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -792.8560712560395,
      y: 423.8055750286087,
    },
    {
      type: "node",
      id: "srvc-aq",
      d: {
        dependencies: ["vh-l", "vh-ac"],
        type: "service",
      },
      t: "AnalyticsEngine-GWMLY5",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 513.7919175115896,
      y: 803.2206764605007,
    },
    {
      type: "node",
      id: "srvc-ar",
      d: {
        dependencies: ["vh-r"],
        type: "service",
      },
      t: "OrderProcessing-NL6FWA",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -540.9314268124645,
      y: -616.4703549245896,
    },
    {
      type: "node",
      id: "srvc-as",
      d: {
        dependencies: ["vh-t", "vh-ae"],
        type: "service",
      },
      t: "InventoryService-3HAXRN",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 681.0549018783456,
      y: -229.95895471974814,
    },
    {
      type: "node",
      id: "srvc-at",
      d: {
        dependencies: ["vh-af"],
        type: "service",
      },
      t: "NotificationService-GTOITG",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -225.66374781425725,
      y: 369.1787839037279,
    },
    {
      type: "node",
      id: "srvc-au",
      d: {
        dependencies: ["vh-ae", "vh-y"],
        type: "service",
      },
      t: "NotificationService-NHIJRP",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 170.70023319760753,
      y: -251.75640152330175,
    },
    {
      type: "node",
      id: "srvc-av",
      d: {
        dependencies: ["vh-s", "vh-ah"],
        type: "service",
      },
      t: "OrderProcessing-1D3Q3Z",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -139.2395078541481,
      y: 284.79193686192775,
    },
    {
      type: "node",
      id: "srvc-aw",
      d: {
        dependencies: ["vh-k", "vh-af"],
        type: "service",
      },
      t: "NotificationService-35T4CE",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -323.46027624397607,
      y: -74.02053613329554,
    },
    {
      type: "node",
      id: "srvc-ax",
      d: {
        dependencies: ["vh-g", "vh-j"],
        type: "service",
      },
      t: "SessionManager-RGDD2Z",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -54.20858815302108,
      y: -395.57053996224886,
    },
    {
      type: "node",
      id: "srvc-ay",
      d: {
        dependencies: ["vh-af", "vh-z"],
        type: "service",
      },
      t: "InventoryService-0KVPAC",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -146.39802400509097,
      y: 488.7774410487609,
    },
    {
      type: "node",
      id: "srvc-az",
      d: {
        dependencies: ["vh-ad"],
        type: "service",
      },
      t: "NotificationService-35C10Z",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -426.00208766820833,
      y: -1239.7041329403164,
    },
    {
      type: "node",
      id: "srvc-ba",
      d: {
        dependencies: ["vh-m"],
        type: "service",
      },
      t: "SessionManager-I02T8I",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 240.7999771217942,
      y: -1113.0503636708531,
    },
    {
      type: "node",
      id: "srvc-bb",
      d: {
        dependencies: ["vh-o", "vh-n"],
        type: "service",
      },
      t: "AnalyticsEngine-LCI9DD",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 572.3237178650763,
      y: 628.820771964919,
    },
    {
      type: "node",
      id: "srvc-bc",
      d: {
        dependencies: ["vh-o", "vh-ac"],
        type: "service",
      },
      t: "AuthService-EI7ECH",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 768.3332636368239,
      y: 518.3882050571283,
    },
    {
      type: "node",
      id: "srvc-bd",
      d: {
        dependencies: ["vh-ac"],
        type: "service",
      },
      t: "AnalyticsEngine-B8PQN5",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 736.2363895622941,
      y: 689.7674905982176,
    },
    {
      type: "node",
      id: "srvc-be",
      d: {
        dependencies: ["vh-u"],
        type: "service",
      },
      t: "ReportGenerator-01RLQB",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -161.27584613839008,
      y: 1161.2320237628091,
    },
    {
      type: "node",
      id: "srvc-bf",
      d: {
        dependencies: ["vh-c"],
        type: "service",
      },
      t: "UserProfileService-BBDTIW",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -770.3722940369198,
      y: -807.4215577100053,
    },
    {
      type: "node",
      id: "srvc-bg",
      d: {
        dependencies: ["vh-q"],
        type: "service",
      },
      t: "AuthService-XSE1LW",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 860.1024681526562,
      y: -891.3583799578204,
    },
    {
      type: "node",
      id: "srvc-bh",
      d: {
        dependencies: ["vh-ag"],
        type: "service",
      },
      t: "OrderProcessing-1MUL7Y",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -552.8071442072173,
      y: 637.3883755724162,
    },
    {
      type: "node",
      id: "srvc-bi",
      d: {
        dependencies: ["vh-q"],
        type: "service",
      },
      t: "AnalyticsEngine-VP9EJY",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 922.3216248508122,
      y: -850.6342837082309,
    },
    {
      type: "node",
      id: "srvc-bj",
      d: {
        dependencies: ["vh-o"],
        type: "service",
      },
      t: "AuthService-LTRIWX",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 883.7153244601834,
      y: 477.0651620520721,
    },
    {
      type: "node",
      id: "srvc-bk",
      d: {
        dependencies: ["vh-g"],
        type: "service",
      },
      t: "AuthService-0BFECG",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 286.6473863690692,
      y: -847.409101065265,
    },
    {
      type: "node",
      id: "srvc-bl",
      d: {
        dependencies: ["vh-ag", "vh-j"],
        logLevel: "error",
        logMessage: "Alert Status: Error",
        type: "service",
        generatedErrorMessage: "Service crashed due to unhandled exception.",
      },
      t: "OrderProcessing-JTAG13",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -429.7854616657788,
      y: 162.44506024604902,
    },
    {
      type: "node",
      id: "srvc-bm",
      d: {
        dependencies: ["vh-x"],
        type: "service",
      },
      t: "AnalyticsEngine-RL8D8C",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 1126.7030785203167,
      y: 185.15519507767226,
    },
    {
      type: "node",
      id: "srvc-bn",
      d: {
        dependencies: ["vh-b"],
        type: "service",
      },
      t: "BillingService-LHM1R7",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 915.2091062815132,
      y: -344.85074923443676,
    },
    {
      type: "node",
      id: "srvc-bo",
      d: {
        dependencies: ["vh-c"],
        type: "service",
      },
      t: "SessionManager-0KTL8B",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -878.7742629952211,
      y: -696.5295375715677,
    },
    {
      type: "node",
      id: "srvc-bp",
      d: {
        dependencies: ["vh-r", "vh-ae", "vh-y"],
        type: "service",
      },
      t: "SearchService-UW7NXS",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -0.4957524286542139,
      y: -211.08278305315253,
    },
    {
      type: "node",
      id: "srvc-bq",
      d: {
        dependencies: ["vh-h"],
        type: "service",
      },
      t: "SessionManager-KGNL9N",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 870.1498061649902,
      y: -617.174203412597,
    },
    {
      type: "node",
      id: "srvc-br",
      d: {
        dependencies: ["vh-o", "vh-z"],
        type: "service",
      },
      t: "UserProfileService-E7GY6W",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 327.44615030527325,
      y: 416.0868942090965,
    },
    {
      type: "node",
      id: "srvc-bs",
      d: {
        dependencies: ["vh-r"],
        type: "service",
      },
      t: "SessionManager-GHS3CE",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -617.7790406454062,
      y: -579.9235055813624,
    },
    {
      type: "node",
      id: "srvc-bt",
      d: {
        dependencies: ["vh-p"],
        type: "service",
      },
      t: "AuthService-RLWNTA",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -686.7632345368954,
      y: 956.7320702826023,
    },
    {
      type: "node",
      id: "srvc-bu",
      d: {
        dependencies: ["vh-ac", "vh-ae"],
        type: "service",
      },
      t: "BillingService-KZDON5",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 631.6593265599834,
      y: 218.0390108647332,
    },
    {
      type: "node",
      id: "srvc-bv",
      d: {
        dependencies: ["vh-p"],
        type: "service",
      },
      t: "SearchService-HF8F9U",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: -619.1682763252779,
      y: 999.8050138336575,
    },
    {
      type: "node",
      id: "srvc-bw",
      d: {
        dependencies: ["vh-q", "vh-e"],
        type: "service",
      },
      t: "EmailService-SPO6HU",
      c: serviceColour,
      fbc: "#2d383f",
      fc: "#FFFFFF",
      x: 958.086663027347,
      y: -444.8178208108767,
    },
  ],
};

function createAnnotation(message, severity, subject) {
  const colour = severity === "warning" ? warningColourLight : errorColourLight;
  const glyphColour = severity === "warning" ? warningColour : errorColour;
  const annotation = {
    type: "annotation",
    id: "annotation-" + subject,
    subject,
    w: 175,
    h: 175 / 5,
    c: colour,
    bw: 2,
    connectorStyle: {
      c: colour,
      subjectEnd: "dot",
      ls: "dashed",
      w: 2,
    },
    b: colour,
    borderRadius: 4,
    bw: 4,
    t: [
      {
        t: message,
        fs: 12,
        position: { vertical: "middle", horizontal: "left" },
        padding: 5,
        fb: true,
        margin: {
          left: 11,
          right: 5,
          top: 1,
        },
        fc: bgColour,
      },
    ],
    g: [
      {
        c: glyphColour,
        fi: {
          t: fontIcons.exclamationTriangle,
          c: bgColour,
        },
        e: 1.7,
        p: 270,
        r: 90,
        border: {
          colour: bgColour,
          width: 1.5,
        },
      },
      {
        c: "white",
        fi: {
          t: fontIcons.eyeSlash,
          c: bgColour,
        },
        e: 1.3,
        p: 90,
        r: 90,
        border: {
          colour: bgColour,
          width: 1.5,
        },
      },
    ],
  };
  return annotation;
}

// Map where the key is the subjectId
export const annotationsState = {};
let errorShown = false;
let warningShown = false;
data.items.forEach((item) => {
  if (item.d && item.d.generatedErrorMessage) {
    const annotation = createAnnotation(item.d.generatedErrorMessage, item.d.logLevel, item.id);
    let hidden = true;
    if (item.d.logLevel === "warning" && !warningShown) {
      hidden = false;
      warningShown = true;
    } else if (item.d.logLevel === "error" && !errorShown) {
      hidden = false;
      errorShown = true;
    }

    annotationsState[item.id] = {
      hidden,
      annotation,
    };
  }
});
<!doctype html>
<html lang="en" style="background-color: #2d383f">
  <head>
    <meta charset="utf-8" />
    <title>Impact Analysis</title>
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div id="klchart" class="klchart"></div>
    <script type="module" src="./code.js"></script>
  </body>
</html>
#nodeDependantWarning {
  background-color: #fcf8e3;
  padding-left: 4px;
  border-style: solid;
  border-width: 1px;
  border-radius: 2px;
}

.radio {
  padding-left: 25px;
}

table {
  border: 1px solid #969696;
  border-collapse: collapse;
  font-size: 14px;
  width: 100%;
  height: 30vh;
}

table thead:hover {
  background-color: #969696;
}

table thead tr {
  display: block;
  width: 100%;
  background-color: #969696;
}

table thead th {
  color: #212121;
  background-color: #969696;
  position: sticky;
  top: 0;
  text-align: left;
}

table tbody {
  display: block;
  overflow-y: scroll;
  height: 100%;
  background-color: white;
}

table tbody::-webkit-scrollbar {
  width: 8px;
}

table tbody::-webkit-scrollbar-thumb {
  background: #969696;
  border-radius: 5px;
}

table tbody tr {
  border-radius: 30px;
  cursor: pointer;
  display: table-row;
  transition: all 0.3s ease;
}

.selected-row,
#alerts .selected-row:hover {
  background-color: #212121;
  color: white;
}

table tr *:nth-child(1) {
  width: 130px;
}

table tr *:nth-child(2) {
  text-align: center;
  width: 100px;
}

table tr *:nth-child(3) {
  width: 170px;
}

table th,
table td {
  padding: 0.5em;
}

#reset {
  text-align: center;
  margin: 12px 0px;
  border-style: solid;
  border-width: 1px;
}

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.