Rich_Morin

Rich_Morin

Storing system information in a graph database?

tl; dr - I’d like to populate Neo4j with system information

Overview

I’d like to make both static and dynamic system information available as a labeled property graph, using a graph database such as Neo4j. This would start with sets of source code (e.g., applications), building graphs of atoms, functions, modules, etc. It would then fold in dynamic system information, tracking messages, nodes, processes, VM activity, etc. And a pony…

The basic idea is that anything and everything should be up for grabs, from atoms through functions to modules, nodes, processes, and more. If it looks plausibly useful, track and record it for later exploration. (It’s all good…)

Use Cases

Once the data is harvested and saved, various clients could access and process the result. For example, front ends could present both summarized and specific system information, providing dynamic and historical context. As in:

  • Which processes have recently used this function?
  • Which nodes are currently running this app, module, etc?
  • What’s the status and recent history of this process?

I’m not at all sure about how this data might be employed, but it seems likely to be useful. FWIW, I plan to start by using Cypher and assorted Neo4j Tools for initial exploration and tuning. After that, setting up some Livebooks and a Liveview web interface might be worth considering. Finally, if the database proves useful, one or more presentation front ends might opt to take advantage of it.

Status, etc.

At this point, I’m casting about for convenient (and preferably, low impact) ways to harvest app and system information. Fortunately, some broad-spectrum data collection facilities already exist, including ElixirLS and recon (other suggestions welcome!).

In this context, I’d like to know what other options exist for getting useful system snapshots. Could anyone point me to relevant APIs, data structures, etc? Basically, I’d like to know what data is readily available and what things seem most likely to be useful. As usual, I welcome advice, comments, reactions, etc.

-r

Most Liked

Rich_Morin

Rich_Morin

tl;dr - some possibly useful background information

It occurs to me that some readers may not be familiar with Labeled Property Graphs in general or Neo4j in particular. More to the point, it may not be obvious why these could be a good fit for storing and accessing system information. So, here’s a (somewhat high level and opinionated) rundown…

A labeled-property graph model is represented by a set of nodes, relationships, properties, and labels. Both nodes of data and their relationships are named and can store properties represented by key–value pairs. Nodes can be labelled to be grouped. The edges representing the relationships have two qualities: they always have a start node and an end node, and are directed; making the graph a directed graph. Relationships can also have properties. This is useful in providing additional metadata and semantics to relationships of the nodes. Direct storage of relationships allows a constant-time traversal.

Graph_database, in Wikipedia

Careful Reader will notice that this overloads the term node. That is, a Neo4j node can describe an Erlang node, but it could just as easily describe a function, module, process, etc. To reduce confusion, I’ll use the term “entity” below for the Neo4j meaning. However, note that this is not the only linguistic clash between Neo4j and Erlang: other issues include name syntax, etc. So, YMMV…

Stored Information

We’d like to store several kinds of information:

  • generic entity definitions (e.g., what is a function?)
  • possible relationships (e.g., modules can define functions)
  • specific entities (e.g., module Foo, function Foo.bar/1)
  • specific relationships (e.g., Foo.bar/2 calls Foo.bar/1)

Some of this information is generic; other information is specific to a given code base and/or set of running processes. So, we should gather each type of information when it either becomes available or changes.

Access, Data Structures, and Performance

The Cypher query language isn’t the only way to access Neo4j, but it’s definitely the Golden Path. Cypher syntax looks a bit like a cross between SQL and DOT (graph description) notation, with a bit of pattern matching thrown in. So, a typical query might look something like this:

MATCH (nicole:Actor {name: 'Nicole Kidman'})-[:ACTED_IN]->(movie:Movie)
WHERE movie.year < $yearParameter
RETURN movie

Neo4j has indexes that make it reasonably fast at finding specified entities and relationships, but the real speedup comes when we start traversing chains of relationships. Neo4j keeps connectivity information in memory, so following a relationship only requires dereferencing a pointer. So, it’s real fast at finding related entities, even when multiple relationships are involved.

This means that answering a multi-step “join” like “list all processes running on node name@host that have recently called function Foo.bar/1 via Foo.bar/2” can be expected to happen quite quickly. So, asking a Livebook to generate and display a Mermaid diagram of this sort of information isn’t a crazy idea.

A Possible Use Case

Serendipity for the win… I just stumbled on a possible use case, described by Peer Stritzinger at Code BEAM V EU 21: Jumping gen_servers! A new way of building (…) applications.

In this talk, Peer describes a robotic assembly line which uses a mesh of Erlang nodes to control all of the stages and types of actions involved. In order to migrate processes to the most relevant nodes, he needs a source of information on the entire system.

Because he doesn’t want a single point of failure, a single Neo4j database would not suffice. However, multiple database clones might work just fine. And, even if he wants to keep critical information “in the mesh”, he could use the Neo4j database(s) as a convenient data source.

HTH, Rich

peerst

peerst

GRiSP Core Team

Thanks for the citation notification Rich.

For our use case we need a more lightweight solution than a replicated neo4j instance. We have two graphs to manage: one is the application data flow graph which can be coming from the user in an IDE we are building. The other is the network & node property graph. The former is relatively static and could be a use case for neo4j, however we need to have it (at least partially) replicated on all nodes to allow decentralised decision making.

The network and node property graph can be much more dynamic and we need fast updates to it to be able to move computation around new obstacles quickly. For that a classical Link State Protocol (LSP) is implemented between Erlang Nodes (very simplified, each nodes floods the net with its info plus the surrounding topology on each local change). Here again we need a dataset on all nodes to be able to implement the LSP even but also again for local decision making. Classically the Link State Packets are stored as is and graph algorithms are directly implemented on this dataset. Alternatively one can also with little extra effort store them in a digraph — OTP 29.0.2 (stdlib 8.0.1) which is a data structure added to OTP for exactly such use cases.

digraph — OTP 29.0.2 (stdlib 8.0.1) can store sizeable datasets since its underlying storage is a ETS table. It has a nice set of graph algorithms pre-implemented and its not hard to add others du to its efficient underlying data-structure. Its a very useful and often neglected part of OTP

Where Next?

Popular in Discussions Top

crispinb
On reading dhh’s latest The One Person Framework it strikes me that Phoenix with LiveView is already pretty much this. However, never hav...
New
AstonJ
If a newbie asked you about Phoenix Contexts, how would you explain the basics to them? Feel free to be as concise or in-depth as you li...
New
lorenzo
Hey everone! I created a prototype for my app using Nodejs for the api. But the framework I chose wasnt great (in general theresnt any g...
New
AlexMcConnell
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
588 19652 166
New
ejpcmac
I have discovered Nix last month and I am currently on my way to migrating to it—both on macOS at home and the full NixOS distrubution at...
New
shishini
I think this twitter post and youtube video didn’t get as much attention as I hoped I am still new to Elixir, so can’t really judge ...
New
hazardfn
I suppose this question is effectively hackney vs. ibrowse but we are at a point in our project where we have to make a choice between th...
New
chulkilee
Here are the list of HTTP client libraries/wrappers, and some thoughts on HTTP client in general. I’d like to hear from others how they w...
New
acrolink
How does the two languages compare when it comes to server side application development? Any experiences or ideas? Thank you.
New
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127089 1222
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement