Skip to main content

Overview

flush() forces immediate export of all pending spans to Keywords AI. Useful before application shutdown or when you need to ensure data is sent immediately.

Signature

async flush(): Promise<void>

Basic Usage

import { KeywordsAITelemetry } from '@keywordsai/tracing';

const keywordsAi = new KeywordsAITelemetry({
    apiKey: process.env.KEYWORDSAI_API_KEY,
    appName: 'my-app'
});

await keywordsAi.initialize();

await keywordsAi.withWorkflow(
    { name: 'my_workflow' },
    async () => {
        return await processData();
    }
);

// Manually flush spans
await keywordsAi.getClient().flush();
console.log('Spans sent to Keywords AI');

Before Application Exit

async function main() {
    const keywordsAi = new KeywordsAITelemetry({
        apiKey: process.env.KEYWORDSAI_API_KEY,
        appName: 'batch-job'
    });
    
    await keywordsAi.initialize();
    
    try {
        await keywordsAi.withWorkflow(
            { name: 'batch_processing' },
            async () => {
                for (let i = 0; i < 100; i++) {
                    await processBatch(i);
                }
                return 'complete';
            }
        );
    } finally {
        // Ensure all spans are sent before exit
        await keywordsAi.getClient().flush();
        console.log('All traces flushed');
    }
}

main().catch(console.error);

Periodic Flushing

await keywordsAi.withWorkflow(
    { name: 'long_running_job' },
    async () => {
        for (let i = 0; i < 1000; i++) {
            await keywordsAi.withTask(
                { name: `batch_${i}` },
                async () => {
                    return await processBatch(i);
                }
            );
            
            // Flush every 100 batches
            if (i % 100 === 0) {
                await keywordsAi.getClient().flush();
                console.log(`Flushed after batch ${i}`);
            }
        }
        
        return 'complete';
    }
);

Serverless Functions

// AWS Lambda handler
export async function handler(event: any) {
    const keywordsAi = new KeywordsAITelemetry({
        apiKey: process.env.KEYWORDSAI_API_KEY,
        appName: 'lambda-function'
    });
    
    await keywordsAi.initialize();
    
    try {
        const result = await keywordsAi.withWorkflow(
            { name: 'lambda_execution' },
            async () => {
                return await processEvent(event);
            }
        );
        
        // Flush before Lambda freezes
        await keywordsAi.getClient().flush();
        
        return {
            statusCode: 200,
            body: JSON.stringify(result)
        };
    } catch (error) {
        // Flush even on error
        await keywordsAi.getClient().flush();
        throw error;
    }
}

Express Middleware

import express from 'express';

const app = express();

const keywordsAi = new KeywordsAITelemetry({
    apiKey: process.env.KEYWORDSAI_API_KEY,
    appName: 'api-server'
});

await keywordsAi.initialize();

app.post('/api/important', async (req, res) => {
    try {
        const result = await keywordsAi.withWorkflow(
            { name: 'critical_operation' },
            async () => {
                return await processCriticalRequest(req.body);
            }
        );
        
        // Flush immediately for critical operations
        await keywordsAi.getClient().flush();
        
        res.json({ success: true, result });
    } catch (error) {
        await keywordsAi.getClient().flush();
        res.status(500).json({ error: error.message });
    }
});

// Graceful shutdown
process.on('SIGTERM', async () => {
    console.log('Flushing traces before shutdown...');
    await keywordsAi.getClient().flush();
    process.exit(0);
});

Testing

import { describe, it, beforeAll, afterAll } from '@jest/globals';

describe('My Service', () => {
    let keywordsAi: KeywordsAITelemetry;
    
    beforeAll(async () => {
        keywordsAi = new KeywordsAITelemetry({
            apiKey: process.env.KEYWORDSAI_API_KEY,
            appName: 'test-suite'
        });
        await keywordsAi.initialize();
    });
    
    afterAll(async () => {
        // Flush all test traces
        await keywordsAi.getClient().flush();
    });
    
    it('should process data', async () => {
        await keywordsAi.withWorkflow(
            { name: 'test_workflow' },
            async () => {
                const result = await processData();
                expect(result).toBeDefined();
            }
        );
    });
});

With shutdown()

For complete cleanup, use shutdown() instead of flush(). shutdown() flushes and then closes the tracer.
// Flush only (tracer stays active)
await keywordsAi.getClient().flush();

// Shutdown (flush + close tracer)
await keywordsAi.shutdown();

Best Practices

  • Call flush() before application exit to ensure no data is lost
  • Use shutdown() for complete cleanup instead of just flush()
  • In serverless environments, always flush before function completion
  • For critical operations, flush immediately after completion
  • Flush is automatically called periodically when batching is enabled
  • Flushing is synchronous and waits for export to complete
  • In long-running processes, prefer shutdown() over flush() when done