text: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  /* eslint-disable camelcase */
  /* eslint prefer-const: 2 */
  import shortid from 'shortid';
  import { SupersetClient } from '@superset-ui/core';
  
  import { safeStringify } from '../utils/safeStringify';
  import { LOG_EVENT } from '../logger/actions';
  import { LOG_EVENT_TYPE_TIMING } from '../logger/LogUtils';
  import DebouncedMessageQueue from '../utils/DebouncedMessageQueue';
  
  const LOG_ENDPOINT = '/superset/log/?explode=events';
  const sendBeacon = events => {
    if (events.length <= 0) {
      return;
    }
  
    let endpoint = LOG_ENDPOINT;
    const { source, source_id } = events[0];
    // backend logs treat these request params as first-class citizens
    if (source === 'dashboard') {
      endpoint += `&dashboard_id=${source_id}`;
    } else if (source === 'slice') {
      endpoint += `&slice_id=${source_id}`;
    }
  
    if (navigator.sendBeacon) {
      const formData = new FormData();
      formData.append('events', safeStringify(events));
      navigator.sendBeacon(endpoint, formData);
    } else {
      SupersetClient.post({
        endpoint,
        postPayload: { events },
        parseMethod: null,
      });
    }
  };
  
  // beacon API has data size limit = 2^16.
  // assume avg each log entry has 2^6 characters
  const MAX_EVENTS_PER_REQUEST = 1024;
  const logMessageQueue = new DebouncedMessageQueue({
    callback: sendBeacon,
    sizeThreshold: MAX_EVENTS_PER_REQUEST,
    delayThreshold: 1000,
  });
  let lastEventId = 0;
  const loggerMiddleware = store => next => action => {
    if (action.type !== LOG_EVENT) {
      return next(action);
    }
  
    const {
      dashboardInfo,
      explore,
      impressionId,
      dashboardLayout,
    } = store.getState();
    let logMetadata = {
      impression_id: impressionId,
      version: 'v2',
    };
    if (dashboardInfo) {
      logMetadata = {
        source: 'dashboard',
        source_id: dashboardInfo.id,
        ...logMetadata,
      };
    } else if (explore) {
      logMetadata = {
        source: 'explore',
        source_id: explore.slice ? explore.slice.slice_id : 0,
        ...logMetadata,
      };
    }
  
    const { eventName } = action.payload;
    let { eventData = {} } = action.payload;
    eventData = {
      ...logMetadata,
      ts: new Date().getTime(),
      event_name: eventName,
      ...eventData,
    };
    if (LOG_EVENT_TYPE_TIMING.has(eventName)) {
      eventData = {
        ...eventData,
        event_type: 'timing',
        trigger_event: lastEventId,
      };
    } else {
      lastEventId = shortid.generate();
      eventData = {
        ...eventData,
        event_type: 'user',
        event_id: lastEventId,
        visibility: document.visibilityState,
      };
    }
  
    if (eventData.target_id && dashboardLayout.present) {
      const meta = dashboardLayout.present[eventData.target_id].meta;
      // chart name or tab/header text
      eventData.target_name = meta.chartId ? meta.sliceName : meta.text;
    }
  
    logMessageQueue.append(eventData);
    return eventData;
  };
  
  export default loggerMiddleware;
  