Skip to content

Commit 7a756ab

Browse files
committed
feat: translate collect metrics into tegde measurements
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
1 parent 802e7d0 commit 7a756ab

9 files changed

Lines changed: 610 additions & 1 deletion

File tree

.release-please-manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@
1414
"flows/tedge-events": "1.0.0",
1515
"flows/tedge-measurement-batch": "1.0.0",
1616
"flows/x509-cert-issuer": "1.0.0",
17-
"flows/tedge-compat": "0.1.0"
17+
"flows/tedge-compat": "0.1.0",
18+
"flows/collectd": "0.0.1"
1819
}

flows/collectd/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## collectd
2+
3+
This flows converts messages received from collectd into thin-edge measurements
4+
5+
### Description
6+
7+
Messages are received from collectd over the MQTT topics `collectd/$HOSTNAME/$GROUP/$MEASUREMENT`.
8+
9+
These messages are CSV encoded (using `':'` column separators) and contains a unix timestamp followed by the measurement value.

flows/collectd/flow.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[input]
2+
mqtt.topics = [
3+
"collectd/+/+/+"
4+
]
5+
6+
[[steps]]
7+
script = "lib/main.js"
8+
config.topic = "te/device/main///m/collectd"

flows/collectd/package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "collectd",
3+
"version": "0.0.1",
4+
"description": "Translate collectd metrics into thin-edge measurements",
5+
"source": "src/main.ts",
6+
"module": "lib/main.js",
7+
"type": "module",
8+
"tedge": {
9+
"mapper": "local"
10+
},
11+
"scripts": {
12+
"build": "esbuild src/main.ts --target=es2018 --bundle --outfile=lib/main.js --format=esm",
13+
"test": "jest --coverageProvider=v8 --coverage"
14+
},
15+
"author": "thin-edge.io",
16+
"license": "Apache-2.0",
17+
"devDependencies": {
18+
"@types/jest": "^30.0.0",
19+
"esbuild": "^0.25.5",
20+
"esbuild-register": "^3.6.0",
21+
"jest": "^30.0.4",
22+
"jest-esbuild": "^0.4.0",
23+
"prettier": "3.6.2",
24+
"typescript": "^5.8.3"
25+
}
26+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# enable debug messages
2+
debug = false

flows/collectd/src/main.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Message, Context, decodePayload } from "../../common/tedge";
2+
3+
export interface Config {
4+
topic?: string;
5+
}
6+
7+
export interface FlowContext extends Context {
8+
config: Config;
9+
}
10+
11+
export function onMessage(message: Message, context: FlowContext): Message[] {
12+
const output = [];
13+
const { topic = "te/device/main///m/collectd" } = context.config;
14+
15+
const groups = message.topic.split("/");
16+
const data = decodePayload(message.payload).split(":");
17+
18+
if (groups.length < 4) {
19+
throw new Error("Not a collectd topic");
20+
}
21+
if (data.length < 2) {
22+
throw new Error("Not a collectd payload");
23+
}
24+
25+
let group = groups[2];
26+
let measurement = groups[3];
27+
let time = data[0];
28+
let value = data[1];
29+
30+
output.push({
31+
topic,
32+
payload: `{"time": ${time}, "${group}": {"${measurement}": ${value}}}`,
33+
});
34+
35+
return output;
36+
}

flows/collectd/tests/main.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { expect, test, describe } from "@jest/globals";
2+
import * as tedge from "../../common/tedge";
3+
import * as flow from "../src/main";
4+
5+
describe("map collectd messages", () => {
6+
test("simple message", () => {
7+
const output = flow.onMessage(
8+
{
9+
time: new Date("2026-01-01"),
10+
topic: "collectd/localhost/temperature/temp1",
11+
payload: "1776866602.745439166:23.7",
12+
},
13+
tedge.createContext({}),
14+
);
15+
expect(output).toHaveLength(1);
16+
expect(output[0].topic).toBe("te/device/main///m/collectd");
17+
const payload = tedge.decodeJsonPayload(output[0].payload);
18+
expect(payload).toEqual({
19+
time: 1776866602.745439166,
20+
temperature: { temp1: 23.7 },
21+
});
22+
});
23+
});

0 commit comments

Comments
 (0)