fair-rose
fair-rose10mo ago

Audit Log Provider Question / Example

Hey everyone! So far Refine has been great. I am a little confused on the Audit Log Provider however, what would be a good pattern for using it? Some context - I am creating a portal to interact with a large Airtable base, and i want to track who makes edits to records. I'm wondering if I would create a new table and write logs there or if anyone had reccomendations
9 Replies
kapa.ai
kapa.ai10mo ago
Hi @jawmes.. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Sure, I can help with that. The Audit Log Provider in Refine is a powerful tool that allows you to track changes and who made them in your data. It works by sending a new log event record whenever a new record is created, updated, or deleted. To use the auditLogProvider, you need to pass it to the <Refine> component in your App.tsx file like this:
import { Refine } from "@refinedev/core";
import auditLogProvider from "./auditLogProvider";

const App: React.FC = () => {
return <Refine auditLogProvider={auditLogProvider} />;
};
import { Refine } from "@refinedev/core";
import auditLogProvider from "./auditLogProvider";

const App: React.FC = () => {
return <Refine auditLogProvider={auditLogProvider} />;
};
The auditLogProvider object should have three methods: create, get, and update. Here's an example of what your auditLogProvider might look like:
const auditLogProvider = {
create: (params: {
resource: string;
action: string;
data?: any;
author?: {
name?: string;
[key: string]: any;
};
previousData?: any;
meta?: Record<string, any>;
}) => void;
get: (params: {
resource: string;
action?: string;
meta?: Record<string, any>;
author?: Record<string, any>;
metaData?: MetaDataQuery;
}) => Promise<any>;
update: (params: {
id: BaseKey;
name: string;
}) => Promise<any>;
};
const auditLogProvider = {
create: (params: {
resource: string;
action: string;
data?: any;
author?: {
name?: string;
[key: string]: any;
};
previousData?: any;
meta?: Record<string, any>;
}) => void;
get: (params: {
resource: string;
action?: string;
meta?: Record<string, any>;
author?: Record<string, any>;
metaData?: MetaDataQuery;
}) => Promise<any>;
update: (params: {
id: BaseKey;
name: string;
}) => Promise<any>;
};
In your case, you could create a new table in your Airtable base and write logs there. The create method in your auditLogProvider would be responsible for creating a new log entry in this table whenever a record is created, updated, or deleted. The get method would be used to fetch a list of these log entries, and the update method would be used to update an existing log entry. You can also use the useLog and useLogList hooks provided by Refine to access your auditLogProvider methods from anywhere in your application. For more detailed information, you can refer to the Refine Audit Log Provider documentation (https://refine.dev/docs/api-reference/core/providers/audit-log-provider/). If you want to see a practical example of how to create an audit log provider, you can check out the source code of the audit log provider example (https://github.com/refinedev/refine/tree/master/examples/audit-log-provider) provided by Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai10mo ago
<@632698368958791681> kapa.ai is still learning and improving, please let us know how it did by reacting below
fair-rose
fair-rose10mo ago
The above answer makes sense, I think I will create a new table in the base I'm working with called "Logs". For each resource though would I need a new "Log" table? For example, if I have two tables called "Sales" and "Product", would I need a "Sales_Log" and "Product_Log" table? or just one "Logs" table for both? @kapa.ai
kapa.ai
kapa.ai10mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- You can structure your logs in either way, depending on your specific needs and how you want to organize your data. 1. Single "Logs" Table: You can have a single "Logs" table that tracks changes across all resources. In this case, you would likely include a field in each log entry that specifies the resource (e.g., "Sales" or "Product") that the log entry pertains to. This approach can make it easier to get a holistic view of all changes across all resources. 2. Separate "Resource_Log" Tables: Alternatively, you can have separate "Sales_Log" and "Product_Log" tables. This approach can make it easier to manage and understand the logs for each resource separately. The choice between these two approaches depends on your specific use case and how you want to manage your logs. Remember, the auditLogProvider in Refine will handle the creation of these log entries for you. You just need to specify in the create method of your auditLogProvider where to store the log entries (i.e., in which table). For more information on how to implement this, you can refer to the Refine Audit Log Provider documentation (https://refine.dev/docs/api-reference/core/providers/audit-log-provider/). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai10mo ago
<@632698368958791681> kapa.ai is still learning and improving, please let us know how it did by reacting below
fair-rose
fair-rose10mo ago
If I go with option 1, how does refine parse through the logs to get the relevant entry? @kapa.ai
kapa.ai
kapa.ai10mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Refine uses the get method of the auditLogProvider to fetch the relevant log entries. This method is used to query the logs table and retrieve the log entries that match certain criteria. Here's an example of how the get method might be implemented:
get: (params: {
resource: string;
action?: string;
meta?: Record<string, any>;
author?: Record<string, any>;
metaData?: MetaDataQuery;
}) => {
// Use your data provider to query the `logs` table
// Filter the log entries based on the `params` object
// Return the matching log entries
};
get: (params: {
resource: string;
action?: string;
meta?: Record<string, any>;
author?: Record<string, any>;
metaData?: MetaDataQuery;
}) => {
// Use your data provider to query the `logs` table
// Filter the log entries based on the `params` object
// Return the matching log entries
};
In this method, you would use your data provider (in your case, the Airtable API) to query the logs table. You would then filter the log entries based on the params object that is passed to the get method. This object can contain various properties that you can use to filter the log entries, such as the resource, action, meta, and author. For example, if you want to get all log entries for the "Sales" resource, you would call the get method with a params object like this:
auditLogProvider.get({ resource: 'Sales' });
auditLogProvider.get({ resource: 'Sales' });
This would return all log entries where the resource field is "Sales". You can also use the useLogList hook provided by Refine to fetch a list of log entries from anywhere in your application. This hook uses the get method of your auditLogProvider under the hood. For more detailed information, you can refer to the Refine Audit Log Provider documentation (https://refine.dev/docs/api-reference/core/providers/audit-log-provider/). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai10mo ago
<@632698368958791681> kapa.ai is still learning and improving, please let us know how it did by reacting below
harsh-harlequin
harsh-harlequin10mo ago
Hello @jawmes., do you able to solve your issue ? Autdit log provider has the necessary methods and takes the necessary parameters from core. the implementation details are up to you. after implementation, refine will automatically run these methods every time there is a data transaction and send the log to the API.