This documentation, like our python package, is simple.
Three important things to know about this package :
We will be following the CPE-NBC framework to log information.
C - Customer ID - To know which customer is using your product
P - Product ID- To know which product is being used
N - Node ID - To know which node of your product your customer is interacting with? (Front-End, Back-End, Analytics, etc.)
B - Branch ID - To know which branch or version of your product your customer is interacting with?
E - Endpoint - Identifies which features in your product your customers interact with (identifies customer-feature fit)
C - Code ID - To know which code blocks are being run when your customer interacts with your endpoint.
This style of logging makes data relational (every log is related to each other) and provides a complete understanding of your business.
We use function wrappers instead of traditional logging. This makes logging simple and beautiful (really).
Function wrappers start with an @ symbol. For example,
@insightsoncode_logger(log_1, log_2)
def your_product_function():
<your code>
You can log values that simply.
We have three types of loggers - constants logger, endpoint logger and code logger.
Constant loggers @log_constantpoints()
This logs information that will remain constant throughout your code. As the information is constant, they just have to be logged once.
Constant logs include product, node and branch IDs; as each product-node-branch combination define an independent module of your software and are constant within this module.
Endpoint logger @log_endpoint()
This logs the features users interact with (in tech jargon - an endpoint), and is unique for each endpoint at a module level.
Code logger @log_codepoint()
This logs code blocks- which could be any function (block of code) including API calls, Query calls, etc.
Note that we have missed one logging information - Customer ID - as we can gain this information only when running the code and not when writing code.
Customer ID is thus logged separately when a customer interacts with the endpoint (during code run).
Setup (post installation of python package)
In your main python file where the endpoints are defined, import Constant logger and Code logger.
from insightsoncode.wrappers import log_constantpoints, log_codepoint
Define the values for the constant logs by calling the Constants logger function.
log_constantpoints(project_id = "1", branch_id = "main_1", csv_filename ="ioc_business_logs.csv")
The results from the previous step will return a function. Save this function as Endpoint logger.
log_endpoint = log_constantpoints(....)
Write the below line of code. Note that there are No paranthesis at the end of the code. That is we are just re-defining the function, not calling it.
log_codepoint = log_codepoint
The setup is now complete.
Step 4 is required to maintain a single source of truth for Endpoint and Code loggers. This will help in tracking log information across python files.
Therefore, please note that when using Endpoint logger and Code logger in any other file, import them from the main python file.
from main_python_file import log_endpoint, log_codepoint
Endpoint and Code Logger
Endpoint Logger and Code Logger functions are symmetric.
That is, if you understand how one works, you can understand how the other works.
The common syntax for wrapper functions is :
@wrapper(wrapper_params)
def your_function(your_params):
<your code>
The common syntax for Endpoint and Code loggers is :
@logger(logger_params)
def your_function(ioc_logger, more_ioc_params, your_params):
<your code>
There are 3 parts to understanding this :
@logger(logger_params)
Replace logger with log_endpoint or log_codepoint as per the usage. This tells the logger the type of log.
logger_params refers to the parameters you want to log. You can input values here when you know the parameter value before-hand. For ex. Endpoint ID is a parameter value which can be defined as you would know the value prior to calling the endpoint function.
ioc_logger parameter in your_function
If you are logging a function, be it endpoint or code, the first parameter that it accepts should be a variable whose name remains constant across all your functions. Please note that this variable name should not conflict with any other variables you create. We recommend using ioc_logger as it is short, descriptive and would probably not conflict with any of your existing variables.
Note that you have to use this variable at both function definition and function call. (Tip : You can use a "replace across files" option in your editor to perform this more easily)
(Also, if you are extremely clear with how our code works, you can use different names for the above variable at different function definitions, calls and still make everything work. But its messy and you will not gain anything out of the experience except maybe a headache. Our recommended approach is smooth and is highly important in making your data powerfully relational.)
more_ioc_params parameters in your_function
If you know your log parameters during function definition, you can use Part 1. to log them.
If you will know your log parameters only while calling the function, you can pass these directly as function parameters will calling the function. Note that we will automatically pick it up from the parameter values and remove it from your **kwargs list so that your operations don't get affected.
Note that for the endpoint logger, you can also pass constant parameters in more_ioc_params. We have provided this option to include parameters like Customer_ID.
Important points
You cannot and must not use our loggers on asymmetric functions. Doing so will create errors.
Define the Endpoint logger and Code logger in a single file, and import them from here always.
Define a constant name for insightsoncode's logger. We recommend you keep it as ioc_logger.
Note that Customer ID can be passed as a more_ioc_params to the endpoint function.
Remember that code_id should be unique at an endpoint level. i.e for a particular endpoint function, all the code blocks which are called so have distinct IDs.
Recommended Workflow
Discuss with your team and product leads thoroughly before deciding which endpoint and codepoints to log. Restrict and track only endpoints and code-blocks which are important. More data does not mean better data.
Create a json/csv file and map endpoint function names to endpoint IDs. This is more important for code blocks are they will usually be more in number.
For code IDs, follow one of two approaches
For functions common across many endpoints, give each tracked code-block a unique ID. For each endpoint, for all functions specific to that endpoint, give a unique code ID (which does not conflict with common function code IDs)
Create a unique ID for each code block across your code. This could be easier to maintain and track over time.
Implement the tracking mechanism in one-shot so as to keep the process simple.
Analyze your data at a weekly and monthly basis to check how your products are performing.
Adding logs inside functions
If there are some very special cases where the first two ways of logging values doesn't work, we have a third and final way of logging parameter values inside functions (endpoint and code blocks).
The general syntax will be
@logger(logger_params)
def your_function(ioc_logger, more_ioc_params, your_params):
special_logger_function(even_more_ioc_params)
<your code>
Since, there are three types of loggers, you can add logs three types of logs.
To add constant logs - ioc_logger.add_constant_logs(log1, log2)
To add endpoint logs - ioc_logger.add_endpoint_logs(endpointlog1)
To add code block logs - ioc_logger.add_code_logs(codelog1)
Note that add_code_logs can be used only inside @log_codepoint wrapped functions.
And it is recommended to use add_endpoint_logs, add_constant_logs inside @log_endpoint wrapped functions.
Email: insightsoncode@gmail.com