Skip to content

Commit a688bb0

Browse files
fix: initial creation of child logging (#533)
## Description The main goal is to be able to have pepr maintain one level of logging ( info ) and uds logs at another level ( debug ). There are some log changes in the package output to decrease extra noise, as well as a few logs moved from debug to trace level. This change also addresses a comment on another PR about JWT's being logged, which was part of pepr logs at the debug level. Definitely open to discussions about at what level we want to log the childLog subproject. ## Related Issue Fixes #526 Relates to #201 ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [x] Other (security config, docs update, etc) ## Checklist before merging - [x] Test, docs, adr added or updated as needed - [x] [Contributor Guide Steps](https://github.com/defenseunicorns/uds-template-capability/blob/main/CONTRIBUTING.md)(https://github.com/defenseunicorns/uds-template-capability/blob/main/CONTRIBUTING.md#submitting-a-pull-request) followed --------- Co-authored-by: Micah Nagel <micah.nagel@defenseunicorns.com>
1 parent 26fa750 commit a688bb0

20 files changed

Lines changed: 199 additions & 90 deletions

File tree

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"name": "UDS Core",
1717
"uuid": "uds-core",
1818
"onError": "reject",
19-
"logLevel": "debug",
19+
"logLevel": "info",
2020
"alwaysIgnore": {
2121
"namespaces": [
2222
"uds-dev-stack",
@@ -27,7 +27,8 @@
2727
"env": {
2828
"UDS_DOMAIN": "###ZARF_VAR_DOMAIN###",
2929
"UDS_ALLOW_ALL_NS_EXEMPTIONS": "###ZARF_VAR_ALLOW_ALL_NS_EXEMPTIONS###",
30-
"UDS_SINGLE_TEST": "###ZARF_VAR_UDS_SINGLE_TEST###"
30+
"UDS_SINGLE_TEST": "###ZARF_VAR_UDS_SINGLE_TEST###",
31+
"UDS_LOG_LEVEL": "###ZARF_VAR_UDS_LOG_LEVEL###"
3132
}
3233
},
3334
"scripts": {

src/pepr/config.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Log } from "pepr";
1+
import { Component, setupLogger } from "./logger";
22

33
let domain = process.env.UDS_DOMAIN;
44

@@ -16,10 +16,12 @@ export const UDSConfig = {
1616
allowAllNSExemptions: process.env.UDS_ALLOW_ALL_NS_EXEMPTIONS === "true",
1717
};
1818

19-
Log.info(UDSConfig, "Loaded UDS Config");
19+
// configure subproject logger
20+
const log = setupLogger(Component.CONFIG);
21+
log.info(UDSConfig, "Loaded UDS Config");
2022

2123
if (UDSConfig.isSingleTest) {
22-
Log.warn(
24+
log.warn(
2325
"Running in single test mode, this will change the behavior of the operator and should only be used for UDS Core development testing.",
2426
);
2527
}

src/pepr/istio/index.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { Exec, KubeConfig } from "@kubernetes/client-node";
2-
import { Capability, Log, a } from "pepr";
2+
import { Capability, a } from "pepr";
3+
import { Component, setupLogger } from "../logger";
4+
5+
// configure subproject logger
6+
const log = setupLogger(Component.ISTIO);
37

48
export const istio = new Capability({
59
name: "istio",
@@ -20,13 +24,8 @@ When(a.Pod)
2024
.WithLabel("batch.kubernetes.io/job-name")
2125
.WithLabel("service.istio.io/canonical-name")
2226
.Watch(async pod => {
23-
Log.info(
24-
pod,
25-
`Processing Pod ${pod.metadata?.namespace}/${pod.metadata?.name} for istio job termination`,
26-
);
27-
2827
if (!pod.metadata?.name || !pod.metadata.namespace) {
29-
Log.error(pod, `Invalid Pod definition`);
28+
log.error(pod, `Invalid Pod definition`);
3029
return;
3130
}
3231

@@ -42,7 +41,7 @@ When(a.Pod)
4241
if (pod.status?.phase == "Running") {
4342
// Check all container statuses
4443
if (!pod.status.containerStatuses) {
45-
Log.error(pod, `Invalid container status in Pod`);
44+
log.error(pod, `Invalid container status in Pod`);
4645
return;
4746
}
4847
const shouldTerminate = pod.status.containerStatuses
@@ -55,7 +54,7 @@ When(a.Pod)
5554
// Mark the pod as seen
5655
inProgress.add(key);
5756

58-
Log.info(`Attempting to terminate sidecar for ${key}`);
57+
log.info(`Attempting to terminate sidecar for ${key}`);
5958
try {
6059
const kc = new KubeConfig();
6160
kc.loadFromDefault();
@@ -72,9 +71,9 @@ When(a.Pod)
7271
true,
7372
);
7473

75-
Log.info(`Terminated sidecar for ${key}`);
74+
log.info(`Terminated sidecar for ${key}`);
7675
} catch (err) {
77-
Log.error({ err }, `Failed to terminate the sidecar for ${key}`);
76+
log.error({ err }, `Failed to terminate the sidecar for ${key}`);
7877

7978
// Remove the pod from the seen list
8079
inProgress.delete(key);

src/pepr/logger.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Log } from "pepr";
2+
3+
export enum Component {
4+
CONFIG = "config",
5+
ISTIO = "istio",
6+
OPERATOR_EXEMPTIONS = "operator.exemptions",
7+
OPERATOR_ISTIO = "operator.istio",
8+
OPERATOR_KEYCLOAK = "operator.keycloak",
9+
OPERATOR_MONITORING = "operator.monitoring",
10+
OPERATOR_NETWORK = "operator.network",
11+
OPERATOR_GENERATORS = "operator.generators",
12+
OPERATOR_CRD = "operator.crd",
13+
OPERATOR_RECONCILERS = "operator.reconcilers",
14+
POLICIES = "policies",
15+
POLICIES_EXEMPTIONS = "policies.exemptions",
16+
PROMETHEUS = "prometheus",
17+
}
18+
19+
export function setupLogger(component: Component) {
20+
const setupLogger = Log.child({ component });
21+
22+
// Handle commands that do not template the env vars
23+
let logLevel = process.env.UDS_LOG_LEVEL;
24+
if (!logLevel || logLevel === "###ZARF_VAR_UDS_LOG_LEVEL###") {
25+
logLevel = "debug";
26+
}
27+
28+
setupLogger.level = logLevel;
29+
30+
return setupLogger;
31+
}

src/pepr/operator/controllers/exemptions/exemption-store.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import { Log } from "pepr";
1+
import { Component, setupLogger } from "../../../logger";
22
import { StoredMatcher } from "../../../policies";
33
import { Matcher, Policy, UDSExemption } from "../../crd";
44

5+
// configure subproject logger
6+
const log = setupLogger(Component.OPERATOR_EXEMPTIONS);
7+
58
export type PolicyOwnerMap = Map<string, UDSExemption>;
69
export type PolicyMap = Map<Policy, StoredMatcher[]>;
710
let policyExemptionMap: PolicyMap;
@@ -34,7 +37,7 @@ function addMatcher(matcher: Matcher, p: Policy, owner: string = ""): void {
3437
}
3538

3639
// Iterate through each exemption block of CR and add matchers to PolicyMap
37-
function add(exemption: UDSExemption, log: boolean = true) {
40+
function add(exemption: UDSExemption, logger: boolean = true) {
3841
// Remove any existing exemption for this owner, in case of WatchPhase.Modified
3942
remove(exemption);
4043
const owner = exemption.metadata?.uid || "";
@@ -45,8 +48,8 @@ function add(exemption: UDSExemption, log: boolean = true) {
4548
for (const p of policies) {
4649
// Append the matcher to the list of stored matchers for this policy
4750
addMatcher(e.matcher, p, owner);
48-
if (log) {
49-
Log.debug(`Added exemption to ${p}: ${JSON.stringify(e.matcher)}`);
51+
if (logger) {
52+
log.debug(`Added exemption to ${p}: ${JSON.stringify(e.matcher)}`);
5053
}
5154
}
5255
}
@@ -68,9 +71,9 @@ function remove(exemption: UDSExemption) {
6871
}
6972
}
7073
policyOwnerMap.delete(owner);
71-
Log.debug(`Removed all policy exemptions for ${owner}`);
74+
log.debug(`Removed all policy exemptions for ${owner}`);
7275
} else {
73-
Log.debug(`No existing exemption for owner ${owner}`);
76+
log.debug(`No existing exemption for owner ${owner}`);
7477
}
7578
}
7679

src/pepr/operator/controllers/istio/injection.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import { K8s, Log, kind } from "pepr";
1+
import { K8s, kind } from "pepr";
22

3+
import { Component, setupLogger } from "../../../logger";
34
import { UDSPackage } from "../../crd";
45

6+
// configure subproject logger
7+
const log = setupLogger(Component.OPERATOR_ISTIO);
8+
59
const injectionLabel = "istio-injection";
610
const injectionAnnotation = "uds.dev/original-istio-injection";
711

@@ -143,7 +147,7 @@ async function killPods(ns: string, enableInjection: boolean) {
143147
}
144148

145149
for (const pod of group) {
146-
Log.info(`Deleting pod ${ns}/${pod.metadata?.name} to enable the istio sidecar`);
150+
log.info(`Deleting pod ${ns}/${pod.metadata?.name} to enable the istio sidecar`);
147151
await K8s(kind.Pod).Delete(pod);
148152
}
149153
}

src/pepr/operator/controllers/istio/istio-resources.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import { K8s, Log } from "pepr";
1+
import { K8s } from "pepr";
22

3-
import { IstioVirtualService, IstioServiceEntry, UDSPackage } from "../../crd";
3+
import { Component, setupLogger } from "../../../logger";
4+
import { IstioServiceEntry, IstioVirtualService, UDSPackage } from "../../crd";
45
import { getOwnerRef } from "../utils";
5-
import { generateVirtualService } from "./virtual-service";
66
import { generateServiceEntry } from "./service-entry";
7+
import { generateVirtualService } from "./virtual-service";
8+
9+
// configure subproject logger
10+
const log = setupLogger(Component.OPERATOR_ISTIO);
711

812
/**
913
* Creates a VirtualService and ServiceEntry for each exposed service in the package
@@ -30,7 +34,7 @@ export async function istioResources(pkg: UDSPackage, namespace: string) {
3034
// Generate a VirtualService for this `expose` entry
3135
const vsPayload = generateVirtualService(expose, namespace, pkgName, generation, ownerRefs);
3236

33-
Log.debug(vsPayload, `Applying VirtualService ${vsPayload.metadata?.name}`);
37+
log.debug(vsPayload, `Applying VirtualService ${vsPayload.metadata?.name}`);
3438

3539
// Apply the VirtualService and force overwrite any existing policy
3640
await K8s(IstioVirtualService).Apply(vsPayload, { force: true });
@@ -45,7 +49,7 @@ export async function istioResources(pkg: UDSPackage, namespace: string) {
4549
continue;
4650
}
4751

48-
Log.debug(sePayload, `Applying ServiceEntry ${sePayload.metadata?.name}`);
52+
log.debug(sePayload, `Applying ServiceEntry ${sePayload.metadata?.name}`);
4953

5054
// Apply the ServiceEntry and force overwrite any existing policy
5155
await K8s(IstioServiceEntry).Apply(sePayload, { force: true });
@@ -66,7 +70,7 @@ export async function istioResources(pkg: UDSPackage, namespace: string) {
6670

6771
// Delete any orphaned VirtualServices
6872
for (const vs of orphanedVS) {
69-
Log.debug(vs, `Deleting orphaned VirtualService ${vs.metadata!.name}`);
73+
log.debug(vs, `Deleting orphaned VirtualService ${vs.metadata!.name}`);
7074
await K8s(IstioVirtualService).Delete(vs);
7175
}
7276

@@ -83,7 +87,7 @@ export async function istioResources(pkg: UDSPackage, namespace: string) {
8387

8488
// Delete any orphaned ServiceEntries
8589
for (const se of orphanedSE) {
86-
Log.debug(se, `Deleting orphaned ServiceEntry ${se.metadata!.name}`);
90+
log.debug(se, `Deleting orphaned ServiceEntry ${se.metadata!.name}`);
8791
await K8s(IstioServiceEntry).Delete(se);
8892
}
8993

src/pepr/operator/controllers/keycloak/client-sync.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { K8s, Log, fetch, kind } from "pepr";
1+
import { fetch, K8s, kind } from "pepr";
22

33
import { UDSConfig } from "../../../config";
4+
import { Component, setupLogger } from "../../../logger";
45
import { Store } from "../../common";
56
import { Sso, UDSPackage } from "../../crd";
67
import { getOwnerRef } from "../utils";
@@ -32,6 +33,9 @@ const x509CertRegex = new RegExp(
3233
/<[^>]*:X509Certificate[^>]*>((.|[\n\r])*)<\/[^>]*:X509Certificate>/,
3334
);
3435

36+
// configure subproject logger
37+
const log = setupLogger(Component.OPERATOR_KEYCLOAK);
38+
3539
/**
3640
* Create or update the Keycloak clients for the package
3741
*
@@ -72,7 +76,7 @@ export async function purgeSSOClients(pkg: UDSPackage, refs: string[] = []) {
7276
Store.removeItem(ref);
7377
await apiCall({ clientId }, "DELETE", token);
7478
} else {
75-
Log.warn(pkg.metadata, `Failed to remove client ${clientId}, token not found`);
79+
log.warn(pkg.metadata, `Failed to remove client ${clientId}, token not found`);
7680
}
7781
}
7882
}
@@ -82,7 +86,8 @@ async function syncClient(
8286
pkg: UDSPackage,
8387
isRetry = false,
8488
) {
85-
Log.debug(pkg.metadata, `Processing client request: ${clientReq.clientId}`);
89+
log.debug(pkg.metadata, `Processing client request: ${clientReq.clientId}`);
90+
8691
// Not including the CR data in the ref because Keycloak client IDs must be unique already
8792
const name = `sso-client-${clientReq.clientId}`;
8893
let client: Client;
@@ -94,10 +99,10 @@ async function syncClient(
9499
try {
95100
// If an existing client is found, use the token to update the client
96101
if (token && !isRetry) {
97-
Log.debug(pkg.metadata, `Found existing token for ${clientReq.clientId}`);
102+
log.debug(pkg.metadata, `Found existing token for ${clientReq.clientId}`);
98103
client = await apiCall(clientReq, "PUT", token);
99104
} else {
100-
Log.debug(pkg.metadata, `Creating new client for ${clientReq.clientId}`);
105+
log.debug(pkg.metadata, `Creating new client for ${clientReq.clientId}`);
101106
client = await apiCall(clientReq);
102107
}
103108
} catch (err) {
@@ -107,12 +112,12 @@ async function syncClient(
107112

108113
// Throw the error if this is the retry or was an initial client creation attempt
109114
if (isRetry || !token) {
110-
Log.error(`${msg}, retry failed.`);
115+
log.error(`${msg}, retry failed.`);
111116
// Throw the original error captured from the first attempt
112117
throw new Error(msg);
113118
} else {
114119
// Retry the request without the token in case we have a bad token stored
115-
Log.error(msg);
120+
log.error(msg);
116121

117122
try {
118123
return await syncClient(clientReq, pkg, true);
@@ -121,7 +126,7 @@ async function syncClient(
121126
const retryMsg =
122127
`Retry of Keycloak request failed for client '${clientReq.clientId}', package ` +
123128
`${pkg.metadata?.namespace}/${pkg.metadata?.name}. Error: ${retryErr.message}`;
124-
Log.error(retryMsg);
129+
log.error(retryMsg);
125130
// Throw the error from the original attempt since our retry without token failed
126131
throw new Error(msg);
127132
}
@@ -154,6 +159,7 @@ async function syncClient(
154159
labels: {
155160
"uds/package": pkg.metadata!.name,
156161
},
162+
157163
// Use the CR as the owner ref for each VirtualService
158164
ownerReferences: getOwnerRef(pkg),
159165
},
@@ -185,7 +191,7 @@ export function handleClientGroups(clientReq: Sso) {
185191
async function apiCall(sso: Partial<Sso>, method = "POST", authToken = "") {
186192
// Handle single test mode
187193
if (UDSConfig.isSingleTest) {
188-
Log.warn(`Generating fake client for '${sso.clientId}' in single test mode`);
194+
log.warn(`Generating fake client for '${sso.clientId}' in single test mode`);
189195
return {
190196
...sso,
191197
secret: sso.secret || "fake-secret",
@@ -231,14 +237,14 @@ async function apiCall(sso: Partial<Sso>, method = "POST", authToken = "") {
231237

232238
export function generateSecretData(client: Client, secretTemplate?: { [key: string]: string }) {
233239
if (secretTemplate) {
234-
Log.debug(`Using secret template for client: ${client.clientId}`);
240+
log.debug(`Using secret template for client: ${client.clientId}`);
235241
// Iterate over the secret template entry and process each value
236242
return templateData(secretTemplate, client);
237243
}
238244

239245
const stringMap: Record<string, string> = {};
240246

241-
Log.debug(`Using client data for secret: ${client.clientId}`);
247+
log.debug(`Using client data for secret: ${client.clientId}`);
242248

243249
// iterate over the client object and convert all values to strings
244250
for (const [key, value] of Object.entries(client)) {

src/pepr/operator/controllers/monitoring/service-monitor.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import { K8s, Log } from "pepr";
1+
import { K8s } from "pepr";
22

33
import { V1OwnerReference } from "@kubernetes/client-node";
4-
import { Prometheus, UDSPackage, Monitor } from "../../crd";
4+
import { Component, setupLogger } from "../../../logger";
5+
import { Monitor, Prometheus, UDSPackage } from "../../crd";
56
import { getOwnerRef, sanitizeResourceName } from "../utils";
67

8+
// configure subproject logger
9+
const log = setupLogger(Component.OPERATOR_MONITORING);
10+
711
/**
812
* Generate a service monitor for a service
913
*
@@ -15,7 +19,7 @@ export async function serviceMonitor(pkg: UDSPackage, namespace: string) {
1519
const generation = (pkg.metadata?.generation ?? 0).toString();
1620
const ownerRefs = getOwnerRef(pkg);
1721

18-
Log.debug(`Reconciling ServiceMonitors for ${pkgName}`);
22+
log.debug(`Reconciling ServiceMonitors for ${pkgName}`);
1923

2024
// Get the list of monitored services
2125
const monitorList = pkg.spec?.monitor ?? [];
@@ -27,7 +31,7 @@ export async function serviceMonitor(pkg: UDSPackage, namespace: string) {
2731
for (const monitor of monitorList) {
2832
const payload = generateServiceMonitor(monitor, namespace, pkgName, generation, ownerRefs);
2933

30-
Log.debug(payload, `Applying ServiceMonitor ${payload.metadata?.name}`);
34+
log.debug(payload, `Applying ServiceMonitor ${payload.metadata?.name}`);
3135

3236
// Apply the ServiceMonitor and force overwrite any existing policy
3337
await K8s(Prometheus.ServiceMonitor).Apply(payload, { force: true });
@@ -48,7 +52,7 @@ export async function serviceMonitor(pkg: UDSPackage, namespace: string) {
4852

4953
// Delete any orphaned ServiceMonitors
5054
for (const sm of orphanedSM) {
51-
Log.debug(sm, `Deleting orphaned ServiceMonitor ${sm.metadata!.name}`);
55+
log.debug(sm, `Deleting orphaned ServiceMonitor ${sm.metadata!.name}`);
5256
await K8s(Prometheus.ServiceMonitor).Delete(sm);
5357
}
5458
} catch (err) {

0 commit comments

Comments
 (0)