text: # -*- coding: utf-8 -*-
  """An output module that saves events to Elasticsearch."""
  
  from __future__ import unicode_literals
  
  from plaso.output import logger
  from plaso.output import manager
  from plaso.output import shared_elastic
  
  
  class ElasticsearchOutputModule(shared_elastic.SharedElasticsearchOutputModule):
    """Output module for Elasticsearch."""
  
    NAME = 'elastic'
    DESCRIPTION = 'Saves the events into an Elasticsearch database.'
  
    _DEFAULT_MAPPINGS = {
        'properties': {
            'application': {
                'type': 'text',
                'fields': {
                    'keyword': {
                        'type': 'keyword',
                    }
                },
            },
            'data': {'type': 'text', 'fields': {'keyword': {'type': 'keyword'}}},
            'doc_type': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'event_type': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'exit_status': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'facility': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'file_reference': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'file_size': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'flags': {'type': 'text', 'fields': {'keyword': {'type': 'keyword'}}},
            'identifier': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'message_status': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'message_type': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'offset': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}}},
            'sequence_number': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'severity': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'source_port': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'user_identifier': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            },
            'version': {
                'type': 'text',
                'fields': {'keyword': {'type': 'keyword'}},
            }
        }
    }
    # Strings longer than this will not be analyzed by elasticsearch.
    _ELASTIC_ANALYZER_STRING_LIMIT = 10922
  
    def __init__(self, output_mediator):
      """Initializes an Elasticsearch output module.
  
      Args:
        output_mediator (OutputMediator): mediates interactions between output
            modules and other components, such as storage and dfvfs.
      """
      super(ElasticsearchOutputModule, self).__init__(output_mediator)
      self._raw_fields = False
  
    def SetRawFields(self, raw_fields):
      """Set raw (non-analyzed) fields.
  
      This is used for sorting and aggregations in Elasticsearch.
      https://www.elastic.co/guide/en/elasticsearch/guide/current/
      multi-fields.html
  
      Args:
        raw_fields (bool): True if raw (non-analyzed) fields should be added.
      """
      self._raw_fields = raw_fields
  
      if raw_fields:
        logger.debug('Elasticsearch adding raw (non-analyzed) fields.')
      else:
        logger.debug('Elasticsearch not adding raw (non-analyzed) fields.')
  
    def WriteHeader(self):
      """Connects to the Elasticsearch server and creates the index."""
      mappings = self._DEFAULT_MAPPINGS
  
      if self._raw_fields:
        # This cannot be static because we use the value of self._document_type
        # from arguments.
        mappings = {
            'dynamic_templates': [{
                'strings': {
                    'mapping': {
                        'fields': {
                            'raw': {
                                'ignore_above': (
                                    self._ELASTIC_ANALYZER_STRING_LIMIT),
                                'index': 'false',
                                'type': 'keyword',
                            },
                        },
                    },
                    'match_mapping_type': 'string',
                },
            }],
        }
  
      # TODO: Remove once Elasticsearch v6.x is deprecated.
      client_major_version = self._GetClientMajorVersion()
      if client_major_version < 7:
        mappings = {self._document_type: mappings}
  
      self._Connect()
  
      self._CreateIndexIfNotExists(self._index_name, mappings)
  
  
  manager.OutputManager.RegisterOutput(
      ElasticsearchOutputModule, disabled=shared_elastic.elasticsearch is None)
  