Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Quick start
3.
Termination of the debugging session
4.
Abbreviating debugging commands
5.
Breakpoints
6.
Dynamic breakpoints
7.
Synchronous mode
8.
Logging from scripts
9.
Inspecting the program state with print and eval
10.
Frequently Asked Questions
10.1.
What is Redis?
10.2.
What is the usage of Redis?
10.3.
What is the meaning of Redis?
10.4.
What are the ways to interact with Redis?
10.5.
What language is Redis written in?
11.
Conclusion
Last Updated: Mar 27, 2024
Easy

Debugging Lua scripts in Redis

Author Manan Singhal
0 upvote

Introduction

Starting with version 3.2, Redis comes with a full Lua debugger that can be used to make writing complex Redis scripts a lot easier.

The LDB debugger for Redis Lua includes the following significant features:

  • It's a remote debugger that uses a server-client approach. The default client is redis-cli, while the Redis server serves as the debugging server. On the other hand, other clients can be created by following the server's primary protocol.
     
  • Every new debugging session is considered to be a forked session by default. It means that the server does not block while the Redis Lua script is being debugged, and it can be used for development or to run many debugging sessions in parallel. This also implies that all modifications are rolled back after the script debugging session is completed, allowing you to start a new debugging session with the same Redis data set.
     
  • On-demand, an alternate synchronous (non-forked) debugging approach is offered to keep changes to the dataset. The server blocks in this mode for the duration of the debugging session.
     
  • Step-by-step execution is supported.
     
  • Breakpoints can be static or dynamic.
     
  • Logging the debugged script into a debugger console is supported.
     
  • Variables in Lua are examined.
     
  • The script's Redis commands are being traced.
     
  • Redis and Lua's values are printed nicely.
     
  • Infinite loops and detection of extended execution times, simulating a breakpoint.

Quick start

To use redis-cli to start an afresh debugging session, perform the following:

Write your script in a file using your favorite editor. Let's pretend you're editing your /tmp/script.lua Redis Lua script.

Begin your debugging session by:

./redis-cli --ldb --eval /tmp/script.lua


Note that you can supply key names and arguments to redis-cli using the —eval option, separated by a comma, as seen in the below example:

./redis-cli --ldb --eval /tmp/script.lua mykey some key , arg1 arg


You'll enter a special mode in which redis-cli stops accepting normal inputs and instead produces a help page and sends the debugging commands to Redis unchanged.

Only the following commands are not given to the Redis debugger:

  • quit: This command will end the debugging session. It's the same as removing all breakpoints and rerunning the debugging command. Furthermore, the command will terminate redis-cli.
  • Restart: the debugging session will begin with the new version of the script loaded from the file. So, after some debugging, a typical debugging cycle entails modifying the script and then calling restart to resume debugging with the new script changes.
  • help: this command is passed to the debugger, which prints a list of commands such as
     
lua debugger> help
Redis Lua debugger help:
[h]elp               Show this help.
[n]ext               Alias for step.
[c]continue          Run till the next breakpoint.
[s]tep               Run current line and then stop again.
[w]hole              List all source code. Alias for 'list 1 1000000'.
[p]rint              Show all the local variables.
[b]reak              Show all breakpoints.
[t]race              Show a backtrace.
[l]list              List a source code around the current line.
[b]reak 0            Remove all breakpoints.
[r]edis <cmd>        Execute a Redis command.
[b]reak <line>       Add a breakpoint to a particular line.
[e]eval <code>       Execute some Lua code.
[l]list [line]       List the source code around the line.
                    where line = 0 means current position.
[a]abort             Stop the execution of a script and in sync
                    mode dataset changes will be retained.
[p]rint <var>        Show the value of some specified variable.
                    It can also show global vars KEYS and ARGV.
[b]reak -<line>      Remove breakpoint from a particular line.
[m]axlen [len]       Trim logged Redis replies and Lua var dumps to learn.
                    Specifying zero as <len> means unlimited.

Debugger functions that you can call from Lua scripts:
redis.debug()        Produce logs in the console.
redis.breakpoint() would Stop execution if there were a breakpoint in the
                    next line of code.


When you first start the debugger, it will be in stepping mode. Before executing the script, pause at the first line that accomplishes something before running the script.

You normally call step from here to execute the line and go on to the next one. While you step, Redis will display all of the server's commands, as shown in the following example:

* Stopped at 1, stop reason = step over
-> 1   redis.call('ping')
lua debugger> step
<redis> ping
<reply> "+PONG"
* Stopped at 2, stop reason = step over


The <reply> and <redis> lines show the command issued by the line just executed and the server's response. It is worth noting that this happens in stepping mode. To avoid too much output, if you continue to execute the script until the next breakpoint, commands will not be spewed on the screen.

Termination of the debugging session

It finishes when the scripts terminate naturally, and redis-cli returns to its non-debugging mode. As usual, you can restart the session with the restart command.

Another option to end a debugging session is to terminate redis-cli by hitting Ctrl+C manually. Any event that breaks the connection between redis-cli and the redis-server will also cause the debugging session to be interrupted.

When the server is shut down, all forked debugging sessions are stopped.

Abbreviating debugging commands

Debugging can be a tedious process. As a result, each Redis debugger command begins with a different character, and you can refer to the command by its single beginning character.

So, instead of typing step, you might type s.

Breakpoints

As mentioned in the online instructions, adding and removing breakpoints is simple. Put a breakpoint in lines 1, 2, 3, 4, type b 1 2 3 4. All breakpoints are removed with the command b 0. Selected breakpoints can be eliminated by bypassing the line containing the breakpoint we wish to remove, but preceded by a minus sign as an input. For example, they remove the breakpoint from line 3 with b -3.

Breakpoints will not operate if they are placed on lines that Lua never runs, such as declarations of local variables or comments. The breakpoint will be added, but the program will never stop because this part of the script will never be executed.

Dynamic breakpoints

Breakpoints can be added to specified lines with the breakpoint command. However, there are occasions when we want the application to come to a halt only when anything unusual occurs. You can do this by using the redis.breakpoint() function in your Lua script. It simulates a breakpoint that will be performed when called.

if counter > 10 then redis.breakpoint() end


When debugging, this functionality comes in handy because it allows us to avoid having to run the script several times until a specific condition is met.

Synchronous mode

Default LDB employs split sessions with rollback of all data changes made by the script while it is being debugged, as previously mentioned. Determinism is usually a useful thing to have when debugging because it allows you to start new debugging sessions without having to restore the database information to its previous state.

However, if you want to track specific defects, you might want to note the changes made to the key area during each debugging session. When this is a good idea, start the debugger with a special option in redis-cli called ldb-sync-mode.

./redis-cli --ldb-sync-mode --eval /tmp/script.lua


The abort command can be used in this special mode to halt the script while making modifications to the dataset this is not the same as simply terminating the debugging session. The script will be fully performed, and the session will be canceled if you interrupt redis-cli. Instead, you can use abort to stop the script in the middle of its execution and start an afresh debugging session if necessary.

Logging from scripts

The redis.debug() command is a strong debugging capability that may be used to log things into the debug console from within a Redis Lua script:

lua debugger> list
-> 1   local a = {1,2,3}
  2   local b = false
  3   redis.debug(a,b)
lua debugger> continue
<debug> line 3: {1; 2; 3}, false


Redis.debug() has no effect if the script is run outside of a debugging session. The function accepts several inputs, separated in the output by a comma and a space. Tables and stacked tables are shown correctly for the programmer debugging the script to see the values easily.

Inspecting the program state with print and eval

redis.debug() function is used to report results directly from within a Lua script, it is frequently beneficial to examine a program's local variables while stepping or stopping at a breakpoint.

The print command accomplishes this by performing a lookup in the call frames from the current one through the previous ones, up to the top level. This means that we can use print foo to look at the value of foo in the context of the calling function, even if we're in a nested function inside a Lua script. When a print is called without a variable name, it prints all variables and their values.

The eval command executes tiny Lua scripts outside the current call frame's context. On the other hand, this command can be used to test Lua routines.

lua debugger> e redis.sha1hex('foo')
<retval> "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"

Frequently Asked Questions

What is Redis?

Redis is a key-value data storage and cache that is open-source, and it is also known as a data structure server because the keys include hashes, sets, lists, sorted sets, and strings.

What is the usage of Redis?

Redis is a key-value store database that may be used as a NoSQL database or a memory cache store to boost performance when delivering data from system memory.

What is the meaning of Redis?

Redis stands for REmote DIctionary Server.

What are the ways to interact with Redis?

After the server has been installed, you can either use the Redis Client given by the Redis installation or open a command prompt and type the following command: redis-cli

What language is Redis written in?

Redis is a cache solution and session management system developed in ANSI C. It generates one-of-a-kind keys for storing data.

Conclusion

In this article, we have learned the debugging of Lua scripts in Redis. We hope that this blog will help you understand the concept of Lua scripts, and if you would like to learn more about it, check out our other blogs on redismongo-dBdatabase, and operational databases.

Attempt our Online Mock Test Series on Coding Ninjas Studio now!

Happy Coding!

Live masterclass