Logging

The Descope backend SDKs can emit log messages to help you diagnose failed API calls, session validation errors, and configuration problems.

Support differs by language, and the SDKs do not share a common shape. Some take a log level, some take a logger object you supply.

SDKWhat you setLog levels
Node.jsA logger objectNone, so you filter inside the logger you supply
GoLogLevel, and optionally a Logger of your ownlogger.LogNone, logger.LogInfoLevel, and logger.LogDebugLevel
Rubylog_level, and optionally a logger of your owndebug, info, warn, error, fatal, and unknown
PHPdebug to true or falseNone

Enabling a Logger

The Node.js SDK takes a logger object rather than a log level. Pass it alongside projectId:

import DescopeClient from '@descope/node-sdk';

const descopeClient = DescopeClient({
  projectId: '__ProjectID__',
  logger: console,
});

During development you can pass console directly. To route messages into your own logging service, supply an object with debug, log, warn, and error methods:

const logger = {
  debug: (message, ...args) => myLogger.debug(message, ...args),
  log: (message, ...args) => myLogger.info(message, ...args),
  warn: (message, ...args) => myLogger.warn(message, ...args),
  error: (message, ...args) => myLogger.error(message, ...args),
};

const descopeClient = DescopeClient({
  projectId: '__ProjectID__',
  logger,
});

All four methods are required, which is why passing console works. The SDK calls error for failures, log for informational messages, and warn for non-fatal problems. Messages are emitted for session validation failures, refresh token validation failures, access key exchange failures, public key parsing errors, and license handshake problems.

The Go SDK takes a log level, and optionally a logger of your own. Set them on client.Config:

import (
    "github.com/descope/go-sdk/descope/client"
    "github.com/descope/go-sdk/descope/logger"
)

descopeClient, err := client.NewWithConfig(&client.Config{
    ProjectID: "__ProjectID__",
    LogLevel:  logger.LogDebugLevel,
})

Supported Log Levels

  • logger.LogNone logs nothing. This is the default.
  • logger.LogInfoLevel logs errors and informational messages.
  • logger.LogDebugLevel logs errors, informational messages, and debug detail.

Supplying Your Own Logger

If you leave Logger unset, the SDK writes to Go's log.Default(). To send messages elsewhere, provide any type with a Print(v ...any) method:

type myLogger struct{}

func (myLogger) Print(v ...any) {
    // forward to your logging library
}

descopeClient, err := client.NewWithConfig(&client.Config{
    ProjectID: "__ProjectID__",
    LogLevel:  logger.LogDebugLevel,
    Logger:    myLogger{},
})

The Ruby SDK takes a log level. Unlike every other Descope SDK, it logs by default at info:

require 'descope'

client = Descope::Client.new(
  project_id: '__ProjectID__',
  log_level: 'debug'
)

Log messages go to STDOUT, prefixed with the timestamp, severity, and your Project ID:

[2026-01-14 09:22:41 UTC] INFO PRID: __ProjectID__ Descope::Client: Initializing Descope API

Supported Log Levels

log_level accepts the names of Ruby's standard Logger levels: debug, info, warn, error, fatal, and unknown. An unrecognized value raises a NameError, so keep to that list.

The level is resolved in this order:

  1. The log_level option passed to Descope::Client.new
  2. The DESCOPE_LOG_LEVEL environment variable
  3. info, if neither is set

To minimize log output, override the default by setting the level explicitly:

client = Descope::Client.new(
  project_id: '__ProjectID__',
  log_level: 'error'
)

Supplying Your Own Logger

Passing a logger takes over completely. When you supply one, log_level is ignored and the level is whatever your logger is configured with:

require 'logger'

client = Descope::Client.new(
  project_id: '__ProjectID__',
  logger: Logger.new($stdout, level: Logger::WARN)
)

The PHP SDK takes a boolean. Set debug in the config array you pass to DescopeSDK:

require 'vendor/autoload.php';
use Descope\SDK\DescopeSDK;

$descopeSDK = new DescopeSDK([
    'projectId' => $_ENV['DESCOPE_PROJECT_ID'],
    'debug' => true,
]);

There are no levels. When debug is on, a failed POST, GET, or DELETE request to the Descope API is written to PHP's error log through error_log():

[04-Aug-2026 18:47:06 UTC] Descope SDK [POST] Error: HTTP Status Code: 400, Response: {"errorCode":"E061102","errorDescription":"One time code is invalid"}

Messages are prefixed with Descope SDK and tagged with the HTTP method, so you can filter for them. Because they go through error_log(), they land wherever your PHP installation sends error output: the path set by error_log in your php.ini, your web server's error log.

Enabling It Without Changing Code

You can also turn debug logging on with the DESCOPE_DEBUG environment variable, most reliably from a .env file:

.env
DESCOPE_DEBUG=true

The value must be the exact lowercase string true. 1, TRUE, and on are ignored. The SDK reads this from PHP's $_ENV superglobal, so a variable exported only into the process environment is not picked up unless your php.ini variables_order includes E, which it does not by default. Setting debug in the config array always takes precedence over the environment variable.

Additional Resources

Was this helpful?

On this page