{# The final Javascript/Typescript code is autogenerated, but this
Jinja2 template is not. Please file bugs! #}
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// AUTOGENERATED BY glean_parser v{{ parser_version }}. DO NOT EDIT. DO NOT COMMIT.

// This requires `uuid` and `mozlog` libraries to be in the environment
{% if lang == "typescript" %}
// @types/uuid and mozlog types definitions are required in devDependencies
// for the latter see https://github.com/mozilla/fxa/blob/85bda71cda376c417b8c850ba82aa14252208c3c/types/mozlog/index.d.ts
{% endif %}
{% if module_spec == "commonjs" %}
const uuidv4 = require('uuid').v4;
const mozlog = require('mozlog');
{% else %}
import { v4 as uuidv4 } from 'uuid';
import mozlog{% if lang == "typescript" %}, { Logger }{% endif %} from 'mozlog';
{% endif %}

const GLEAN_EVENT_MOZLOG_TYPE = 'glean-server-event';
{% if lang == "typescript" %}
type LoggerOptions = { app: string; fmt?: 'heka' };
{% if event_metric_exists %}
type Event = {
  category: string;
  name: string;
  extra?: Record<string, any>;
  timestamp?: number;
};
{% endif %}
{% endif %}

let _logger{% if lang == "typescript" %}: Logger{% endif %};

{% for ping, metrics_by_type in pings.items() %}
class {{ ping|event_class_name(metrics_by_type) }} {
  {% if lang == "typescript" %}
  _applicationId: string;
  _appDisplayVersion: string;
  _channel: string;
  {% endif %}
  /**
   * Create {{ ping|event_class_name(metrics_by_type) }} instance.
   *
   * @param {string} applicationId - The application ID.
   * @param {string} appDisplayVersion - The application display version.
   * @param {string} channel - The channel.
   * @param {LoggerOptions} logger_options - The logger options.
   */
  {% if lang == "typescript" %}
  constructor(
    applicationId: string,
    appDisplayVersion: string,
    channel: string,
    logger_options: LoggerOptions
  ) {
  {% else %}
  constructor(applicationId, appDisplayVersion, channel, logger_options) {
  {% endif %}
    this._applicationId = applicationId;
    this._appDisplayVersion = appDisplayVersion;
    this._channel = channel;

    if (!_logger) {
      // append '-glean' to `logger_options.app` to avoid collision with other loggers and double logging
      logger_options.app = logger_options.app + '-glean';
      // set the format to `heka` so messages are properly ingested and decoded
      logger_options.fmt = 'heka';
      {% if lang == "typescript" %}
      // mozlog types declaration requires a typePrefix to be passed when creating a logger
      // we don't want a typePrefix, so we pass `undefined`
      _logger = mozlog(logger_options)(undefined);
      {% else %}
      _logger = mozlog(logger_options)();
      {% endif %}
    }
  }
  {% if 'event' in metrics_by_type %}
  #record({
  {% else %}
  /**
   * Record and submit a server event object.
   * Event is logged using internal mozlog logger.
   *
   * @param {string} user_agent - The user agent.
   * @param {string} ip_address - The IP address. Will be used to decode Geo
   *                              information and scrubbed at ingestion.
   {% for metric_type, metrics in metrics_by_type.items() %}
   {% for metric in metrics %}
   * @param { {{-metric|js_metric_type-}} } {{ metric|metric_argument_name }} - {{ metric.description|clean_string }}.
   {% endfor %}
   {% endfor %}
   */
  record({
  {% endif %}
    user_agent,
    ip_address,
    {% for metric_type, metrics in metrics_by_type.items() %}
    {% if metric_type != 'event' %}
    {% for metric in metrics %}
    {{ metric|metric_argument_name }},
    {% endfor %}
    {% endif %}
    {% endfor %}
    {% if 'event' in metrics_by_type %}
    event,
    {% endif %}
  {% if lang == "typescript" %}
  }: {
    user_agent: string;
    ip_address: string;
    {% for metric_type, metrics in metrics_by_type.items() %}
    {% if metric_type != 'event' %}
    {% for metric in metrics %}
    {{ metric|metric_argument_name }}: {{ metric|js_metric_type }};
    {% endfor %}
    {% endif %}
    {% endfor %}
    {% if 'event' in metrics_by_type %}
    event: Event;
    {% endif %}
  {% endif %}
  }) {
    const now = new Date();
    const timestamp = now.toISOString();
    {% if 'event' in metrics_by_type %}
    event.timestamp = now.getTime();
    {% endif %}
    const eventPayload = {
      metrics: {
        {% for metric_type, metrics in metrics_by_type.items() %}
        {% if metric_type != 'event' %}
        {{ metric_type }}: {
          {% for metric in metrics %}
          '{{ metric|metric_name }}': {{ metric|metric_argument_name }},
          {% endfor %}
        },
        {% endif %}
        {% endfor %}
      },
      {% if 'event' in metrics_by_type %}
      events: [event],
      {% endif %}
      ping_info: {
        seq: 0, // this is required, however doesn't seem to be useful in server context
        start_time: timestamp,
        end_time: timestamp,
      },
      // `Unknown` fields below are required in the Glean schema, however they are not useful in server context
      client_info: {
        telemetry_sdk_build: 'glean_parser v{{ parser_version }}',
        first_run_date: 'Unknown',
        os: 'Unknown',
        os_version: 'Unknown',
        architecture: 'Unknown',
        app_build: 'Unknown',
        app_display_version: this._appDisplayVersion,
        app_channel: this._channel,
      },
    };
    const eventPayloadSerialized = JSON.stringify(eventPayload);

    // This is the message structure that Decoder expects: https://github.com/mozilla/gcp-ingestion/pull/2400
    const ping = {
      document_namespace: this._applicationId,
      document_type: '{{ ping }}',
      document_version: '1',
      document_id: uuidv4(),
      user_agent: user_agent,
      ip_address: ip_address,
      payload: eventPayloadSerialized,
    };

    // this is similar to how FxA currently logs with mozlog: https://github.com/mozilla/fxa/blob/4c5c702a7fcbf6f8c6b1f175e9172cdd21471eac/packages/fxa-auth-server/lib/log.js#L289
    _logger.info(GLEAN_EVENT_MOZLOG_TYPE, ping);
  }
  {% if 'event' in metrics_by_type %}
  {% for event in metrics_by_type["event"] %}
  /**
   * Record and submit a {{ event.category }}_{{ event.name }} event:
   * {{ event.description|clean_string }}
   * Event is logged using internal mozlog logger.
   *
   * @param {string} user_agent - The user agent.
   * @param {string} ip_address - The IP address. Will be used to decode Geo
   *                              information and scrubbed at ingestion.
   {% for metric_type, metrics in metrics_by_type.items() %}
   {% if metric_type != 'event' %}
   {% for metric in metrics %}
   * @param { {{-metric|js_metric_type-}} } {{ metric|metric_argument_name }} - {{ metric.description|clean_string }}.
   {% endfor %}
   {% endif %}
   {% endfor %}
   {% if event.extra_keys %}
   {% for extra, metadata in event.extra_keys.items() %}
   * @param { {{-metadata.type-}} } {{ extra }} - {{ metadata.description|clean_string }}.
   {% endfor %}
   {% endif %}
   */
  {{ event|event_metric_record_function_name }}({
    user_agent,
    ip_address,
    {% for metric_type, metrics in metrics_by_type.items() %}
    {% if metric_type != 'event' %}
    {% for metric in metrics %}
    {{ metric|metric_argument_name }},
    {% endfor %}
    {% endif %}
    {% endfor %}
    {% for extra, metadata in event.extra_keys.items() %}
    {{ extra }},
    {% endfor %}
  {% if lang == "typescript" %}
  }: {
    user_agent: string;
    ip_address: string;
    {% for metric_type, metrics in metrics_by_type.items() %}
    {% if metric_type != 'event' %}
    {% for metric in metrics %}
    {{ metric|metric_argument_name }}: {{ metric|js_metric_type }};
    {% endfor %}
    {% endif %}
    {% endfor %}
    {% for extra, metadata in event.extra_keys.items() %}
    {{ extra }}: {{metadata.type}};
    {% endfor %}
  {% endif %}
  }) {
    const event = {
      category: '{{ event.category }}',
      name: '{{ event.name }}',
      {% if event.extra_keys %}
      extra: {
        {% for extra, metadata in event.extra_keys.items() %}
        {{ extra }}: String({{ extra }}),
        {% endfor %}
      },
      {% endif %}
    };
    this.#record({
      user_agent,
      ip_address,
      {% for metric_type, metrics in metrics_by_type.items() %}
      {% if metric_type != 'event' %}
      {% for metric in metrics %}
      {{ metric|metric_argument_name }},
      {% endfor %}
      {% endif %}
      {% endfor %}
      event,
    });
  }
  {% endfor %}
  {% endif %}
}
{% endfor %}
{% for ping, metrics_by_type in pings.items() %}

/**
 * Factory function that creates an instance of Glean Server Event Logger to
 * record `{{ ping }}` ping events.
 * @param {string} applicationId - The application ID.
 * @param {string} appDisplayVersion - The application display version.
 * @param {string} channel - The channel.
 * @param {Object} logger_options - The logger options.
 * @returns {EventsServerEventLogger} An instance of EventsServerEventLogger.
 */
{% if module_spec == "commonjs" %}
module.exports.{{ ping|factory_method(metrics_by_type) }} = function ({
{% else %}
export const {{ ping|factory_method(metrics_by_type) }} = function ({
{% endif %}
  applicationId,
  appDisplayVersion,
  channel,
  logger_options,
{% if lang == "typescript" %}
}: {
  applicationId: string;
  appDisplayVersion: string;
  channel: string;
  logger_options: LoggerOptions;
{% endif %}
}) {
  return new {{ ping|event_class_name(metrics_by_type) }}(
    applicationId,
    appDisplayVersion,
    channel,
    logger_options
  );
};
{% endfor %}
