.Output
```
-Serialize output: Tmp-String-0 = \"This is a string\"Tmp-String-0 = \"This is another one\"
+Serialize output: Tmp-String-0 = "\"This is a string\", Tmp-String-0 = \"This is another one\""
```
=== %randstr( ...)
toupper of caipirinha is CAIPIRINHA
```
-== String Conversion
+== Data Conversion
=== %base64.encode( ... )
"next week Monday", or "start of next month". The `%nexttime(...)`
expansion above should be used for those time operations.
+== Logging
+
+=== %log.debug(<string>)
+
+Logs a message at a DEBUG level. This function returns nothing.
+
+[source,unlang]
+----
+%log.debug("Now processing %interpreter(...filename):%interpreter(...line)")
+----
+
+The DEBUG messages are printed only when the server has the debug flag set.
+
+=== %log.info(<string>)
+
+Logs a message at a INFO level. This function returns nothing.
+
+[source,unlang]
+----
+%log.info("Doing something useful now")
+----
+
+The INFO messages are always logged. We suggest using these messages
+only to log special or unusual events. Producing multiple log
+messages per packet is not recommended, and can have a surprisingly
+large (and negative) impact on performance.
+
== Deprecated or removed Expansions.
=== %expr(<string>)
return XLAT_ACTION_DONE;
}
+static xlat_arg_parser_t const xlat_func_log_arg[] = {
+ { .concat = true, .type = FR_TYPE_STRING },
+ XLAT_ARG_PARSER_TERMINATOR
+};
+
+/** Log something at INFO level.
+ *
+ * Example:
+@verbatim
+%log("foo") == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
+@endverbatim
+ *
+ * @ingroup xlat_functions
+ */
+static xlat_action_t xlat_func_log_info(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+ UNUSED xlat_ctx_t const *xctx,
+ request_t *request, fr_value_box_list_t *args)
+{
+ fr_value_box_t *vb;
+
+ XLAT_ARGS(args, &vb);
+
+ if (!vb) return XLAT_ACTION_DONE;
+
+ RINFO("%s", vb->vb_strvalue);
+
+ return XLAT_ACTION_DONE;
+}
+
+
+/** Log something at DEBUG level.
+ *
+ * Example:
+@verbatim
+%log.debug("foo") == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
+@endverbatim
+ *
+ * @ingroup xlat_functions
+ */
+static xlat_action_t xlat_func_log_debug(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+ UNUSED xlat_ctx_t const *xctx,
+ request_t *request, fr_value_box_list_t *args)
+{
+ fr_value_box_t *vb;
+
+ XLAT_ARGS(args, &vb);
+
+ if (!vb) return XLAT_ACTION_DONE;
+
+ RDEBUG("%s", vb->vb_strvalue);
+
+ return XLAT_ACTION_DONE;
+}
+
+
static xlat_arg_parser_t const xlat_func_map_arg[] = {
{ .required = true, .concat = true, .type = FR_TYPE_STRING },
XLAT_ARG_PARSER_TERMINATOR
XLAT_REGISTER_ARGS("debug", xlat_func_debug, FR_TYPE_INT8, xlat_func_debug_args);
XLAT_REGISTER_ARGS("debug_attr", xlat_func_debug_attr, FR_TYPE_NULL, xlat_func_debug_attr_args);
XLAT_REGISTER_ARGS("immutable", xlat_func_immutable_attr, FR_TYPE_NULL, xlat_func_immutable_attr_args);
+ XLAT_REGISTER_ARGS("log.debug", xlat_func_log_debug, FR_TYPE_NULL, xlat_func_log_arg);
+ XLAT_REGISTER_ARGS("log.info", xlat_func_log_info, FR_TYPE_NULL, xlat_func_log_arg);
XLAT_REGISTER_ARGS("nexttime", xlat_func_next_time, FR_TYPE_UINT64, xlat_func_next_time_args);
XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, FR_TYPE_STRING, xlat_func_pairs_args);
XLAT_REGISTER_ARGS("subst", xlat_func_subst, FR_TYPE_STRING, xlat_func_subst_args);