Odin's Spear
  • Welcome
  • What's New
  • Getting Started
    • Getting the Essentials
    • Create API Object
  • API Coverage
  • Docs
    • API Object
    • Standard Methods
      • Administrators
        • POST - Service Provider Admin
        • PUT - Service Provider Admin Policies
        • POST - Group Admin Polices Bulk
        • POST - Group Admin
      • Alternate Numbers
        • GET - User Alternate Numbers
      • Authentication
        • PUT - User Web Authentication Password
        • PUT - User Authentication Service
      • Auto Attendants
        • GET - Auto Attendants
        • POST - Auto Attendant
        • GET - Auto Attendant
        • GET - Auto Attendant User
        • POST - Auto Attendant Remove User
        • PUT - Auto Attendant
        • DELETE - Auto Attendant
        • GET - Auto Attendant Submenus
        • POST - Auto Attendant Submenu
        • GET - Auto Attendant Submenu Usage
        • PUT - Auto Attendant Submenu
        • PUT - Auto Attendant Status
        • DELETE - Auto Attendant Submenu
      • Call Centers
        • GET - Group Call Center
        • PUT - Group Call Center
        • GET - Group Call Centers
        • PUT - Group Call Center Agents
        • PUT - Group Call Center Agents Levels
        • GET - Group Call Center Bounced Calls
        • PUT - Group Call Center Bounced Call
        • PUT - Group Call Center DNIS Instance
        • GET - Group Call Center Forced Forwarding
        • PUT - Group Call Center Forced Forwarding
        • GET - Group Call Center Overflow
        • PUT - Group Call Center Overflow
        • GET - Group Call Center Stranded Calls
        • GET - Group Call Center Stranded Calls Unavailable
        • PUT - Group Call Center Status
        • PUT - Group Call Center Stranded Calls
        • PUT - Group Call Center Stranded Calls Unavailable
        • GET - User Call Center
        • PUT - User Call Center
        • PUT - User Call Center Agent Sign Out
        • PUT - User Call Center Agents Update
        • PUT - User Call Center Supervised Agents
      • Call Forwarding Always
        • GET - Bulk Call Forwarding Always
        • GET - User Call Forwarding Always
      • Call Forwarding Busy
        • GET - Bulk Call Forwarding Busy
        • GET - User Call Forwarding Busy
      • Call Forwarding No Answer
        • GET - Bulk User Call Forwarding No Answer
        • GET - User Call Forwarding No Answer
      • Call Forwarding Not Reachable
        • GET - Bulk User Call Forwarding Not Reachable
        • GET - User Call Forwarding Not Reachable
      • Call Forwarding Selective
        • GET - User Call Forwarding Selective
        • GET - User Call Forwarding Selective Criteria
        • GET - User Call Forwarding Selective Criterias
      • Call Pickup
        • GET - Call Pickup Group User
      • Call Processing Policies
        • PUT - User Call Processing Policy
      • Call Records
        • GET - User Stats
      • Devices
        • POST - Group Device
        • PUT - Group Devices
        • PUT - Group Device File
        • PUT - Group Device Tag
        • PUT - Group Device Type File
        • PUT - Group Device Tags Profile
        • PUT - Group Device Type Tag
        • PUT - Service Provider Device
        • PUT - Service Provider Device File
        • PUT - Service Provider Device Tag
        • PUT - Service Provider Device Type Tag
        • PUT - System Devices
        • PUT - System Device File
        • PUT - System Device Tag
      • DNs
        • GET - Group DNs
        • POST - Group DNs
        • DELETE - Group DNs
        • PUT - Group DNs Activate
        • POST - Group DNs Assign Bulk
        • GET - Group DN Details
        • GET - Group DN Search
        • POST - Group DNs Unassign Bulk
        • GET - Service Provider DNs
        • POST - Service Provider DNs
        • GET - Service Provider DN Search
        • DELETE - Service Provider DNs
        • GET - System DNs
        • GET - System DN Search
        • GET - System DN Summary
        • GET - System DN Utilisation
      • Do Not Disturb
        • GET - User Do Not Disturb
        • PUT - User Do Not Disturb
      • Emergency Zones
        • POST - Group Emergency Zones
        • PUT - Group Emergency Zones
      • Groups
        • GET - Group Information
        • GET - Service Provider Groups
      • Hunt Groups
        • GET - Group Hunt Groups
        • GET - Group Hunt Group
        • POST - Group Hunt Group
        • PUT - Group Hunt Group
        • DELETE - Group Hunt Group
        • GET - Group Hunt Groups Available Users
        • PUT - Group Hunt Groups Status
        • GET - Group Hunt Group User
        • PUT - Group Hunt Group Weighted Call Distribution
        • POST - Group Hunt Groups Remove User
      • Password Generate
        • GET - Password Generate
        • GET - Passwords Generate
        • GET - Passcode Generate
        • GET - Passcodes Generate
        • GET - SIP Password Generate
        • GET - SIP Passwords Generate
      • Registration
        • GET - User Registration
        • GET - Bulk User Registration
      • Reports
        • GET - User Report
      • Schedules
        • GET - Group Schedules
        • GET - Group Events
      • Service Providers
        • GET - Service Provider
        • GET - Service Providers
      • Services
        • GET - Group Services
        • GET - Group Services Assigned
        • GET - User-Services
        • PUT - User Services
        • GET - User Services Assigned
        • GET - User Service Settings
        • PUT - User Service Settings
      • Shared Call Appearance
        • POST - User Shared Call Appearance Endpoint
      • Trunk Groups
        • GET - Group Trunk Group
        • GET - Group Trunk Groups
        • GET - Group Trunk Groups Call Capacity
        • PUT - Group Trunk Groups Call Capacity
        • PUT - Group Trunk Group
        • POST - Group Trunk Group
        • GET - Service Provider Call Capacity Report
        • GET - Service Provider Trunk Group Call Capacity
        • PUT - Service Provider Trunk Group Call Capacity
      • User
        • GET - User By ID
        • GET - Users
        • POST - User
        • PUT - User
        • DELETE - User
        • PUT - User ID
        • PUT - Users Bulk
        • PUT - User Group ID Update
        • GET - User Login Info
        • GET - User Portal Passcode
        • PUT - User Portal Passcode
        • POST - User Reset
      • Voice Messaging
        • GET - Group Voice Messaging
        • GET - Group Voice Messaging Portal
        • GET - User Voice Messaging Advanced
        • GET - User Voice Messaging Bulk
        • GET - User Voice Messaging Greetings
        • GET - User Voice Messaging Message Details
        • GET - User Voice Messaging Message Download
        • GET - User Voice Messaging Messages
        • GET - User Voice Messaging User Distribution List
        • GET - User Voice Messaging User Distribution Lists
        • GET - User Voice Messaging Voice Portal
        • GET - User Voice Messaging
        • PUT - Group Voice Messaging
        • PUT - Group Voice Messaging Portal
        • PUT - User Voice Messaging Bulk
        • PUT - User Voice Messaging Greetings
        • PUT - User Voice Messaging Messages Read
        • PUT - User Voice Messaging Messages Unread
        • PUT - User Voice Messaging User Distribution List
        • PUT - User Voice Messaging Voice Portal
        • PUT - User Voice Messaging
        • DELETE - User Voice Messaging Messages
    • Advanced Features
      • Scripter
        • Find Alias
        • User Association
        • Group Audit
        • Move Numbers
        • Remove Numbers
        • Bulk Password Reset
        • Service Provider Trunking Capacity
        • Webex Builder
        • Locate Free Extension
        • User Registration
        • VM Auto Login
      • Reporter
        • Call Flow
          • Making Sense of The Call Flow
          • Graphviz
        • Group Users Call Statistics
        • User Registration Report
    • Utils
      • Config Manager
        • Template Configs
          • Auto Attendant
          • Call Center
          • Device
          • Group
          • Hunt Group
          • Service Provider
          • Trunk Group
          • User
      • Checkers
      • Constants
      • Formatters
      • Parsers
    • Logging
  • Powered By Odin's Spear
    • AA, CC, HG Audit
    • Bulk Build Group Admins
    • Bulk Build Service Provider Admins
    • Service Pack Audit
    • VM Bulk Passcode Set CSV
  • 14IP
    • Custom Logger
  • Development
  • Troubleshooting & FAQ
    • Frequently Asked Questions
    • Common Issues
      • Graphviz Troubleshooting
  • Change Log
  • Bugs and Issues
  • Contact
Powered by GitBook
On this page
  • Overview
  • Features
  • Configuration Options
  • How It Works
  • How to Use
  • ESLogger Class
  • Use ESLogger with Odin's Spear
  • Terminal Output

Was this helpful?

  1. 14IP

Custom Logger

The ESLogger is a custom Python logger designed to simultaneously send log records to Elasticsearch for FourteenIP's needs as well as print them to the terminal for the end user.

It extends Python’s built-in logging.Logger to capture accurate caller information (file, function, and line number) and to support flexible logging output.


Overview

The ESLogger is built to:

  • Send logs to Elasticsearch: Every log message is indexed in Elasticsearch using the provided cloud credentials.

  • Print logs to the terminal: A built-in console handler outputs logs in a human-friendly format.

  • Capture correct caller information: Overrides the default logging behavior so that the file, function, and line number reported are from the actual logging call site.


Features

  • Dual Logging Output:

    • Elasticsearch: Logs are structured and sent to a specified Elasticsearch index.

    • Terminal: Logs are output to the terminal with a configurable format.

  • Caller Context Accuracy: The logger overrides the internal _log() method with an increased stacklevel to ensure that the origin (file, function, and line) of the log is captured correctly.

  • Custom Fields: The log document sent to Elasticsearch includes a unique GUID (generated on instantiation) and user information.


Configuration Options

When instantiating an ESLogger, the following parameters must be provided:

  • name (str):

    • Description: The name of the logger.

    • Default: "OS"

  • level (int):

    • Description: The base logging level for the logger (as defined in Python’s logging module).

    • Default: logging.INFO

  • cloud_id (str):

    • Description: The Elasticsearch Cloud ID required to connect to your Elasticsearch deployment.

    • Required: Yes

  • api_key (tuple):

    • Description: A tuple containing the API key and API key ID for Elasticsearch authentication.

    • Required: Yes

  • index (str):

    • Description: The Elasticsearch index to which log documents will be sent.

  • username (str):

    • Description: The username to be included in the log document under the user field.

Note: If cloud_id or api_key are not provided, the logger will raise a ValueError.


How It Works

  1. Initialization: The logger is initialized with the provided Elasticsearch connection parameters and creates:

    • An Elasticsearch client using cloud_id and api_key.

    • A unique GUID (uuid) to be included with every log.

    • A console (terminal) handler with a specified formatter.

  2. Handling Log Records: The overridden handle() method processes each log record in two steps:

    • Console Output: The record is forwarded to the StreamHandler to print the log to the terminal.

    • Elasticsearch Output: A structured document is built using fields such as:

      • @timestamp: The log timestamp.

      • message: The log message.

      • log: A nested object containing log level, logger name, and origin (file name, line number, and function name).

      • custom: Contains the unique GUID.

      • user: Contains the username.

      This document is then indexed in Elasticsearch.

  3. Caller Context: The _log() method is overridden with an increased stacklevel (set to 2) so that the logging framework correctly identifies the real calling context rather than the logger’s internal methods.


How to Use

ESLogger Class

# filename es_logger.py

import logging
import time
import uuid

from elasticsearch import Elasticsearch


class ESLogger(logging.Logger):
    def __init__(
        self,
        name="OS",
        level=logging.INFO,
        cloud_id=None,
        api_key=None,
        index=str,
        username=str,
    ):
        """
        A custom logger that sends logs directly to Elasticsearch and ensures
        the correct function/module name is captured.
        """
        super().__init__(name, level)

        if not cloud_id or not api_key:
            raise ValueError(
                "cloud_id and api_key are required for Elasticsearch logging."
            )

        self.username = username
        self.uuid = str(uuid.uuid4())
        self.es = Elasticsearch(cloud_id=cloud_id, api_key=api_key)
        self.index = index

        # used to push logs to terminal
        self.console_handler = logging.StreamHandler()
        console_formatter = logging.Formatter(
            "timestamp: %(asctime)s, level: %(levelname)s, module: %(module)s, function: %(funcName)s, message: %(message)s"
        )
        self.console_handler.setFormatter(console_formatter)

    def handle(self, record: logging.LogRecord):
        """
        Custom handling of log records to send them to Elasticsearch while ensuring
        the correct function/module name is captured.
        """
        if not self.isEnabledFor(record.levelno):
            return

        # console
        self.console_handler.handle(record)

        # elastic
        try:
            doc = {
                "@timestamp": time.strftime(
                    "%Y-%m-%dT%H:%M:%S", time.localtime(record.created)
                ),
                "message": record.getMessage(),
                "log": {
                    "level": record.levelname,
                    "logger": record.name,  # Corrected logger name
                    "origin": {
                        "file": {
                            "name": record.pathname,  # Full file path
                            "line": record.lineno,
                        },
                        "function": record.funcName,  # Correct function name
                    },
                    "custom": {"guid": self.uuid},
                    "user": {"name": self.username},
                },
            }
            self.es.index(index=self.index, document=doc)
        except Exception:
            self.handleError(record)

    def _log(
        self,
        level,
        msg,
        args,
        exc_info=None,
        extra=None,
        stack_info=False,
        stacklevel=2,
    ):
        """
        Override `_log` to increase `stacklevel` so that logging captures
        the real caller.
        """
        super()._log(
            level, msg, args, exc_info, extra, stack_info, stacklevel=stacklevel
        )

Use ESLogger with Odin's Spear

from odins_spear import API
from es_logger import ESLogger  # Adjust the import path as needed

# Instantiate the custom logger with your Elasticsearch credentials
my_logger = ESLogger(
    cloud_id="YOUR_CLOUD_ID",
    api_key=("YOUR_API_KEY", "YOUR_API_KEY_ID"),
    index="odins_spear",
    username="test.user"
)

my_api = API(
    base_url="API URL",
    username="YOUR ODIN USERNAME",
    password="YOUR ODIN PASSWORD",
    logger=my_logger
)

Terminal Output

timestamp: 2025-03-11 15:45:30, level: INFO, module: <module>, function: example_function, message: This is an example log.
Previous14IPNextDevelopment

Last updated 2 months ago

Was this helpful?