Skip to content

Commit ea87039

Browse files
committed
Allow to configure logging per service with BALENA_LOGS_LEVEL env var
Services `core-next` and `service-relay` are configured by default with `BALENA_LOGS_LEVEL: error`. Change-type: patch
1 parent cedf0c6 commit ea87039

6 files changed

Lines changed: 47 additions & 4 deletions

File tree

docker-compose.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ services:
4343
# Needed for locks and balenahup. This needs to match the device
4444
# used for the `runtime` volume
4545
- BALENA_HOST_RUNTIME_DIR=/tmp/balena-supervisor
46+
# Only send error logs to dashboard
47+
- BALENA_LOGS_LEVEL=error
4648
volumes:
4749
# Critical configurations
4850
- config:/config/helios
@@ -67,6 +69,9 @@ services:
6769
- core
6870
volumes:
6971
- runtime:/tmp/run
72+
environment:
73+
# Only send error logs to dashboard
74+
- BALENA_LOGS_LEVEL=error
7075
healthcheck:
7176
test: ['CMD', 'wget', '-O', '-', '-q', 'http://127.0.0.1:48484/ping']
7277

src/compose/service-manager.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ export async function start(service: Service) {
372372
);
373373
}
374374

375-
logger.attach(container.id, { serviceId });
375+
logger.attach(container.id, { serviceId, logLevel: service.logLevel() });
376376

377377
if (!alreadyStarted) {
378378
logger.logSystemEvent(LogTypes.startServiceSuccess, { service });
@@ -433,8 +433,10 @@ export function listenToEvents() {
433433
`serviceId not defined for service: ${service.serviceName} in ServiceManager.listenToEvents`,
434434
);
435435
}
436+
436437
logger.attach(data.id, {
437438
serviceId,
439+
logLevel: service.logLevel(),
438440
});
439441
} else if (status === 'destroy') {
440442
logMonitor.detach(data.id);
@@ -489,8 +491,10 @@ export async function attachToRunning() {
489491
`containerId not defined for service: ${service.serviceName} in ServiceManager.attachToRunning`,
490492
);
491493
}
494+
492495
logger.attach(service.containerId, {
493496
serviceId,
497+
logLevel: service.logLevel(),
494498
});
495499
}
496500
}

src/compose/service.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import log from '../lib/supervisor-console';
1414
import * as conversions from '../lib/conversions';
1515
import { checkInt } from '../lib/validation';
1616
import { InternalInconsistencyError } from '../lib/errors';
17+
import { LogLevel } from '../logging/types';
1718

1819
import type { EnvVarObject } from '../types';
1920
import type {
@@ -1185,6 +1186,18 @@ class ServiceImpl implements Service {
11851186
`${updateLock.lockPath(appId, serviceName)}:/tmp/balena`,
11861187
];
11871188
}
1189+
1190+
public logLevel(): LogLevel {
1191+
switch (this.config.environment['BALENA_LOGS_LEVEL']) {
1192+
case 'none':
1193+
return LogLevel.None;
1194+
case 'err':
1195+
case 'error':
1196+
return LogLevel.Err;
1197+
default:
1198+
return LogLevel.Info;
1199+
}
1200+
}
11881201
}
11891202

11901203
export const Service = ServiceImpl;

src/compose/types/service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type Dockerode from 'dockerode';
33
import { isAbsolute } from 'path';
44

55
import type { PortMap } from '../ports';
6+
import type { LogLevel } from '../../logging/types';
67

78
export interface ComposeHealthcheck {
89
test: string | string[];
@@ -392,4 +393,5 @@ export interface Service {
392393
containerIds: Dictionary<string>;
393394
}): Dockerode.ContainerCreateOptions;
394395
handoverCompleteFullPathsOnHost(): string[];
396+
logLevel(): LogLevel;
395397
}

src/logging/index.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { LogType } from '../lib/log-types';
66
import { BalenaLogBackend } from './balena-backend';
77
import { LocalLogBackend } from './local-backend';
88
import type { LogBackend } from './log-backend';
9-
import type { LogMessage } from './types';
9+
import { LogLevel, type LogMessage } from './types';
1010
import logMonitor from './monitor';
1111

1212
import * as globalEventBus from '../event-bus';
@@ -126,18 +126,31 @@ export function logSystemMessage(
126126
}
127127
}
128128

129-
type ServiceInfo = { serviceId: number };
130-
export function attach(containerId: string, { serviceId }: ServiceInfo): void {
129+
type ServiceInfo = { serviceId: number; logLevel: LogLevel };
130+
export function attach(
131+
containerId: string,
132+
{ serviceId, logLevel }: ServiceInfo,
133+
): void {
131134
// First detect if we already have an attached log stream
132135
// for this container
133136
if (logMonitor.isAttached(containerId)) {
134137
return;
135138
}
136139

140+
// skip service attach LogLevel is None
141+
if (logLevel === LogLevel.None) {
142+
return;
143+
}
144+
137145
// We do not grab a container lock here as we are only adding it to the list of container ids to monitor
138146
// and not directly affecting the container itself, and grabbing the lock can cause a delay which means
139147
// that early messages logged from the container are missed and never sent to the backend.
140148
logMonitor.attach(containerId, async (message) => {
149+
// ignore non stderr messages for an error only service
150+
if (logLevel === LogLevel.Err && !message.isStdErr) {
151+
return;
152+
}
153+
141154
await log({ ...message, serviceId });
142155
});
143156
}

src/logging/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ type ContainerLogMessage = BaseLogMessage & {
1111
isSystem?: false;
1212
};
1313
export type LogMessage = SystemLogMessage | ContainerLogMessage;
14+
15+
export enum LogLevel {
16+
None,
17+
Info,
18+
Err,
19+
}

0 commit comments

Comments
 (0)