module GoogleCloudRun

Constants

VERSION

Public Class Methods

default_service_account_email() click to toggle source

default_service_account_email returns the default service account's email from the metadata server

# File lib/google_cloud_run/util.rb, line 84
def self.default_service_account_email
  return ENV["GOOGLE_SERVICE_ACCOUNT_EMAIL"] unless ENV["GOOGLE_SERVICE_ACCOUNT_EMAIL"].blank?
  return "123456789-compute@developer.gserviceaccount.com" if Rails.env.test?

  @default_service_account_email ||= begin
      creds = parse_google_application_credentials
      return creds["email_client"] unless creds["client_email"].blank?

      uri = URI.parse("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email")
      request = Net::HTTP::Get.new(uri)
      request["Metadata-Flavor"] = "Google"

      req_options = {
        open_timeout: 5,
        read_timeout: 5,
        max_retries: 2,
      }

      response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
        http.request(request)
      end

      raise "unknown google default service account" if response.code.to_i != 200

      response.body.strip
    end
end
exception_interceptor(request, exception) click to toggle source
# File lib/google_cloud_run/exceptions.rb, line 2
def self.exception_interceptor(request, exception)

  # ref: https://cloud.google.com/error-reporting/reference/rest/v1beta1/projects.events/report#reportederrorevent

  return false if Rails.application.config.google_cloudrun.silence_exceptions.any? { |e| exception.is_a?(e) }

  l = ErrorReportingEntry.new
  l.project_id = GoogleCloudRun.project_id
  l.severity = Rails.application.config.google_cloudrun.error_reporting_exception_severity
  l.exception = exception
  l.request = request

  l.context_service = GoogleCloudRun.k_service
  l.context_version = GoogleCloudRun.k_revision

  # attach user to entry
  p = Rails.application.config.google_cloudrun.error_reporting_user
  if p && p.is_a?(Proc)
    begin
      l.user = p.call(request)
    rescue
      # TODO ignore or log?
    end
  end

  Rails.application.config.google_cloudrun.out.puts l.to_json
  Rails.application.config.google_cloudrun.out.flush

  return true
end
k_revision() click to toggle source
# File lib/google_cloud_run/util.rb, line 11
def self.k_revision
  @k_revision ||= begin
      revision = ENV.fetch("K_REVISION", "")
      service = ENV.fetch("K_SERVICE", "")
      revision.delete_prefix(service + "-")
    end
end
k_service() click to toggle source
# File lib/google_cloud_run/util.rb, line 5
def self.k_service
  @k_service ||= begin
      ENV.fetch("K_SERVICE", "")
    end
end
parse_google_application_credentials() click to toggle source
# File lib/google_cloud_run/util.rb, line 112
def self.parse_google_application_credentials
  file = ENV["GOOGLE_APPLICATION_CREDENTIALS"]
  return {} if file.blank?
  JSON.parse(File.read(file)).deep_stringify_keys
rescue
  return {}
end
parse_trace_context(raw) click to toggle source

parse_trace_context parses header X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE

# File lib/google_cloud_run/util.rb, line 21
def self.parse_trace_context(raw)
  raw&.strip!
  return nil, nil, nil if raw.blank?

  trace = nil
  span = nil
  sample = nil

  first = raw.split("/")
  if first.size > 0
    trace = first[0]
  end

  if first.size > 1
    second = first[1].split(";")

    if second.size > 0
      span = second[0]
    end

    if second.size > 1
      case second[1].delete_prefix("o=")
      when "1"; sample = true
      when "0"; sample = false
      end
    end
  end

  return trace, span, sample
end
project_id() click to toggle source

project_id returns the current Google project id from the metadata server

# File lib/google_cloud_run/util.rb, line 54
def self.project_id
  return ENV["GOOGLE_PROJECT_ID"] unless ENV["GOOGLE_PROJECT_ID"].blank?
  return "dummy-project" if Rails.env.test?

  @project_id ||= begin
      creds = parse_google_application_credentials
      return creds["project_id"] unless creds["project_id"].blank?

      uri = URI.parse("http://metadata.google.internal/computeMetadata/v1/project/project-id")
      request = Net::HTTP::Get.new(uri)
      request["Metadata-Flavor"] = "Google"

      req_options = {
        open_timeout: 5,
        read_timeout: 5,
        max_retries: 2,
      }

      response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
        http.request(request)
      end

      raise "unknown google cloud project" if response.code.to_i != 200

      response.body.strip
    end
end