View Source LoggerJSON.Formatters.GoogleCloud (logger_json v6.0.3)

Custom Erlang's :logger formatter which writes logs in a structured format that can be consumed by Google Cloud Logger.

Even though the log messages on Google Cloud use LogEntry format, not all the fields are available in the structured payload. The fields that are available can be found in the special fields in structured payloads.

Formatter Configuration

The formatter can be configured with the following options:

  • :project_id (optional) - the Google Cloud project ID. This is required for correctly logging OpenTelemetry trace and span IDs so that they can be linked to the correct trace in Google Cloud Trace.

  • :service_context (optional) - a map with the following keys:

    • :service - the name of the service that is logging the message. Default: node().
    • :version - the version of the service that is logging the message.

For list of shared options see "Shared options" in LoggerJSON.

Metadata

You can extend the log entry with some additional metadata:application

  • user_id, identity_id, actor_id, account_id (ordered by precedence) - the ID of the user that is performing the action. It will be included along with the error report for Google Cloud Error Reporting;

For list of other well-known metadata keys see "Metadata" in LoggerJSON.

Examples

Regular message:

%{
  "logging.googleapis.com/operation" => %{"pid" => "#PID<0.228.0>"},
  "logging.googleapis.com/sourceLocation" => %{
    "file" => "/Users/andrew/Projects/os/logger_json/test/formatters/google_cloud_test.exs",
    "function" => "Elixir.LoggerJSON.Formatters.GoogleCloudTest.test logs an LogEntry of a given level/1",
    "line" => 44
  },
  "message" => %{"domain" => ["elixir"], "message" => "Hello"},
  "severity" => "NOTICE",
  "time" => "2024-04-11T21:32:46.957Z"
}

Exception message that will be recognized by Google Cloud Error Reporting:

%{
  "httpRequest" => %{
    "protocol" => "HTTP/1.1",
    "referer" => "http://www.example.com/",
    "remoteIp" => "",
    "requestMethod" => "PATCH",
    "requestUrl" => "http://www.example.com/",
    "status" => 503,
    "userAgent" => "Mozilla/5.0"
  },
  "logging.googleapis.com/operation" => %{"pid" => "#PID<0.250.0>"},
  "logging.googleapis.com/sourceLocation" => %{
    "file" => "/Users/andrew/Projects/os/logger_json/test/formatters/google_cloud_test.exs",
    "function" => "Elixir.LoggerJSON.Formatters.GoogleCloudTest.test logs exception http context/1",
    "line" => 301
  },
  "@type" => "type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent",
  "context" => %{
    "httpRequest" => %{
      "protocol" => "HTTP/1.1",
      "referer" => "http://www.example.com/",
      "remoteIp" => "",
      "requestMethod" => "PATCH",
      "requestUrl" => "http://www.example.com/",
      "status" => 503,
      "userAgent" => "Mozilla/5.0"
    },
    "reportLocation" => %{
      "filePath" => "/Users/andrew/Projects/os/logger_json/test/formatters/google_cloud_test.exs",
      "functionName" => "Elixir.LoggerJSON.Formatters.GoogleCloudTest.test logs exception http context/1",
      "lineNumber" => 301
    }
  },
  "domain" => ["elixir"],
  "message" => "Hello",
  "serviceContext" => %{"service" => "nonode@nohost"},
  "stack_trace" => "** (EXIT from #PID<0.250.0>) :foo",
  "severity" => "DEBUG",
  "time" => "2024-04-11T21:34:53.503Z"
}