-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(data-point-tracers): add mermaid support (#420)
closes #419
- Loading branch information
Showing
5 changed files
with
223 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* eslint-disable */ | ||
|
||
const path = require("path"); | ||
|
||
const DataPoint = require("@data-point/core"); | ||
const DPModel = require("@data-point/core/model"); | ||
const DPIfThenElse = require("@data-point/core/ifThenElse"); | ||
const DPMap = require("@data-point/core/map"); | ||
|
||
const DPMermaidTracer = require("@data-point/tracers/mermaid"); | ||
|
||
const myModel = DPModel({ | ||
name: "myModel", | ||
|
||
uid: acc => `${acc.reducer.id}${acc.value.a.b}`, | ||
|
||
value: [ | ||
"$a.b", | ||
input => input.toUpperCase(), | ||
DPIfThenElse({ | ||
if: input => input === "FOO", | ||
then: () => { | ||
// return "yes foo!!"; | ||
throw new Error("ohh"); | ||
}, | ||
else: input => `foo no! got ${input}` | ||
}) | ||
], | ||
|
||
catch(acc) { | ||
return "its all ok"; | ||
} | ||
}); | ||
|
||
async function main() { | ||
const datapoint = DataPoint(); | ||
|
||
const input = [ | ||
{ | ||
a: { | ||
b: "foo" | ||
} | ||
}, | ||
{ | ||
a: { | ||
b: "bar" | ||
} | ||
}, | ||
{ | ||
a: { | ||
b: "baz" | ||
} | ||
} | ||
]; | ||
|
||
const tracer = DPMermaidTracer(); | ||
|
||
result = await datapoint.resolve(input, DPMap(myModel), { | ||
tracer | ||
}); | ||
|
||
// save to disk | ||
tracer.report(path.join(__dirname, "datapoint-trace-example.mermaid")); | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"name": "@data-point/mermaid-example", | ||
"main": "mermaid-example.js", | ||
"private": true, | ||
"version": "1.0.0", | ||
"devDependencies": { | ||
"@data-point/core": "^6.0.0", | ||
"@data-point/tracers": "^1.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require("./mermaid").Mermaid.create; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
const fs = require("fs").promises; | ||
|
||
function getParent(span) { | ||
return span.root ? "root" : span.parent; | ||
} | ||
|
||
function getName(span) { | ||
return span === "root" ? "root" : `${span.name}${span.context.pid}`; | ||
} | ||
|
||
function graphTD(spans) { | ||
const nodes = spans.map(span => { | ||
return ` ${getName(getParent(span))}-->${getName(span)}`; | ||
}); | ||
|
||
return `graph TD;\n${nodes.join("\n")}`; | ||
} | ||
|
||
class Mermaid { | ||
constructor() { | ||
this.spans = []; | ||
} | ||
|
||
static create() { | ||
return new Mermaid(); | ||
} | ||
|
||
start(dpSpan) { | ||
this.spans.push(dpSpan); | ||
} | ||
|
||
async report(destinationPath) { | ||
const report = graphTD(this.spans); | ||
|
||
if (destinationPath) { | ||
await fs.writeFile(destinationPath, report); | ||
} | ||
|
||
return report; | ||
} | ||
} | ||
|
||
module.exports = { | ||
getParent, | ||
getName, | ||
graphTD, | ||
Mermaid | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
const fs = require("fs").promises; | ||
const { getParent, getName, graphTD, Mermaid } = require("./mermaid"); | ||
|
||
function createChildSpan(name, pid, parent) { | ||
return { | ||
name, | ||
parent, | ||
context: { | ||
pid | ||
} | ||
}; | ||
} | ||
|
||
function createSampleSpans() { | ||
const aa = createChildSpan("aa", 1); | ||
aa.root = true; | ||
const bb = createChildSpan("bb", 2, aa); | ||
const cc = createChildSpan("cc", 3, aa); | ||
const dd = createChildSpan("dd", 4, bb); | ||
|
||
const spans = [aa, bb, cc, dd]; | ||
|
||
return spans; | ||
} | ||
|
||
const graphResult = `graph TD; | ||
root-->aa1 | ||
aa1-->bb2 | ||
aa1-->cc3 | ||
bb2-->dd4`; | ||
|
||
describe("getParent", () => { | ||
it("should return `root` if root flag is true", () => { | ||
expect(getParent({ root: true })).toEqual("root"); | ||
}); | ||
it("should return parent if root flag not true", () => { | ||
expect(getParent({ parent: "parent" })).toEqual("parent"); | ||
}); | ||
}); | ||
|
||
describe("getName", () => { | ||
it("should return 'root' if span is root", () => { | ||
expect(getName("root")).toEqual("root"); | ||
}); | ||
it("should return constructed name if span is not root", () => { | ||
const span = createChildSpan("name", 1); | ||
expect(getName(span)).toEqual("name1"); | ||
}); | ||
}); | ||
|
||
describe("graphTD", () => { | ||
it("should create graph tree", () => { | ||
const result = graphTD(createSampleSpans()); | ||
expect(result).toEqual(graphResult); | ||
}); | ||
}); | ||
|
||
describe("Mermaid", () => { | ||
describe("constructor", () => { | ||
it("should create spans array", () => { | ||
const result = new Mermaid(); | ||
expect(result).toHaveProperty("spans", []); | ||
}); | ||
}); | ||
|
||
describe("create", () => { | ||
it("should have static method to create new instance", () => { | ||
const result = Mermaid.create(); | ||
expect(result).toBeInstanceOf(Mermaid); | ||
}); | ||
}); | ||
|
||
describe("start", () => { | ||
it("should track spans", () => { | ||
const result = new Mermaid(); | ||
result.start("span"); | ||
expect(result.spans).toEqual(["span"]); | ||
}); | ||
}); | ||
|
||
describe("report", () => { | ||
it("should create and return mermaid graph", async () => { | ||
const result = new Mermaid(); | ||
result.spans = createSampleSpans(); | ||
expect(await result.report()).toEqual(graphResult); | ||
}); | ||
|
||
it("should save to file", async () => { | ||
const result = new Mermaid(); | ||
result.spans = createSampleSpans(); | ||
|
||
const spyWriteFile = jest.spyOn(fs, "writeFile").mockResolvedValue(true); | ||
|
||
await result.report("/test.mer"); | ||
expect(spyWriteFile).toBeCalledWith("/test.mer", graphResult); | ||
}); | ||
}); | ||
}); |