common

package module
v1.29.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 31, 2025 License: Apache-2.0 Imports: 39 Imported by: 0

README ΒΆ

Common Go Package

Go Reference License

A comprehensive Go library providing reusable components for building scalable applications. This package offers production-ready utilities for authentication, data storage, payments, monitoring, and more.

πŸš€ Features

  • 🧾 Logging: Structured, PII-safe logging with optional LLM-assisted error analysis
  • πŸ” Authentication: OAuth2, JWT, session management
  • πŸ’Ύ Data Storage: Datastore, BigQuery, caching abstractions
  • πŸ’° Payments: Subscription management with multiple providers
  • πŸ“§ Communications: Email, SMS, and notification services
  • πŸ” Search: Full-text search with faceting
  • πŸ“Š Analytics: Event tracking and metrics collection
  • πŸ₯ Monitoring: Health checks and system metrics
  • 🎨 Frontend: Asset management, templates, HTMX support
  • πŸ”’ Security: RBAC, multi-tenancy, PII protection

πŸ“¦ Installation

go get github.com/patdeg/common

πŸ› οΈ Quick Start

Basic Usage
import "github.com/patdeg/common"

// PII-safe logging
common.InfoSafe("User logged in: %s", userEmail)

// Type conversions
num, err := common.StringToInt("123")
LLM-Assisted Logging
log := common.CreateLoggingLLM("handler.go", "HandleRequest", "processing %s", r.URL.Path)
defer log.Print() // emit markdown summary at the end

log.InfoSafe("starting handler for user %s", userEmail)

if err := doWork(); err != nil {
    // Triggers asynchronous LLM analysis when COMMON_LLM_API_KEY is set
    log.ErrorSafe("failed to process request: %v", err)
    return
}

// Optional: plug in a callback for self-healing behavior (alerts, tickets, etc.)
log := common.CreateLoggingLLMWithCallback(
    "handler.go",
    "HandleRequest",
    func(analysis string) error {
        // e.g. send an email, create an issue, or store analysis in a DB
        return nil
    },
    "processing %s", r.URL.Path,
)
defer log.Print()

LLM analysis runs asynchronously in a background goroutine and never blocks the HTTP response path.

Data Storage
import "github.com/patdeg/common/datastore"

repo, err := datastore.NewRepository(ctx)
err = repo.Put(ctx, "User", key, user)
Email Service
import "github.com/patdeg/common/email"

service, err := email.NewService(config)
err = service.Send(ctx, message)

πŸ“š Documentation

πŸ”’ Security Notice

⚠️ This is a PUBLIC repository:

  • βœ… No hardcoded credentials or secrets
  • βœ… PII-safe logging by default
  • βœ… Input validation and sanitization
  • βœ… Example data only (example.com domains)

πŸ§ͺ Examples

See the examples directory:

# Basic usage with local implementations
cd examples/basic-usage && go run main.go

# Complete App Engine application
cd examples/appengine && go run main.go

πŸ”§ Environment Configuration

The package automatically detects the environment and uses appropriate implementations:

Development (default): Local/in-memory services Production: Cloud services (set ENVIRONMENT=production)

Core Variables
# Authentication
GOOGLE_OAUTH_CLIENT_ID=xxxxx.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=your-secret
[email protected]

# Google Cloud
PROJECT_ID=your-project-id
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json

# Email
SENDGRID_API_KEY=SG.example_fake_key.replace_with_real_key
[email protected]

# Optional: LLM-assisted error analysis
COMMON_LLM_API_KEY=gsk_example_fake_key_replace_with_real
COMMON_LLM_MODEL=meta-llama/llama-4-scout-17b-16e-instruct
COMMON_LLM_BASE_URL=https://api.groq.com/openai/v1

πŸ“ˆ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Application Layer                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Frontend β”‚ API β”‚ Search β”‚ Monitor β”‚ Import/Export          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚              Business Logic Layer                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     Tenant β”‚ RBAC β”‚ Payment β”‚ Email β”‚ Tasks                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                Infrastructure Layer                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Datastore β”‚ BigQuery β”‚ Auth β”‚ Cache β”‚ Storage             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                   Core Utilities                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Logging β”‚ Convert β”‚ Crypto β”‚ Files β”‚ URLs β”‚ Debug          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🀝 Contributing

  1. Fork the repository
  2. Create your feature branch
  3. Commit your changes (no sensitive data!)
  4. Push to the branch
  5. Open a Pull Request

πŸ“ License

Apache License 2.0 - see LICENSE file for details.

Documentation ΒΆ

Overview ΒΆ

Package common provides helper utilities shared across the repository. The helpers include logging routines, conversion helpers and small web utilities.

Example:

if common.ISDEBUG {
    common.Debug("processing request")
}

Package common contains small conversion helpers used throughout the repository. The functions here convert between strings, numbers and other primitive types and provide helpers for formatting values.

Package common provides shared helpers used across the application. It includes utilities for reading and writing HTTP requests and responses such as the JSON/XML helpers found in interfaces.go.

Package common provides assorted helpers. This file contains debugging utilities used to dump HTTP requests, responses and cookies when troubleshooting issues during development.

Package common contains request and response helpers for JSON and XML. It exposes utilities like GetBody, WriteJSON and UnmarshalResponse for working with HTTP handlers.

Package common provides shared utilities used throughout the repository.

This file contains simple helpers for working with slices. They are referenced by other packages when building lists of unique values or checking if a string is present.

Index ΒΆ

Constants ΒΆ

View Source
const (
	// Business tags
	TagApp     = "APP"     // Application name
	TagFlow    = "FLOW"    // Flow/feature name (e.g., "checkout.payment")
	TagProduct = "PRODUCT" // Product identifier
	TagCompany = "COMPANY" // Company/tenant identifier
	TagUnit    = "UNIT"    // Business unit

	// User/Session tags
	TagUser    = "USER"    // User identifier (anonymized)
	TagSession = "SESSION" // Session identifier
	TagMarket  = "MARKET"  // Market/region

	// Technical tags
	TagVariant = "VARIANT" // A/B test variant
	TagVersion = "VERSION" // App version
	TagEnv     = "ENV"     // Environment (production, staging, dev)
	TagProject = "PROJECT" // GCP project or similar
)

Demeterics tag keys for analytics and tracking. See https://demeterics.ai/docs/prompt for full documentation.

Variables ΒΆ

View Source
var (
	// ISDEBUG reports whether debug logs should be printed. The value is
	// derived from the COMMON_DEBUG environment variable. When unset or not
	// a valid boolean, it defaults to false.
	//
	// Example:
	//
	//     $ COMMON_DEBUG=true ./your_binary
	//     if common.ISDEBUG {
	//         common.Debug("debugging enabled")
	//     }
	ISDEBUG = func() bool {
		v, err := strconv.ParseBool(os.Getenv("COMMON_DEBUG"))
		return err == nil && v
	}()

	// VERSION stores the application version. It can be overridden at build
	// time using -ldflags:
	//
	//     go build -ldflags "-X github.com/patdeg/common.VERSION=1.0.0"
	VERSION string

	// LLMAPIKey stores the API key used to contact the default LLM provider.
	// Users should set the COMMON_LLM_API_KEY environment variable prior to
	// running their binaries.
	LLMAPIKey = os.Getenv("COMMON_LLM_API_KEY")

	// LLMModel defines the default LLM model identifier. The value may be
	// overridden via the COMMON_LLM_MODEL environment variable.
	LLMModel = func() string {
		if v := os.Getenv("COMMON_LLM_MODEL"); v != "" {
			return v
		}
		return "meta-llama/llama-4-scout-17b-16e-instruct"
	}()

	// LLMBaseURL defines the HTTP endpoint for the LLM provider. It defaults to
	// Demeterics' Groq proxy but can be overridden with COMMON_LLM_BASE_URL.
	LLMBaseURL = func() string {
		if v := os.Getenv("COMMON_LLM_BASE_URL"); v != "" {
			return v
		}
		return "https://api.demeterics.com/groq/v1"
	}()
)
View Source
var (

	// AnalysisThrottleDuration controls how long to suppress duplicate error analyses.
	// Default: 60 minutes. Set to 0 to disable throttling.
	AnalysisThrottleDuration = 60 * time.Minute
)
View Source
var CUSTOM_BOTS_USER_AGENT = botUserAgents

CUSTOM_BOTS_USER_AGENT is kept for backward compatibility.

View Source
var (
	// ERROR_DATASTORE_ENTITY holds the Datastore entity name for error logging.
	// When set, the Error() function will store errors in Datastore.
	// Example: "Error" for production, "UAT_Error" for UAT, "DEV_Error" for development
	ERROR_DATASTORE_ENTITY string
)
View Source
var (

	// EnablePIIProtection controls whether PII sanitization is applied
	EnablePIIProtection = true
)
View Source
var SPAMMERS map[string]bool

SPAMMERS maps domains from spamDomainList for quick lookup.

Functions ΒΆ

func AddCustomPIIPattern ΒΆ

func AddCustomPIIPattern(name string, pattern string) error

AddCustomPIIPattern adds a custom pattern for PII detection and sanitization. This allows applications to define their own PII patterns.

func AddIfNotExists ΒΆ

func AddIfNotExists(element string, list []string) []string

AddIfNotExists appends element to list only if the element is not already present. It is useful when constructing slices that must contain unique values.

func AddIfNotExistsGeneric ΒΆ

func AddIfNotExistsGeneric(element interface{}, list []interface{}) []interface{}

AddIfNotExistsGeneric performs the same conditional append as AddIfNotExists but works with a slice of empty interfaces. It is used when the type of the elements is not known ahead of time.

func B2S ΒΆ

func B2S(b []byte) (s string)

B2S converts a null terminated byte slice to a string. If no null byte is present the entire slice is used. It returns the resulting string.

func CamelCase ΒΆ

func CamelCase(txt string) string

CamelCase converts a string containing separators into camel case. Any character found in the punctuation list starts a new word.

func Clean ΒΆ

func Clean(txt string) string

Clean lowercases a string, replaces spaces with underscores and URL escapes the result.

func ClearCookie ΒΆ

func ClearCookie(w http.ResponseWriter, r *http.Request)

ClearCookie removes the visitor ID cookie from the client by sending an expired cookie back to the browser.

func Debug ΒΆ

func Debug(format string, v ...interface{})

Debug writes a formatted debug message when ISDEBUG is true. A newline is appended so callers do not have to include one.

func DebugInfo ΒΆ

func DebugInfo(r *http.Request)

func DebugSafe ΒΆ

func DebugSafe(format string, v ...interface{})

DebugSafe writes a formatted debug message with PII sanitization. This is a PII-safe version of Debug that should be used when logging potentially sensitive information.

func Decrypt ΒΆ

func Decrypt(c context.Context, key string, message string) string

Decrypt decrypts a message encrypted with Encrypt. Note: For backward compatibility, this function returns empty string on error and logs the error. New code should check for empty return value.

func DoesCookieExists ΒΆ

func DoesCookieExists(r *http.Request) bool

DoesCookieExists reports whether the request contains a non-empty visitor ID cookie.

func DumpCookie ΒΆ

func DumpCookie(c context.Context, cookie *http.Cookie)

DumpCookie logs the details of a single cookie for debugging. Do not log cookies in production as they may contain session or tracking information.

func DumpCookies ΒΆ

func DumpCookies(r *http.Request)

DumpCookies logs all cookies present on the request. Use with caution and never in production if cookies contain private data.

func DumpRequest ΒΆ

func DumpRequest(r *http.Request, withBody bool)

DumpRequest logs the incoming HTTP request at debug level. If withBody is true, the request body is included and closed after logging. This helper should only be used during development as it may expose sensitive data.

func DumpRequestOut ΒΆ

func DumpRequestOut(r *http.Request, withBody bool)

DumpRequestOut logs an outbound client request. If withBody is true the request body is included. Only use in non-production environments as headers or bodies may contain private information.

func DumpResponse ΒΆ

func DumpResponse(c context.Context, r *http.Response)

DumpResponse logs an HTTP response. The response body is left open so callers may still read it and must be closed by the caller. Avoid using this helper in production if the response contains sensitive data.

func Encrypt ΒΆ

func Encrypt(c context.Context, key string, message string) string

Encrypt encrypts message using AES-256-GCM and returns a hex encoded nonce followed by ciphertext. Note: For backward compatibility, this function returns empty string on error and logs the error. New code should check for empty return value.

func Error ΒΆ

func Error(format string, v ...interface{})

Error writes a formatted error message with an "ERROR:" prefix. The prefix helps grep for errors in log files. If ERROR_DATASTORE_ENTITY is set, also stores the error in Datastore.

func ErrorSafe ΒΆ

func ErrorSafe(format string, v ...interface{})

ErrorSafe writes a formatted error message with PII sanitization. This should be used instead of Error when the message might contain PII.

func F2S ΒΆ

func F2S(f float64) (s string)

F2S converts a float64 to a string using fixed notation with eight digits of precision. The returned string is suitable for display or logging purposes.

func Fatal ΒΆ

func Fatal(format string, v ...interface{})

Fatal logs an error message with "FATAL: " prefix and exits the program. This is used for unrecoverable errors during startup or critical failures. The function logs the message and then calls os.Exit(1).

func FirstPart ΒΆ

func FirstPart(s string) string

FirstPart returns the first semi-colon separated component of a string.

func GenerateSecureID ΒΆ

func GenerateSecureID() (string, error)

GenerateSecureID creates a cryptographically secure random identifier Use this for session IDs, cookie IDs, tokens, or any security-sensitive identifier Returns a 64-character hex string (32 bytes of entropy / 256 bits)

func GetBody ΒΆ

func GetBody(r *http.Request) []byte

GetBody reads the entire body from the provided HTTP request and returns it as a byte slice. The caller remains responsible for closing r.Body:

body := GetBody(r)
defer r.Body.Close()

func GetBodyResponse ΒΆ

func GetBodyResponse(r *http.Response) []byte

GetBodyResponse reads the entire body from the given HTTP response and returns it. Always close r.Body after calling this helper:

body := GetBodyResponse(resp)
defer resp.Body.Close()

func GetCSRFToken ΒΆ

func GetCSRFToken(r *http.Request) string

GetCSRFToken returns the CSRF token from the request for template injection This is a convenience wrapper around csrf.GetToken() for use in templates

func GetContent ΒΆ

func GetContent(c context.Context, filename string) (*[]byte, error)

GetContent reads the file named by filename and returns its contents. Any errors encountered are logged and returned.

SECURITY NOTE: This function does NOT validate paths. If accepting user input, use ValidatePath() first to prevent path traversal attacks.

func GetContentByUrl ΒΆ

func GetContentByUrl(c context.Context, url string) ([]byte, error)

func GetCookieID ΒΆ

func GetCookieID(w http.ResponseWriter, r *http.Request) string

GetCookieID retrieves the visitor ID cookie or creates a new one if missing.

The created cookie is secured with the following attributes:

  • Path is always set to "/" so the ID is sent for all application routes.
  • Expires is 30 days in the future, giving the cookie a one month lifetime.
  • HttpOnly is true to prevent JavaScript access.
  • Secure is true for production (false for localhost/127.0.0.1) to support local development.
  • SameSite is Lax to protect against CSRF while allowing normal navigation.
  • Domain is only set when the host is neither localhost nor 127.0.0.1.

func GetServiceAccountClient ΒΆ

func GetServiceAccountClient(c context.Context) *http.Client

func GetSuffix ΒΆ

func GetSuffix(s string, split string) string

GetSuffix returns the portion of a string after the final occurrence of the supplied split delimiter.

func HandleEcho ΒΆ

func HandleEcho(w http.ResponseWriter, r *http.Request)

HandleEcho is an undocumented debug endpoint that echoes the first 255 characters of the request body to the logs and returns a simple response. This is useful for debugging request payloads without storing sensitive data.

Request:

  • Method: POST
  • Body: Any content (application/json, text/plain, etc.)

Response (200 OK):

{
  "status": "ok"
}

func Hash ΒΆ

func Hash(data string) uint32

func HashIP ΒΆ

func HashIP(ip string) string

HashIP creates a one-way hash of an IP address for privacy-compliant logging This function is used to comply with GDPR/CCPA requirements by not storing plain IP addresses in logs. The hash is consistent for the same IP within a deployment (using the IP_HASH_SALT), allowing for session tracking while protecting user privacy.

func I2S ΒΆ

func I2S(i int64) string

I2S converts an int64 to its decimal string representation. It returns the formatted string for the provided integer.

func Info ΒΆ

func Info(format string, v ...interface{})

Info writes a formatted informational message. A newline is appended to keep log lines consistent.

func InfoSafe ΒΆ

func InfoSafe(format string, v ...interface{})

InfoSafe writes a formatted informational message with PII sanitization. This should be used instead of Info when the message might contain PII.

func InitErrorDatastore ΒΆ

func InitErrorDatastore() error

InitErrorDatastore initializes the error logging datastore client

func IsBot ΒΆ

func IsBot(useragent string) bool

IsBot reports whether the agent is a known crawler. The heuristics rely on the user_agent library and a small list of custom user agents.

func IsCrawler ΒΆ

func IsCrawler(r *http.Request) bool

func IsHacker ΒΆ

func IsHacker(r *http.Request) bool

func IsMobile ΒΆ

func IsMobile(useragent string) bool

IsMobile returns true when the user agent represents a mobile device. It uses the github.com/mssola/user_agent library to parse the UA string.

func IsSpam ΒΆ

func IsSpam(c context.Context, referer string) bool

func IsValidHTTPURL ΒΆ

func IsValidHTTPURL(dest string) bool

IsValidHTTPURL verifies that dest is an absolute HTTP or HTTPS URL.

func Join ΒΆ added in v1.16.0

func Join(rawBase, path string) string

Join concatenates the provided path with the normalized base URL. The base URL is normalized using NormalizeBase, and the path is joined safely. If the base is empty after normalization, an empty string is returned. If the path is empty, the normalized base is returned.

func Left ΒΆ

func Left(s string, n int) string

Left returns the first n characters of s. If s is shorter than n it returns s unchanged. Example:

prefix := Left("abcdef", 3) // "abc"

func MarkdownToHTML ΒΆ added in v1.25.0

func MarkdownToHTML(markdown string) (string, error)

MarkdownToHTML converts markdown text to HTML. It uses GitHub Flavored Markdown extensions including tables, strikethrough, auto-linking, and task lists.

func MarkdownToHTMLWithWrapper ΒΆ added in v1.25.0

func MarkdownToHTMLWithWrapper(markdown string) (string, error)

MarkdownToHTMLWithWrapper converts markdown text to HTML and wraps it in a basic HTML document structure suitable for email. The wrapper includes minimal styling for readability.

func Marshal ΒΆ

func Marshal(c context.Context, value interface{}) string

Marshal returns the JSON encoding of value as a string, logging any error. Example:

jsonStr := Marshal(ctx, data)

func MessageHandler ΒΆ

func MessageHandler(c context.Context, w http.ResponseWriter, message string, redirectUrl string, timeoutSec int64)

MessageHandler renders a minimal HTML page using messagelTemplate. The page displays a message and performs a client-side redirect to redirectUrl after timeoutSec seconds via a meta-refresh tag.

func MonetaryToString ΒΆ

func MonetaryToString(f float64) string

MonetaryToString formats a float as a currency like value with two decimal places.

func NULLIfEmpty ΒΆ

func NULLIfEmpty(x string) string

NULLIfEmpty returns the provided string or the literal "NULL" if the value is empty or represents a NaN marker.

func NormalizeBase ΒΆ added in v1.16.0

func NormalizeBase(raw string) string

NormalizeBase returns a sanitized base URL with scheme and no trailing slash. If the input is empty, an empty string is returned. If the input lacks an http:// or https:// prefix, https:// is added.

func NumberToString ΒΆ

func NumberToString(n int, sep rune) string

http://stackoverflow.com/questions/13020308/how-to-fmt-printf-an-integer-with-thousands-comma NumberToString formats an integer with a thousands separator. The separator rune is inserted every three digits.

func ReadJSON ΒΆ

func ReadJSON(b []byte, d interface{}) error

ReadJSON unmarshals the JSON byte slice into the destination value. Example:

var out MyStruct
if err := ReadJSON(data, &out); err != nil { ... }

func ReadXML ΒΆ

func ReadXML(b []byte, d interface{}) error

ReadXML unmarshals the provided XML bytes into the destination structure. Example:

var out MyStruct
if err := ReadXML(data, &out); err != nil { ... }

func Reverse ΒΆ

func Reverse(s string) string

Reverse returns the string with its characters in reverse order.

func Round ΒΆ

func Round(num float64, precision int) float64

Round rounds a float to the given precision using round. Negative numbers are handled correctly thanks to math.Copysign in round.

func S2B ΒΆ

func S2B(s string) []byte

S2B converts a string to a byte slice. It returns the byte representation of the string.

func S2F ΒΆ

func S2F(s string) float64

S2F parses a float value from the provided string. It returns the parsed number or 0 if the string cannot be interpreted as a number.

func S2I ΒΆ

func S2I(s string) int64

S2I converts a string to an int64. If parsing fails the returned value is 0.

func SanitizeMessage ΒΆ

func SanitizeMessage(message string) string

SanitizeMessage applies PII sanitization to a message. This can be used to sanitize messages before logging them.

func SecureHash ΒΆ

func SecureHash(data string) string

SecureHash generates a SHA-256 hash of the input string Use this for hashing non-secret data where integrity matters (e.g., asset versioning) For secret data, use HMAC or password hashing functions like bcrypt

func SecurityHeadersMiddleware ΒΆ

func SecurityHeadersMiddleware(next http.Handler) http.Handler

SecurityHeadersMiddleware adds security headers to all HTTP responses This middleware should be applied to all HTTP handlers to protect against common web vulnerabilities including XSS, clickjacking, and MIME-sniffing attacks.

Headers set:

  • X-Frame-Options: DENY (prevents clickjacking)
  • X-Content-Type-Options: nosniff (prevents MIME-sniffing)
  • X-XSS-Protection: 1; mode=block (legacy XSS protection)
  • Content-Security-Policy: restricts resource loading (configurable via env)
  • Referrer-Policy: strict-origin-when-cross-origin (controls referrer info)
  • Strict-Transport-Security: enforces HTTPS (when using HTTPS)
  • Permissions-Policy: restricts browser features

Usage:

mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
secureHandler := common.SecurityHeadersMiddleware(mux)
http.ListenAndServe(":8080", secureHandler)

func SetPIIProtection ΒΆ

func SetPIIProtection(enabled bool)

SetPIIProtection enables or disables PII protection globally

func StringInSlice ΒΆ

func StringInSlice(a string, list []string) bool

StringInSlice reports whether the string a exists in list.

func TS ΒΆ

func TS(unixTime int64) (timeFormated string)

TS converts a Unix timestamp in milliseconds to an ANSI formatted time string.

func ToNumber ΒΆ

func ToNumber(s string) (bool, float64)

ToNumber attempts to parse the provided string as either a float64 or an integer. The first return value indicates success and the second contains the parsed number. When parsing fails for both float and int, the function returns false and 0.

func ToSQLString ΒΆ

func ToSQLString(x interface{}) string

ToSQLString converts an arbitrary value to a string using ToString and then escapes single quotes so the result can be embedded safely in SQL queries.

func ToString ΒΆ

func ToString(x interface{}) string

ToString converts a variety of primitive types to their string representation. Supported types are int, int64, float64 and string. For any other type fmt.Sprint is used. Nil values return an empty string.

func Trunc500 ΒΆ

func Trunc500(s string) string

Trunc500 truncates a string to a maximum length of 500 characters.

func UnmarshalRequest ΒΆ

func UnmarshalRequest(c context.Context, r *http.Request, value interface{}) error

UnmarshalRequest reads the HTTP request body and decodes the JSON payload into value. Example:

var in MyStruct
if err := UnmarshalRequest(ctx, r, &in); err != nil { ... }

func UnmarshalResponse ΒΆ

func UnmarshalResponse(c context.Context, resp *http.Response, value interface{}) error

UnmarshalResponse dumps the response to the debug log, reads the body and unmarshals JSON into value. Example:

var out MyStruct
if err := UnmarshalResponse(ctx, resp, &out); err != nil { ... }

func ValidatePath ΒΆ

func ValidatePath(basePath, userPath string) (string, error)

ValidatePath validates that a user-provided path is safe and within basePath Returns the absolute, validated path or an error if validation fails This function prevents path traversal attacks by:

  1. Cleaning the path (removes .., resolves ./, etc.)
  2. Rejecting paths containing .. after cleaning
  3. Rejecting absolute paths in user input
  4. Ensuring the final path is within the base directory
  5. Handling symlinks securely

func Warn ΒΆ

func Warn(format string, v ...interface{})

Warn writes a formatted warning message with an "WARNING:" prefix. The prefix helps grep for warnings in log files.

func WarnSafe ΒΆ

func WarnSafe(format string, v ...interface{})

WarnSafe writes a formatted warning message with PII sanitization. This should be used instead of Warn when the message might contain PII.

func WriteJSON ΒΆ

func WriteJSON(w http.ResponseWriter, d interface{}) error

WriteJSON marshals d to JSON and writes it to the response writer. Example:

_ = WriteJSON(w, data)

func WriteJSONWithStatus ΒΆ

func WriteJSONWithStatus(w http.ResponseWriter, statusCode int, d interface{}) error

func WriteXML ΒΆ

func WriteXML(w http.ResponseWriter, d interface{}, withHeader bool) error

WriteXML writes d to the http.ResponseWriter as XML. If withHeader is true the standard XML header is included. Example:

_ = WriteXML(w, data, true)

Types ΒΆ

type AnalysisCallback ΒΆ

type AnalysisCallback func(analysis string) error

AnalysisCallback is called when LLM analysis completes successfully. It receives the analysis result text and can perform custom actions like storing it in a database or sending notifications.

type ErrorEntity ΒΆ

type ErrorEntity struct {
	Timestamp      time.Time `datastore:"timestamp"`
	Message        string    `datastore:"message"`
	GAEApplication string    `datastore:"gae_application,omitempty"`
	GAEService     string    `datastore:"gae_service,omitempty"`
	GAEVersion     string    `datastore:"gae_version,omitempty"`
	GAEInstance    string    `datastore:"gae_instance,omitempty"`
	GAEMemoryMB    string    `datastore:"gae_memory_mb,omitempty"`
	GAEEnv         string    `datastore:"gae_env,omitempty"`
	GAERuntime     string    `datastore:"gae_runtime,omitempty"`
	ProjectID      string    `datastore:"project_id,omitempty"`
	Environment    string    `datastore:"environment,omitempty"`
}

ErrorEntity represents an error entry stored in Datastore

type LoggingLLM ΒΆ

type LoggingLLM struct {
	// contains filtered or unexported fields
}

LoggingLLM captures standard log output alongside a markdown summary for a single logical operation. The summary is later available for printing or as additional context for LLM debugging.

func CreateLoggingLLM ΒΆ

func CreateLoggingLLM(fileName, funcName, format string, v ...interface{}) *LoggingLLM

CreateLoggingLLM constructs a LoggingLLM for the provided file and function names. The optional format string is logged immediately as an Info entry to seed the markdown summary.

func CreateLoggingLLMWithCallback ΒΆ

func CreateLoggingLLMWithCallback(fileName, funcName string, callback AnalysisCallback, format string, v ...interface{}) *LoggingLLM

CreateLoggingLLMWithCallback constructs a LoggingLLM with a custom callback that will be invoked when LLM analysis completes successfully. The callback receives the analysis text and can store it, send notifications, etc.

func (*LoggingLLM) Debug ΒΆ

func (l *LoggingLLM) Debug(format string, v ...interface{})

Debug logs a debug message and records it inside the markdown summary when ISDEBUG is enabled. The summary stores a PII-sanitized representation.

func (*LoggingLLM) DebugSafe ΒΆ

func (l *LoggingLLM) DebugSafe(format string, v ...interface{})

DebugSafe logs a sanitized debug message and records it in the markdown summary when ISDEBUG is enabled.

func (*LoggingLLM) Error ΒΆ

func (l *LoggingLLM) Error(format string, v ...interface{})

Error logs an error message, records it in the markdown summary and triggers an asynchronous LLM analysis for additional guidance. If a callback was provided during creation, it will be called with the analysis result.

func (*LoggingLLM) ErrorNoAnalysis ΒΆ

func (l *LoggingLLM) ErrorNoAnalysis(format string, v ...interface{})

ErrorNoAnalysis logs an error message and records it in the markdown summary WITHOUT triggering LLM analysis. Use this for errors that don't need AI debugging or when you want manual control over when analysis happens.

func (*LoggingLLM) ErrorNoAnalysisSafe ΒΆ

func (l *LoggingLLM) ErrorNoAnalysisSafe(format string, v ...interface{})

ErrorNoAnalysisSafe logs an error with PII protection and records the sanitized message in the summary WITHOUT triggering LLM analysis.

func (*LoggingLLM) ErrorSafe ΒΆ

func (l *LoggingLLM) ErrorSafe(format string, v ...interface{})

ErrorSafe logs an error with PII protection, records the sanitized message in the summary, and triggers the LLM analysis workflow. If a callback was provided during creation, it will be called with the analysis result.

func (*LoggingLLM) Info ΒΆ

func (l *LoggingLLM) Info(format string, v ...interface{})

Info logs an informational message and records it in the markdown summary.

func (*LoggingLLM) InfoSafe ΒΆ

func (l *LoggingLLM) InfoSafe(format string, v ...interface{})

InfoSafe logs an informational message with PII sanitization applied and records the sanitized version in the markdown summary.

func (*LoggingLLM) MarkdownSummary ΒΆ

func (l *LoggingLLM) MarkdownSummary() string

MarkdownSummary returns the accumulated markdown summary including the elapsed duration since the logger was created.

func (*LoggingLLM) Print ΒΆ

func (l *LoggingLLM) Print()

Print writes the current markdown summary to stdout.

func (*LoggingLLM) SetTag ΒΆ added in v1.29.0

func (l *LoggingLLM) SetTag(key, value string) *LoggingLLM

SetTag sets a single Demeterics metadata tag. Returns the logger for method chaining.

func (*LoggingLLM) Warn ΒΆ

func (l *LoggingLLM) Warn(format string, v ...interface{})

Warn logs a warning message and records it in the markdown summary.

func (*LoggingLLM) WarnSafe ΒΆ

func (l *LoggingLLM) WarnSafe(format string, v ...interface{})

WarnSafe logs a warning message with sanitization applied and records the sanitized version in the markdown summary.

func (*LoggingLLM) WithTags ΒΆ added in v1.29.0

func (l *LoggingLLM) WithTags(tags map[string]string) *LoggingLLM

WithTags sets Demeterics metadata tags for analytics tracking. Tags are prepended to the LLM prompt as /// KEY value lines and stripped by Demeterics before forwarding to the provider (no token cost). Returns the logger for method chaining.

Example:

log := common.CreateLoggingLLM("payment.go", "ProcessPayment", "starting").
    WithTags(map[string]string{
        common.TagApp:  "billing-service",
        common.TagFlow: "checkout.payment",
        common.TagEnv:  "production",
    })

type Visitor ΒΆ

type Visitor struct {
	// Key is the datastore key for the visitor and also the cookie value.
	Key string `json:"key,omitempty"`
	// Cookie stores the same ID to easily serialize the cookie value.
	Cookie string `json:"cookie,omitempty"`
	// Host is the host name seen when the cookie was issued.
	Host string `json:"host,omitempty"`
	// CreatedTimestamp records when the cookie was created.
	CreatedTimestamp string `json:"createdTimestamp,omitempty"`
	// CreatedIP contains the client IP address at creation time.
	CreatedIP string `json:"createdIP,omitempty"`
	// CreatedReferer holds the HTTP referer header.
	CreatedReferer string `json:"createdReferer,omitempty"`
	// Geolocation fields derived from App Engine headers.
	CreatedCountry string `json:"createdCountry,omitempty"`
	CreatedRegion  string `json:"createdRegion,omitempty"`
	CreatedCity    string `json:"createdCity,omitempty"`
	// CreatedUserAgent stores the raw user agent string.
	CreatedUserAgent string `json:"createdUserAgent,omitempty"`
	// CreatedIsMobile indicates whether the UA looked like a mobile device.
	CreatedIsMobile bool `json:"createdIsMobile,omitempty"`
	// CreatedIsBot indicates whether the UA was identified as a bot.
	CreatedIsBot bool `json:"createdIsBot,omitempty"`
	// Parsed user agent details.
	CreatedMozillaVersion string `json:"createdMozillaVersion,omitempty"`
	CreatedPlatform       string `json:"createdPlatform,omitempty"`
	CreatedOS             string `json:"createdOS,omitempty"`
	// Rendering engine details extracted from the UA string.
	CreatedEngineName    string `json:"createdEngineName,omitempty"`
	CreatedEngineVersion string `json:"createdEngineVersion,omitempty"`
	// Browser details extracted from the UA string.
	CreatedBrowserName    string `json:"createdBrowserName,omitempty"`
	CreatedBrowserVersion string `json:"createdBrowserVersion,omitempty"`
}

Directories ΒΆ

Path Synopsis
Package api provides a flexible HTTP API client with retry logic, rate limiting, and authentication support.
Package api provides a flexible HTTP API client with retry logic, rate limiting, and authentication support.
Package auth implements a minimal Google OAuth workflow used by the other packages in this repository.
Package auth implements a minimal Google OAuth workflow used by the other packages in this repository.
Package bigquery provides utilities for BigQuery operations including streaming inserts, table management, and query execution.
Package bigquery provides utilities for BigQuery operations including streaming inserts, table management, and query execution.
Package csrf provides Cross-Site Request Forgery (CSRF) protection middleware for HTTP handlers.
Package csrf provides Cross-Site Request Forgery (CSRF) protection middleware for HTTP handlers.
Package datastore provides a flexible data storage abstraction that supports both local development (in-memory) and production (Google Cloud Datastore).
Package datastore provides a flexible data storage abstraction that supports both local development (in-memory) and production (Google Cloud Datastore).
Package email provides a flexible email service abstraction that supports multiple providers (SendGrid, SMTP, local development).
Package email provides a flexible email service abstraction that supports multiple providers (SendGrid, SMTP, local development).
examples
appengine command
Package main provides a minimal example server showing how to use the authentication helpers from the common repository.
Package main provides a minimal example server showing how to use the authentication helpers from the common repository.
basic-usage command
Package frontend provides utilities for frontend assets management, template rendering, and HTMX integration.
Package frontend provides utilities for frontend assets management, template rendering, and HTMX integration.
Package ga provides helpers for sending hits to Google Analytics using the Measurement Protocol.
Package ga provides helpers for sending hits to Google Analytics using the Measurement Protocol.
Package gcp provides Google Cloud helpers for mygoto.me service.
Package gcp provides Google Cloud helpers for mygoto.me service.
Package geo provides geo-location utilities for AppEngine
Package geo provides geo-location utilities for AppEngine
Package impexp provides import/export utilities for data migration, backup, and restore operations.
Package impexp provides import/export utilities for data migration, backup, and restore operations.
llm
Package llmutils provides utilities for processing LLM prompt templates with support for comment stripping and metadata extraction.
Package llmutils provides utilities for processing LLM prompt templates with support for comment stripping and metadata extraction.
Package logging provides PII-safe logging functionality for applications.
Package logging provides PII-safe logging functionality for applications.
Package loggingctx provides request ID middleware and context utilities for distributed tracing.
Package loggingctx provides request ID middleware and context utilities for distributed tracing.
Package monitor provides health checks, metrics collection, and monitoring capabilities for applications.
Package monitor provides health checks, metrics collection, and monitoring capabilities for applications.
Package payment provides subscription and payment processing with support for multiple payment providers.
Package payment provides subscription and payment processing with support for multiple payment providers.
Package rbac provides role-based access control with permissions, roles, and policy management.
Package rbac provides role-based access control with permissions, roles, and policy management.
Package search provides full-text search capabilities with support for multiple backends including in-memory and external search services.
Package search provides full-text search capabilities with support for multiple backends including in-memory and external search services.
Package tasks provides utilities for Google Cloud Tasks operations including task creation, queue management, and retry policies.
Package tasks provides utilities for Google Cloud Tasks operations including task creation, queue management, and retry policies.
Package tenant provides multi-tenant support with tenant isolation, configuration management, and cross-tenant operations.
Package tenant provides multi-tenant support with tenant isolation, configuration management, and cross-tenant operations.
Package track contains analytics helpers.
Package track contains analytics helpers.
Package version provides application version management.
Package version provides application version management.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL