How to Enable and Customize JSON Logging in InterSystems IRIS (with Tenant ID Example)
Hello everyone,
As part of our recent initiative to modernize our observability stack, we have successfully transitioned our InterSystems IRIS logging framework to a structured JSON format. Now we need to dynamically enrich these logs with business-critical metadata specifically, theTenant ID.
We have this configmap to enable Json logs:
apiVersion: v1
kind: ConfigMap
metadata:
name: iris-cpf-merge
namespace: {{ .Release.Namespace }}
data:
merge.cpf: |
[Logging]
ChildProcessLaunchCommand=/usr/irissys/bin/irislogd -f /tmp/messages.json
Format=JSON
Enabled=1but we need to run a
iris merge IRIS /config/merge.cpfin order to apply changes on a durable Durable %SYS deployment. This ensures that our logging modifications are dynamically injected into the persistent iris.cpf file on the external volume, maintaining configuration persistence across pod restarts, upgrades, and container lifecycle events without state loss. Is there a better alternative that avoids running iris merge manually in the script?
By the other hand we have injected the tenant id by using this configmap:
apiVersion: v1
kind: ConfigMap
metadata:
name: iris-poststart-script
namespace: {{ .Release.Namespace }}
data: init-json-logs.sh: |
#!/bin/bash
(
# 1. SATELLITE LOOP: Searches for the ID in the background and saves it to a TXT file
(
while true; do
TID=$(printf 'USER\PASSWORD\nZN "WEBCONFIG"\nSET ts=##class(src.main.acl.outbound.service.license. TenantService).%%New()\nWRITE ts.getTenantId()\nHALT\n' \
| iris session IRIS 2>/dev/null \
| grep -v '>' \
| grep -v -E '^\s*$|^Node:|^Username:|^Password:' \
| tail -1 \
| tr -d '\n\r')
if [ -n "$TID" ]; then
echo "$TID" > /tmp/tenant_id.txt
break
fi
sleep 5
done
) &
# 2. Create Python script to inject tenant id
cat << 'EOF' > /tmp/inject-tenant.py
import sys, json, os
def inject(line, tid):
try:
d = json.loads(line)
d['tenantId'] = tid
print(json.dumps(d), flush=True)
except:
try:
l2 = line.rstrip().rstrip('}')
print(l2 + ', "tenantId": "' + tid + '"}', flush=True)
except:
print(line, flush=True)
# Wait for the tenantId BEFORE processing anything
tid = ""
while not tid:
try:
with open('/tmp/tenant_id.txt', 'r') as f:
tid = f.read().strip()
except:
pass
if not tid:
import time; time.sleep(1)
for l in sys.stdin:
l = l.strip()
if not l:
continue
inject(l, tid)
EOF
# 3. Block pipeline execution until log and tenant id are ready
until [ -s /tmp/messages.json ] && [ -s /tmp/tenant_id.txt ]; do sleep 2; done
# 4. Trigger the pipeline
tail -F /tmp/messages.json 2>/dev/null | python3 -u /tmp/inject-tenant.py 1>/proc/1/fd/1 2>/dev/null &
) /dev/null 2>&1 &Is there a more robust and native alternative for log enrichment that avoids using a background Bash loop and a Python stream proxy?
While the background loop and Python script successfully achieve the goal, the approach introduces architectural complexity (terminal text scraping via iris session, relying on temporary files, and routing all container stdout through a custom Python process). This introduces CPU overhead and potential points of failure.