-- Query generated by: sql/telemetry_derived/clients_daily_histogram_aggregates_v1.sql.py --agg-type histograms
CREATE TEMP FUNCTION udf_aggregate_json_sum(histograms ARRAY<STRING>) AS (
  ARRAY(
    SELECT AS STRUCT
      FORMAT('%d', values_entry.key) AS key,
      SUM(values_entry.value) AS value
    FROM
      UNNEST(histograms) AS histogram,
      UNNEST(mozfun.hist.extract(histogram).values) AS values_entry
    WHERE
      histogram IS NOT NULL
    GROUP BY
      values_entry.key
    ORDER BY
      values_entry.key
  )
);

WITH valid_build_ids AS (
  SELECT DISTINCT
    (build.build.id) AS build_id
  FROM
    `moz-fx-data-shared-prod.telemetry.buildhub2`
),
filtered AS (
  SELECT
    *,
    SPLIT(application.version, '.')[OFFSET(0)] AS app_version,
    DATE(submission_timestamp) AS submission_date,
    normalized_os AS os,
    application.build_id AS app_build_id,
    normalized_channel AS channel
  FROM
    `moz-fx-data-shared-prod.telemetry_stable.main_v5`
  INNER JOIN
    valid_build_ids
    ON (application.build_id = build_id)
  WHERE
    DATE(submission_timestamp) = @submission_date
    AND normalized_channel IN ("release", "beta", "nightly")
    AND client_id IS NOT NULL
),
sampled_data AS (
  SELECT
    *
  FROM
    filtered
  WHERE
    channel IN ("nightly", "beta")
    OR (channel = "release" AND os != "Windows")
    OR (channel = "release" AND os = "Windows" AND MOD(sample_id, @sample_size) = 0)
),
histograms AS (
  SELECT
    submission_date,
    sample_id,
    client_id,
    os,
    app_version,
    app_build_id,
    channel,
    ARRAY<
      STRUCT<
        metric STRING,
        metric_type STRING,
        process STRING,
        value STRING,
        bucket_range STRUCT<first_bucket INT64, last_bucket INT64, num_buckets INT64>
      >
    >[
      (
        'apz_zoom_pinchsource',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.apz_zoom_pinchsource,
        (1, 5, 6)
      ),
      (
        'checkerboard_duration',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.checkerboard_duration,
        (1, 100000, 50)
      ),
      (
        'checkerboard_peak',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.checkerboard_peak,
        (1, 66355200, 50)
      ),
      (
        'checkerboard_potential_duration',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.checkerboard_potential_duration,
        (1, 1000000, 50)
      ),
      (
        'checkerboard_severity',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.checkerboard_severity,
        (1, 1073741824, 50)
      ),
      (
        'composite_frame_roundtrip_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.composite_frame_roundtrip_time,
        (1, 1000, 50)
      ),
      (
        'composite_swap_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.composite_swap_time,
        (1, 1000, 50)
      ),
      (
        'composite_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.composite_time,
        (1, 1000, 50)
      ),
      (
        'compositor_animation_duration',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_duration,
        (1, 20000, 50)
      ),
      (
        'compositor_animation_max_contiguous_drops_apz',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_max_contiguous_drops_apz,
        (1, 7200, 50)
      ),
      (
        'compositor_animation_max_contiguous_drops_chrome',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_max_contiguous_drops_chrome,
        (1, 7200, 50)
      ),
      (
        'compositor_animation_max_contiguous_drops_content',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_max_contiguous_drops_content,
        (1, 7200, 50)
      ),
      (
        'compositor_animation_max_layer_area',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_max_layer_area,
        (1, 8294400, 50)
      ),
      (
        'compositor_animation_throughput_apz',
        'histogram-linear',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_throughput_apz,
        (1, 1500, 50)
      ),
      (
        'compositor_animation_throughput_chrome',
        'histogram-linear',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_throughput_chrome,
        (1, 1500, 50)
      ),
      (
        'compositor_animation_throughput_content',
        'histogram-linear',
        'gpu',
        payload.processes.gpu.histograms.compositor_animation_throughput_content,
        (1, 1500, 50)
      ),
      (
        'content_frame_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.content_frame_time,
        (1, 5000, 50)
      ),
      (
        'content_frame_time_reason',
        'histogram-categorical',
        'gpu',
        payload.processes.gpu.histograms.content_frame_time_reason,
        (1, 50, 51)
      ),
      (
        'content_frame_time_vsync',
        'histogram-linear',
        'gpu',
        payload.processes.gpu.histograms.content_frame_time_vsync,
        (8, 792, 100)
      ),
      (
        'content_frame_time_with_svg',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.content_frame_time_with_svg,
        (1, 5000, 50)
      ),
      (
        'content_frame_time_without_resource_upload',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.content_frame_time_without_resource_upload,
        (1, 5000, 50)
      ),
      (
        'content_frame_time_without_upload',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.content_frame_time_without_upload,
        (1, 5000, 50)
      ),
      (
        'content_full_paint_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.content_full_paint_time,
        (1, 1000, 50)
      ),
      (
        'content_response_duration',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.content_response_duration,
        (1, 60000, 50)
      ),
      (
        'd3d11_sync_handle_failure',
        'histogram-count',
        'gpu',
        payload.processes.gpu.histograms.d3d11_sync_handle_failure,
        (1, 2, 3)
      ),
      (
        'device_reset_reason',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.device_reset_reason,
        (1, 10, 11)
      ),
      (
        'forced_device_reset_reason',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.forced_device_reset_reason,
        (1, 50, 51)
      ),
      (
        'fxrpc_entry_method',
        'histogram-categorical',
        'gpu',
        payload.processes.gpu.histograms.fxrpc_entry_method,
        (1, 50, 51)
      ),
      (
        'fxrpc_ff_installation_from',
        'histogram-categorical',
        'gpu',
        payload.processes.gpu.histograms.fxrpc_ff_installation_from,
        (1, 50, 51)
      ),
      (
        'gfx_crash',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.gfx_crash,
        (1, 100, 101)
      ),
      (
        'gpu_process_initialization_time_ms',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.gpu_process_initialization_time_ms,
        (1, 64000, 100)
      ),
      (
        'gpu_wait_time_ms',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.gpu_wait_time_ms,
        (1, 5000, 50)
      ),
      (
        'ipc_message_size2',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.ipc_message_size2,
        (1, 8000000, 50)
      ),
      (
        'keypress_present_latency',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.keypress_present_latency,
        (1, 200000, 50)
      ),
      (
        'media_decoder_backend_used',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.media_decoder_backend_used,
        (1, 10, 11)
      ),
      (
        'media_wmf_decode_error',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.media_wmf_decode_error,
        (1, 256, 257)
      ),
      (
        'mouseup_followed_by_click_present_latency',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.mouseup_followed_by_click_present_latency,
        (1, 200000, 50)
      ),
      (
        'scroll_input_methods',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.scroll_input_methods,
        (1, 64, 65)
      ),
      (
        'scroll_present_latency',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.scroll_present_latency,
        (1, 20000, 100)
      ),
      (
        'telemetry_event_recording_error',
        'histogram-categorical',
        'gpu',
        payload.processes.gpu.histograms.telemetry_event_recording_error,
        (1, 50, 51)
      ),
      (
        'webvr_dropped_frames_in_oculus',
        'histogram-linear',
        'gpu',
        payload.processes.gpu.histograms.webvr_dropped_frames_in_oculus,
        (1, 200, 100)
      ),
      (
        'webvr_dropped_frames_in_openvr',
        'histogram-linear',
        'gpu',
        payload.processes.gpu.histograms.webvr_dropped_frames_in_openvr,
        (1, 200, 100)
      ),
      (
        'webvr_time_spend_for_viewing_in_oculus',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.webvr_time_spend_for_viewing_in_oculus,
        (1, 50000, 100)
      ),
      (
        'webvr_time_spend_for_viewing_in_openvr',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.webvr_time_spend_for_viewing_in_openvr,
        (1, 50000, 100)
      ),
      (
        'webvr_time_spent_viewing_in_oculus',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.webvr_time_spent_viewing_in_oculus,
        (1, 1200000, 100)
      ),
      (
        'webvr_time_spent_viewing_in_openvr',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.webvr_time_spent_viewing_in_openvr,
        (1, 1200000, 100)
      ),
      (
        'webvr_users_view_in',
        'histogram-enumerated',
        'gpu',
        payload.processes.gpu.histograms.webvr_users_view_in,
        (1, 3, 4)
      ),
      (
        'wr_framebuild_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.wr_framebuild_time,
        (1, 1000, 50)
      ),
      (
        'wr_render_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.wr_render_time,
        (1, 1000, 50)
      ),
      (
        'wr_scenebuild_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.wr_scenebuild_time,
        (1, 1000, 50)
      ),
      (
        'wr_sceneswap_time',
        'histogram-exponential',
        'gpu',
        payload.processes.gpu.histograms.wr_sceneswap_time,
        (1, 1000, 50)
      )
    ] AS histogram_aggregates
  FROM
    sampled_data
),
filtered_aggregates AS (
  SELECT
    submission_date,
    sample_id,
    client_id,
    os,
    app_version,
    app_build_id,
    channel,
    metric,
    metric_type,
    process,
    bucket_range,
    value
  FROM
    histograms
  CROSS JOIN
    UNNEST(histogram_aggregates)
  WHERE
    value IS NOT NULL
),
aggregated AS (
  SELECT
    sample_id,
    client_id,
    submission_date,
    os,
    app_version,
    app_build_id,
    channel,
    metric,
    metric_type,
    process,
    ARRAY_AGG(bucket_range) AS bucket_range,
    ARRAY_AGG(value) AS value
  FROM
    filtered_aggregates
  GROUP BY
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10
)
SELECT
  sample_id,
  client_id,
  submission_date,
  os,
  app_version,
  app_build_id,
  channel,
  ARRAY_AGG(
    STRUCT<
      metric STRING,
      metric_type STRING,
      key STRING,
      process STRING,
      agg_type STRING,
      bucket_range STRUCT<first_bucket INT64, last_bucket INT64, num_buckets INT64>,
      value ARRAY<STRUCT<key STRING, value INT64>>
    >(
      metric,
      metric_type,
      '',
      process,
      'summed_histogram',
      bucket_range[OFFSET(0)],
      udf_aggregate_json_sum(value)
    )
  ) AS histogram_aggregates
FROM
  aggregated
GROUP BY
  1,
  2,
  3,
  4,
  5,
  6,
  7
