@deliciousmonster/datadog-agent-binary 7.82.1-next.3 → 7.82.1-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deliciousmonster/datadog-agent-binary",
3
- "version": "7.82.1-next.3",
3
+ "version": "7.82.1-next.6",
4
4
  "description": "Harper component that runs the Datadog trace-agent and core-agent alongside a node, with pre-built binaries installed per platform",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -38,7 +38,7 @@
38
38
  "author": "",
39
39
  "license": "Apache-2.0",
40
40
  "dependencies": {
41
- "@deliciousmonster/harper-process-guard": "0.1.0-next.2"
41
+ "@deliciousmonster/harper-process-guard": "0.1.0-next.3"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^26.0.0",
@@ -68,10 +68,10 @@
68
68
  },
69
69
  "homepage": "https://github.com/deliciousmonster/datadog-agent-binary#readme",
70
70
  "optionalDependencies": {
71
- "@deliciousmonster/datadog-agent-binary-linux-x86_64": "7.82.1-next.3",
72
- "@deliciousmonster/datadog-agent-binary-linux-arm64": "7.82.1-next.3",
73
- "@deliciousmonster/datadog-agent-binary-macos-arm64": "7.82.1-next.3",
74
- "@deliciousmonster/datadog-agent-binary-windows-x86_64": "7.82.1-next.3"
71
+ "@deliciousmonster/datadog-agent-binary-linux-x86_64": "7.82.1-next.6",
72
+ "@deliciousmonster/datadog-agent-binary-linux-arm64": "7.82.1-next.6",
73
+ "@deliciousmonster/datadog-agent-binary-macos-arm64": "7.82.1-next.6",
74
+ "@deliciousmonster/datadog-agent-binary-windows-x86_64": "7.82.1-next.6"
75
75
  },
76
76
  "lint-staged": {
77
77
  "*.{ts,js,json}": [
package/runtime/config.js CHANGED
@@ -78,6 +78,12 @@ function renderDatadogYaml(paths, ports) {
78
78
  "# Pinned because the core-agent verify reads expvar off this port. Measured on 7.82.1: the environment",
79
79
  "# outranks this file, so a set DD_EXPVAR_PORT wins and this only pins the port against a default that moves.",
80
80
  `expvar_port: ${ports.expvar}`,
81
+ "# Live Processes: every process on the node with its CPU, memory and command line, Harper and the agents",
82
+ "# included. Go, so it runs in this Python-free build; DD_PROCESS_CONFIG_PROCESS_COLLECTION_ENABLED=false",
83
+ "# turns it off, since the environment outranks this file.",
84
+ "process_config:",
85
+ " process_collection:",
86
+ " enabled: true",
81
87
  "apm_config:",
82
88
  " enabled: true",
83
89
  ` receiver_port: ${ports.receiver}`,
@@ -94,16 +100,27 @@ function renderDatadogYaml(paths, ports) {
94
100
 
95
101
  const HARPER_LOG_CHECK = "harper.d";
96
102
 
97
- /** A logs source for Harper's own log file: `logging.root` is `log` under the root path unless a node moved it. */
98
- function renderHarperLogSource(logFile) {
103
+ /**
104
+ * Log sources for what runs on this node: every log Harper writes under its log directory (`logging.root`
105
+ * is `log` under the root path unless a node moved it; the HTTP request log `http.logging` enables lands
106
+ * there too, under its own name), and the two agents' and the reaper's, which are the first thing an
107
+ * operator wants when the node stops reporting. Tailed only while logs are enabled (DD_LOGS_ENABLED=true).
108
+ */
109
+ function renderLogSources(harperLog, paths) {
110
+ const source = (path, service, source) => [
111
+ " - type: file",
112
+ ` path: ${yamlString(path)}`,
113
+ ` service: ${service}`,
114
+ ` source: ${source}`,
115
+ ];
99
116
  return [
100
117
  "# GENERATED by resources.js on every Harper worker start. Edits are overwritten.",
101
118
  "# Tailed only while logs are enabled (DD_LOGS_ENABLED=true).",
102
119
  "logs:",
103
- " - type: file",
104
- ` path: ${yamlString(logFile)}`,
105
- " service: harper",
106
- " source: harper",
120
+ ...source(join(dirname(harperLog), "*.log"), "harper", "harper"),
121
+ ...source(paths.coreLog, "datadog-agent", "datadog-agent"),
122
+ ...source(paths.traceLog, "datadog-trace-agent", "datadog-agent"),
123
+ ...source(paths.reaperLog, "datadog-agent-reaper", "harper-process-guard"),
107
124
  "",
108
125
  ].join("\n");
109
126
  }
@@ -179,11 +196,12 @@ export function prepareRuntime(componentDir, { ports, log }) {
179
196
  check.body;
180
197
  }
181
198
  const owned = new Set(checks.map((check) => check.dir));
182
- // Harper's own log as a log source, written whenever the root is known. The agent tails it only
183
- // when logs are on, which is DD_LOGS_ENABLED=true in the environment; off, this file costs nothing.
199
+ // Harper's own log and the agents' as log sources, written whenever the root is known. The agent
200
+ // tails them only when logs are on, which is DD_LOGS_ENABLED=true in the environment; off, this
201
+ // file costs nothing.
184
202
  if (root) {
185
203
  configFiles[join(paths.confd, HARPER_LOG_CHECK, "conf.yaml.default")] =
186
- renderHarperLogSource(join(root, "log", "hdb.log"));
204
+ renderLogSources(join(root, "log", "hdb.log"), paths);
187
205
  owned.add(HARPER_LOG_CHECK);
188
206
  }
189
207
  removeStaleDefaults(paths.confd, owned);
@@ -1,11 +1,17 @@
1
1
  // Who holds the agents up. Released Harper has no sidecar API, so the bundled guard is the other half; one
2
2
  // agent per node comes from a PID lock either way and only the holder changes.
3
3
 
4
+ import { readFileSync, unlinkSync } from "node:fs";
4
5
  import { join } from "node:path";
5
6
 
6
7
  // Pinned to one exact version, never a range: Harper runs `npm install` when it installs a component, so a
7
8
  // caret here would let a customer's node resolve a guard no test in this repo has run against.
8
- import { fingerprint, guard } from "@deliciousmonster/harper-process-guard";
9
+ import {
10
+ argvOf,
11
+ fingerprint,
12
+ guard,
13
+ identify as identifyPid,
14
+ } from "@deliciousmonster/harper-process-guard";
9
15
  import { describeSpawnFailure } from "./agent-exit.js";
10
16
  import { writeConfigFiles } from "./config.js";
11
17
 
@@ -99,12 +105,66 @@ const harperSupervisor = (scope, log) => ({
99
105
  // directory would collide on; this one names the package rather than taking the guard's generic default.
100
106
  const REAPER_NAME = "datadog-agent-reaper";
101
107
 
108
+ /**
109
+ * Harper's own spawn keeps a pid file per process name under <root>/pids and, when the file names a pid
110
+ * that answers kill(pid, 0), returns that pid instead of spawning. After a restart the kernel reissues
111
+ * pids, and a thread of Harper itself answers for one, so the file has to go before the guard asks.
112
+ * Removing it signals nothing. A file naming the real process, or a dead one, is Harper's to keep.
113
+ *
114
+ * @param {string | null} root @param {Array<{ name: string; argv?: readonly string[]; script?: string }>} named
115
+ * @param {import("./log.js").Log} log
116
+ */
117
+ export function clearStaleHarperPidFiles(root, named, log) {
118
+ if (!root) return;
119
+ for (const { name, argv, script } of named) {
120
+ const file = join(root, "pids", `${name}.pid`);
121
+ let pid;
122
+ try {
123
+ pid = Number.parseInt(readFileSync(file, "utf-8"), 10);
124
+ } catch {
125
+ continue;
126
+ }
127
+ if (!Number.isInteger(pid) || pid <= 0) continue;
128
+ const running = argvOf(pid);
129
+ if (running === null) continue;
130
+ const ours = argv
131
+ ? identifyPid(pid, argv) === "match"
132
+ : running.some((argument) => argument.endsWith(script ?? "\u0000"));
133
+ if (ours) continue;
134
+ try {
135
+ unlinkSync(file);
136
+ log.warn(
137
+ `Datadog supervisor: removed ${file}, Harper's own pid file for ${name}: it named pid ${pid}, which ` +
138
+ `is running \`${running.join(" ")}\`, and Harper would have handed that pid back as the ${name} ` +
139
+ `instead of starting one.`
140
+ );
141
+ } catch (error) {
142
+ log.error(
143
+ `Datadog supervisor: could not remove ${file}, which names pid ${pid} running something else: ` +
144
+ `${error.message}. Harper will hand that pid back as the ${name} rather than start one.`
145
+ );
146
+ }
147
+ }
148
+ }
149
+
102
150
  /** The bundled guard, one call for both agents. `spawn` is the entry module's own, which is the one Harper constrains. */
103
151
  const guardSupervisor = (log, spawn) => ({
104
152
  kind: "guard",
105
153
  async start(agents, { runtime, configFiles, fingerprintParts }) {
106
154
  // Harper's start() writes these itself; on this path nothing else will, and both agents read them.
107
155
  writeConfigFiles(configFiles, log);
156
+ clearStaleHarperPidFiles(
157
+ runtime.root,
158
+ [
159
+ ...agents.map((agent) => ({
160
+ name: agent.name,
161
+ argv: [agent.command, ...agent.args],
162
+ })),
163
+ // The guard builds the reaper's own argv; its script name is the one stable thing to match on.
164
+ { name: REAPER_NAME, script: "/reaper.js" },
165
+ ],
166
+ log
167
+ );
108
168
  let result;
109
169
  try {
110
170
  result = await guard({