Skip to main content
Version: 4.3.1

Track Function Calls

Function tracking is the ability to monitor code-level individual functions during runtime for any potential errors. SDK provides two different ways to activate function tracking.

  1. By using the Fn.call() API to invoke code level function, Finotes SDK will be able to monitor and report runtime issues with detailed data points.
  2. By using the Fn.start() and Fn.end() APIs within the function definition, SDK will be able to monitor and report runtime issues with detailed data points.

Regular function call


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

String userName = getUserNameFromDb("123-sd-12");

}

public String getUserNameFromDb(String userId){
String userName = User.findById(userId).getName();
return userName;
}

Method 1 - Using Fn.call() API


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

String userName = (String) Fn.call("getUserNameFromDb", this, "123-sd-12");
}

@Observe
public String getUserNameFromDb(String userId){
String userName = User.findById(userId).getName();
return userName;
}

Once Fn.call() API is invoked, errors like NULL return value, wrong return value, exceptions and function execution delays will be captured and reported to the dashboard.

Things to Note:

  1. Replace the traditional method of function invocation with the SDK based mechanism using Fn.call() API.
  2. Make sure that the function definition is annotated using @Observe.
  3. The access modifier of the function should be set to public.
  4. Function parameters should be of an Object type. primitive data types are not supported by Fn.call() API.
  5. By default, SDK monitors for NULL return value, negative return value and if the function takes more than 1000 milliseconds to execute.
  6. Please refer to the @Observe section to learn more.
  7. Exceptions thrown during function execution will be automatically captured and reported.
  8. The function parameters that were passed to it during its invocation will be tagged along with the issue in the Finotes dashboard if any are raised.

Method 2 - Using Fn.start() and Fn.end() APIs


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

String userName = getUserNameFromDb("123-sd-12");
}

@Observe
public String getUserNameFromDb(String userId){
Fn.start(new Object(){}, userId);

String userName = User.findById(userId).getName();

return Fn.end(new Object(){}, userName);
}

Once Fn.start() and Fn.end() APIs are added to a function definition, errors like NULL return value, wrong return value and function execution delays will be captured and reported to the dashboard.

Things to Note:

  1. It is mandatory to call both Fn.start() and Fn.end() functions at the start and end of your function definition.
  2. The first parameter of both the APIs should be new Object(){}.
  3. Make sure that the function is annotated using @Observe.
  4. This method of function tracking supports primitive function parameters as well.
  5. By default, SDK monitors for NULL return value, negative return value in case of Boolean and if the function takes more than 1000 milliseconds to execute.
  6. Please find the @Observe section to learn more.
  7. Use Fn.reportException API to report exceptions thrown during function invocation.
  8. The function parameters that are passed to Fn.start() during its invocation will be tagged along with issues reported in the Finotes dashboard.
  9. In case there is no return value, just call Fn.end(new Object(){}) at the end of the function definition.

@Observe fields

It is mandatory to annotate every code level function that is to be tracked by the SDK with @Observe annotation. @Observe annotation allows customization in the way issues are reported during a tracked function execution.

Function ID

In case of function overloading, this field is mandatory. ID field gives the ability for the SDK to track functions in case of function overloading. In the case of tracking such functions, use the id field to assign a unique name for the functions.

Method 1 - Usage of function ID when using Fn.call() API

If the id field is set, make sure to mandatorily pass the id and not the function name in the Fn.call() API.

Function Overriding with Fn.call


@Override
protected void onCreate(Bundle savedInstanceState) {

// Function name itself is provided as function getUserNameFromDb(String userId)
// doesnt have any explicit id in its @Observe annotation
Fn.call("getUserNameFromDb", this, "123-sd-12");

// ID 'getUserNameFromDBWithEmailAndToken' is provided as function
// getUserNameFromDb(String email, String token)
// does have an explicit id in its @Observe annotation
Fn.call("getUserNameFromDBWithEmailAndToken",
this, "support@finotes.com", "RENKDS123S");
}

@Observe
public String getUserNameFromDb(String userId){
}

@Observe(id = "getUserNameFromDBWithEmailAndToken")
public String getUserNameFromDb(String email, String token){
}

Method 2 - Usage of function ID when using Fn.start() and Fn.end() APIs

In case of function overloading, simply set a unique name to the id field. This will allow the SDK to track overloaded functions.

Function Overriding with Fn.start and Fn.end


@Override
protected void onCreate(Bundle savedInstanceState) {

// No change needed here
getUserNameFromDb("123-sd-12");

// No change needed here
getUserNameFromDb("support@finotes.com", "RENKDS123S");
}

@Observe
public String getUserNameFromDb(String userId){
Fn.start(new Object(){}, userId);

String userName = User.findById(userId).getName();

return Fn.end(new Object(){}, userName);
}

//Set a unique name to the functions using "id" field
@Observe(id = "getUserNameFromDBWithEmailAndToken")
public String getUserNameFromDb(String email, String token){
Fn.start(new Object(){}, email, token);

String userName = User.findByToken(token).getName();

return Fn.end(new Object(){}, userName);
}

Expected Execution Time

By default, if a tracked function takes more than 1000 milliseconds to execute, an issue report will be sent to the dashboard.
Set a custom expected execution time using the field expectedExecutionTime in @Observe annotation.

Once this field is set with a custom value, and the corresponding function execution takes more than the set amount of time, an issue report will be sent to the dashboard.

Expect Null

By default, if a tracked function returns NULL during its execution, an issue report will be sent to the dashboard.
Set the field expectNull to 'true' to prevent SDK from reporting NULL issues.

Setting expectNull using @Observe annotation


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

...
}

@Observe(expectNull = true)
public String getUserNameFromDb(String userId){
...
}

Expected Boolean Value

By default, if a tracked function with return type Boolean returns 'false' during its execution, an issue report will be sent to the dashboard.
Instead if an issue report needs to be raised if return value is 'true', set the field expectedBooleanValue to 'false'.

Setting expectedBooleanValue using @Observe annotation


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

...
}

@Observe(expectedBooleanValue = false)
public Boolean verifyUser(String userId){
...
}

Set Range Check of Return value

If the tracked function returns a Number type (e.g. Integer, Double, Float). Use min, max, minDecimal, maxDecimal fields to set expected upper and lower limits of return value.
Once set, if the function returns a value outside the min and max values, corresponding issue report will be raised to the Finotes dashboard.

**Setting range check of return value using @Observe annotation@Override


protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

...
}

@Observe(min = 200)
public Integer walletBalanceOfUser(String userId){
...
}

@Observe(min = 10, max = 3000)
public Integer amountTypedByUserForWalletRefill(String userId){
...
}

@Observe(minDecimal = 10)
public Double getTaxComponentForProduct(String productId){
...
}

@Observe(minDecimal = 10, maxDecimal = 20)
public Double calculateFinalTaxPercentageCollected(String userId){
...
}

Severity

By default, issues raised from a tracked function will have the default severity level - MAJOR. Use severity field to change the value. Available severity levels are MINOR, MAJOR, FATAL

Setting Severity using @Observe annotation


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

...
}

@Observe(severity = Severity.MINOR)
public String getUserNameFromDb(String userId){
...
}