OpenAI — Example Configuration

A complete configuration that monitors all supported OpenAI API routes.

Full coverage

const { weflayr_setup, weflayr_instrument } = require('weflayr');

weflayr_setup({
  intake_url:    process.env.WEFLAYR_INTAKE_URL,
  client_id:     process.env.WEFLAYR_CLIENT_ID,
  client_secret: process.env.WEFLAYR_CLIENT_SECRET,
  methods: [
    { call: 'chat.completions.create' },
    { call: 'completions.create' },
    { call: 'embeddings.create' },
    { call: 'responses.create' },
    {
      call: 'audio.speech.create',
      middleware: (args) => ({ char_count: args?.input?.length ?? 0 }),
    },
    { call: 'audio.transcriptions.create' },
    { call: 'audio.translations.create' },
  ],
});

const OpenAI = require('openai');
const client = weflayr_instrument(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }));
import os
from openai import OpenAI
from weflayr import weflayr_setup, weflayr_instrument

weflayr_setup({
    "intake_url":    os.environ["WEFLAYR_INTAKE_URL"],
    "client_id":     os.environ["WEFLAYR_CLIENT_ID"],
    "client_secret": os.environ["WEFLAYR_CLIENT_SECRET"],
    "methods": [
        {"call": "chat.completions.create"},
        {"call": "completions.create"},
        {"call": "embeddings.create"},
        {"call": "responses.create"},
        {
            "call": "audio.speech.create",
            "middleware": lambda args, resp: {"char_count": len(args.get("input") or "")},
        },
        {"call": "audio.transcriptions.create"},
        {"call": "audio.translations.create"},
    ],
})

client = weflayr_instrument(OpenAI(api_key=os.environ["OPENAI_API_KEY"]))

Redacting sensitive content

Pass an ignore_fields function to strip message content from events while keeping metadata. The function receives a deep clone of the payload — the original args forwarded to OpenAI are never affected.

weflayr_setup({
  intake_url:    process.env.WEFLAYR_INTAKE_URL,
  client_id:     process.env.WEFLAYR_CLIENT_ID,
  client_secret: process.env.WEFLAYR_CLIENT_SECRET,
  ignore_fields: (data) => {
    (data.messages ?? []).forEach(m => delete m.content);
    (data.choices  ?? []).forEach(c => { if (c.message) delete c.message.content; });
    return data;
  },
  methods: [
    { call: 'chat.completions.create' },
  ],
});
def ignore_fn(data):
    for m in (data.get("messages") or []):
        m.pop("content", None)
    for c in (data.get("choices") or []):
        if c.get("message"):
            c["message"].pop("content", None)
    return data

weflayr_setup({
    "intake_url":    os.environ["WEFLAYR_INTAKE_URL"],
    "client_id":     os.environ["WEFLAYR_CLIENT_ID"],
    "client_secret": os.environ["WEFLAYR_CLIENT_SECRET"],
    "ignore_fields": ignore_fn,
    "methods": [{"call": "chat.completions.create"}],
})

To keep only specific fields, use allow_fields instead:

weflayr_setup({
  // ...
  allow_fields: (data) => ({
    model: data.model,
    usage: data.usage,
  }),
  methods: [{ call: 'chat.completions.create' }],
});
weflayr_setup({
    # ...
    "allow_fields": lambda data: {"model": data.get("model"), "usage": data.get("usage")},
    "methods": [{"call": "chat.completions.create"}],
})

ignore_fields and allow_fields are mutually exclusive — setting both blocks all events.

Tagging calls

Pass __weflayr_tags on any instrumented call to slice analytics by feature, customer, or environment. The field is stripped before the request reaches OpenAI.

await client.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: 'Hello' }],
  __weflayr_tags: {
    provider: 'openai',
    feature: 'support-chat',
    customer_id: 'acme-corp',
    env: 'production',
  },
});
client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello"}],
    __weflayr_tags={
        "provider": "openai",
        "feature": "support-chat",
        "customer_id": "acme-corp",
        "env": "production",
    },
)

Image generation

Add images.generate to methods to track gpt-image-1 calls. The model returns token usage (input_tokens, output_tokens) in response.usage, so cost is computed the same way as chat completions.

When the response includes base64-encoded images (b64_json), each image object can be several megabytes. Always strip it via ignore_fields:

const { weflayr_setup, weflayr_instrument } = require('weflayr');

weflayr_setup({
  intake_url:    process.env.WEFLAYR_INTAKE_URL,
  client_id:     process.env.WEFLAYR_CLIENT_ID,
  client_secret: process.env.WEFLAYR_CLIENT_SECRET,
  ignore_fields: (data) => {
    (data.data ?? []).forEach(img => delete img.b64_json);
    return data;
  },
  methods: [
    { call: 'images.generate' },
  ],
});

const OpenAI = require('openai');
const client = weflayr_instrument(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }));
import os
from openai import OpenAI
from weflayr import weflayr_setup, weflayr_instrument


def ignore_b64(data):
    for img in (data.get("data") or []):
        img.pop("b64_json", None)
    return data


weflayr_setup({
    "intake_url":    os.environ["WEFLAYR_INTAKE_URL"],
    "client_id":     os.environ["WEFLAYR_CLIENT_ID"],
    "client_secret": os.environ["WEFLAYR_CLIENT_SECRET"],
    "ignore_fields": ignore_b64,
    "methods": [{"call": "images.generate"}],
})

client = weflayr_instrument(OpenAI(api_key=os.environ["OPENAI_API_KEY"]))

The filter is safe to apply unconditionally when the model returns URLs instead of base64, b64_json is absent and the loop is a no-op.

Middleware

Use middleware on a method to attach computed fields to events. The function receives (args, response)response is null on before events.

{
  call: 'audio.speech.create',
  middleware: (args, response) => ({
    char_count: args?.input?.length ?? 0,
  }),
}
{
    "call": "audio.speech.create",
    "middleware": lambda args, resp: {"char_count": len(args.get("input") or "")},
}

The returned object is merged into the event payload.