Testing Logging with HTTP and Python

Overview

This section describes how to locally test Sym's HTTP Logging. To do this, we will:

  • Set up a local Python server that accepts POST requests and expose the server via Ngrok
  • Add the Ngrok URL to your sym_log_destination resource
  • View log entries in the console

Instructions

Set up the Python Server

Download the following Python script, which will start a local Python server on port 8080 and set up an Ngrok endpoint that points to it, so that the server is accessible from the public internet.

📘

Prerequisites

The Python script provided makes the following assumptions:

  1. You have Ngrok installed
  2. There are no other Ngrok servers currently running on your machine
  3. Port 8080 is free
# Python 3 server for Sym Log Entries
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
import subprocess
import urllib.request

hostName = "localhost"
serverPort = 8080

class SymHTTPLogDestination(BaseHTTPRequestHandler):
    def do_GET(self):
        """GET localhost:8080

        Displays the received log entries in JSON format.
        """
        self.send_response(200)
        self.send_header("Content-type", "application/stream+json")
        self.end_headers()
        with open("logs.txt", mode='r', encoding='utf-8') as f:
            content = f.read()
            content = content.rstrip(",\n")

        self.wfile.write(bytes(f"[{content}]", 'utf-8'))

    def do_POST(self):
        """POST localhost:8080
        
        Receives Sym Log entries, prints them to the console, and saves them to logs.txt
        """
        self.send_response(200)
        self.end_headers()
        content_len = int(self.headers.get('Content-Length'))
        post_body = self.rfile.read(content_len)
        json_post_body = json.loads(post_body.decode('utf-8'))
        with open("logs.txt","a", encoding='utf-8') as file:
            json.dump(json_post_body, file, indent=4)
            file.write(",\n")
        print(json.dumps(json_post_body, indent=4))


if __name__ == "__main__":
    # Start the Python web server at localhost:8080
    webServer = HTTPServer((hostName, serverPort), SymHTTPLogDestination)

    # Set up ngrok to forward requests to localhost:8080
    p = subprocess.Popen([f"ngrok http {str(serverPort)}"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # Grab the Ngrok public url
    contents = urllib.request.urlopen("http://localhost:4040/api/tunnels").read()
    ngrok_url = json.loads(contents)["tunnels"][0]["public_url"]
    print(f"HTTP Log Destination URL: {ngrok_url}")

    try:
        webServer.serve_forever()
    except KeyboardInterrupt:
        pass

    webServer.server_close()
    p.kill()
    print("Server stopped.")

Now, run the script from your preferred terminal.

python3 log_server.py

Terraform the HTTP Log Destination

The Python script will print out the Ngrok domain, e.g. (https://99f07bccd804.ngrok.io).

Copy this URL, and use it in your sym_log_destination resource.

resource "sym_log_destination" "local" {
  type = "http"
  settings = {
    # Paste the output of your script here
    url = "https://99f07bccd804.ngrok.io"
  }
}

Then add the log destination to the log_destination_ids in your sym_environment resource.

resource "sym_environment" "test" {
  name                = "test-logging"
  log_destination_ids = [sym_log_destination.http.id]
}

Test the Log Destination

Now that your Ngrok server is running and your environment is sending logs to it, any requests you make with /sym will audit a corresponding log entry! These log entries will be printed to the console and saved to a file called logs.txt.

You may also view the logs in a browser if you navigate to localhost:8080.