Question Daniel Astudillo · May 26

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=1

 but we need to run a 

iris merge IRIS /config/merge.cpf

in 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.

 
Product version: IRIS 2024.1
$ZV: IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2024.1.1 (Build 347_0_24295U)

Comments