Release v1.0.0 #2

Merged
Rene Nochebuena merged 11 commits from release/v1.0.0 into main 2025-04-10 18:30:35 -06:00
4 changed files with 398 additions and 7 deletions
Showing only changes of commit 94c6e882fb - Show all commits

View File

@ -19,6 +19,70 @@ The most scientifically badass logging library from the Kingdom of Science!
go get gitstormr.dev/stone-utils/stonelog@latest go get gitstormr.dev/stone-utils/stonelog@latest
``` ```
## ⚑ Initialization
```go
package main
import (
"gitstormr.dev/stone-utils/stonelog"
)
func main() {
// Basic configuration (INFO level by default)
stonelog.InitStoneLog(stonelog.INFO, false, false) // false = text mode (true = JSON), false = keep suffixes (true = don't add character quotes)
// Example logs
stonelog.Observation("System initialized successfully!")
stonelog.Failure("Reactor core temperature critical!")
}
```
## πŸ“œ Log Levels (Scientific Style!)
| Function | Level Equivalent | Example Output |
|---------------|--------------------|--------------------------------------------------|
| Trace() | TRACE | πŸ” Science traces: Entering function X |
| Debug() | DEBUG | πŸ€” Hypothesis forming: Variable X = 42 |
| Observation() | INFO | βœ… Experiment successful: User logged in |
| Hypothesis() | WARN | ⚠️ Anomaly detected: High memory usage |
| Failure() | ERROR | πŸ’₯ Critical malfunction: DB disconnected |
| Meltdown() | FATAL | ☠️ FINAL EXPERIMENT FAILED: Server exploded |
| Panic() | PANIC | 🚨 CHAIN REACTION DETECTED: Unrecoverable error |
## πŸŽ›οΈ Changing Log Level
```go
// Dynamic change! (e.g., enable DEBUG in production)
stonelog.SetLogLevel(stonelog.DEBUG)
```
## πŸ”¬ JSON Mode (For Production)
```go
stonelog.InitStoneLab(stonelog.STONE_DEBUG, true, false) // true = JSON, false = Keep suffixes
// Output: {"time":"2023-07-15T12:00:00Z","level":"OBSERVATION","message":"βœ… Experiment successful: System ready","caller":"main.go:15"}
```
## **🚨 WINDOWS COLOR SUPPORT NOTICE 🚨**
*"HEY WINDOWS USERS! YOUR TERMINALS NEED SOME SCIENCE!" - Chrome*
πŸ”¬ **Current Limitations:**
- Colors don't work in old Windows Command Prompt (CMD)
- Looks boring in black & white (like stone tablets!)
- Works perfectly in modern terminals
πŸ’‘ **Senku-Approved Solutions:**
1. Install **Windows Terminal** (Microsoft Store)
2. Use **WSL** (Windows Subsystem for Linux)
3. Try **VS Code** or **Git Bash**
*"This temporary setback represents just 0.0000001% of our scientific progress!"*
- **Dr. Senku Ishigami**
*(Chrome whispers: "Pssst... Linux terminals are SO BADASS!")* 🐧πŸ”₯
**Join the Scientific Revolution!** **Join the Scientific Revolution!**
> "This isn't just logging - it's 10 billion percent scientific progress!" - Senku Ishigami > "This isn't just logging - it's 10 billion percent scientific progress!" - Senku Ishigami

264
log.go Normal file
View File

@ -0,0 +1,264 @@
package stonelog
import (
"encoding/json"
"fmt"
"log"
"math/rand"
"os"
"path/filepath"
"runtime"
"strconv"
"time"
)
// logEntry represents the structure for a single log entry.
// Time is the timestamp of the log entry in RFC3339 format.
// Level specifies the severity level of the log message.
// Caller describes the source file and line generating the log.
// Message contains the actual log details or description.
type logEntry struct {
Time string `json:"time"`
Level string `json:"level"`
Caller string `json:"caller"`
Message string `json:"message"`
}
// StoneLevel represents the severity level of logging categories.
type StoneLevel int
// String returns the string representation of the StoneLevel.
func (l StoneLevel) String() string {
return stoneLevelNames[l]
}
// Color returns the color code associated with the StoneLevel.
func (l StoneLevel) Color() string {
return levelColors[l]
}
// TRACE represents the trace log level.
// DEBUG represents the debug log level.
// INFO represents the info log level.
// WARN represents the warning log level.
// ERROR represents the error log level.
// FATAL represents the fatal log level.
// PANIC represents the panic log level.
const (
TRACE StoneLevel = iota
DEBUG
INFO
WARN
ERROR
FATAL
PANIC
)
// stoneLevelNames maps StoneLevel constants to their string representations.
var stoneLevelNames = map[StoneLevel]string{
TRACE: "TRACE",
DEBUG: "DEBUG",
INFO: "INFO",
WARN: "WARN",
ERROR: "ERROR",
FATAL: "FATAL",
PANIC: "PANIC",
}
// ANSI color codes for terminal text formatting.
const (
colorReset = "\033[0m"
colorRed = "\033[31m"
colorGreen = "\033[32m"
colorYellow = "\033[33m"
colorMagenta = "\033[35m"
colorCyan = "\033[36m"
colorWhite = "\033[37m"
)
// levelColors maps StoneLevel constants to their corresponding color codes.
var levelColors = map[StoneLevel]string{
TRACE: colorWhite,
DEBUG: colorCyan,
INFO: colorGreen,
WARN: colorYellow,
ERROR: colorRed,
FATAL: colorMagenta,
PANIC: colorRed + "\033[1m",
}
// stoneLogger is a logger instance for logging stone-related operations.
// currentLogLevel indicates the active logging level for stoneLogger.
// disableCharacterSuffixes disables suffixes in log outputs when true.
var (
stoneLogger *log.Logger
currentLogLevel StoneLevel
useJSON bool
callerFrameDepth = 3
disableCharacterSuffixes bool
)
// InitStoneLog initializes the logging system with the specified parameters.
// level sets the logging severity level threshold.
// jsonMode determines whether logs should be output in JSON format.
// disableSuffixes disables character suffixes in log messages.
func InitStoneLog(level StoneLevel, jsonMode, disableSuffixes bool) {
currentLogLevel = level
stoneLogger = log.New(os.Stdout, "", 0)
useJSON = jsonMode
disableCharacterSuffixes = disableSuffixes
}
// SetLogLevel sets the current log level to the specified StoneLevel.
func SetLogLevel(level StoneLevel) {
currentLogLevel = level
Observation("Log level set to %v", level)
}
// Trace logs a message at the TRACE using the specified format and arguments.
func Trace(format string, args ...interface{}) {
logMessage(TRACE, format, args...)
}
// Debug logs a message at the DEBUG level using the provided format and arguments.
func Debug(format string, args ...interface{}) {
logMessage(DEBUG, format, args...)
}
// Observation logs a message at the INFO level with optional formatting arguments.
func Observation(format string, args ...interface{}) {
logMessage(INFO, format, args...)
}
// Hypothesis logs a message with WARN level using the provided format and arguments.
func Hypothesis(format string, args ...interface{}) {
logMessage(WARN, format, args...)
}
// Failure logs a message at the ERROR level using the provided format and arguments.
func Failure(format string, args ...interface{}) {
logMessage(ERROR, format, args...)
}
// Meltdown logs a message at the FATAL level and terminates the program.
func Meltdown(format string, args ...interface{}) {
logMessage(FATAL, format, args...)
}
// Panic logs a message with PANIC severity and terminates the application.
func Panic(format string, args ...interface{}) {
logMessage(PANIC, format, args...)
}
// getCallerInfo retrieves the file name and line number of the caller.
// It returns the information in the format "file:line" or "unknown:0" on failure.
func getCallerInfo() string {
_, file, line, ok := runtime.Caller(callerFrameDepth)
if !ok {
return "unknown:0"
}
return filepath.Base(file) + ":" + strconv.Itoa(line)
}
// logMessage handles the logging of messages with varying severity levels.
// If the log level is below the configured threshold, it is ignored.
// Formats the message, adds a random prefix, and appends optional suffixes.
// Converts the output to JSON format if enabled or applies a custom formatter.
// Executes fatal or panic behaviors when specified severity levels are met.
func logMessage(level StoneLevel, format string, args ...interface{}) {
if level < FATAL && currentLogLevel > level {
return
}
msg := fmt.Sprintf(format, args...)
msg = getRandomPrefix(level) + " " + msg
// Determine if success or failure quote is needed
isSuccess := level <= WARN
if !disableCharacterSuffixes {
msg += getRandomQuote(isSuccess)
}
var formatted string
if useJSON {
caller := getCallerInfo()
entry := logEntry{
Time: time.Now().UTC().Format(time.RFC3339),
Level: level.String(),
Caller: caller,
Message: msg,
}
jsonData, _ := json.Marshal(entry)
formatted = string(jsonData)
} else {
formatted = stoneFormat(level, msg)
}
// Handle special logging behaviors for FATAL and PANIC
switch level {
case FATAL:
stoneLogger.Fatalln(formatted)
case PANIC:
stoneLogger.Panicln(formatted)
default:
stoneLogger.Println(formatted)
}
}
// getRandomPrefix returns a random prefix based on the provided StoneLevel.
// It selects a prefix from predefined lists corresponding to the log level.
func getRandomPrefix(level StoneLevel) string {
switch level {
case TRACE:
idx := rand.Intn(len(stoneTracePrefixes))
return stoneTracePrefixes[idx]
case DEBUG:
idx := rand.Intn(len(stoneDebugPrefixes))
return stoneDebugPrefixes[idx]
case INFO:
idx := rand.Intn(len(stoneInfoPrefixes))
return stoneInfoPrefixes[idx]
case WARN:
idx := rand.Intn(len(stoneWarnPrefixes))
return stoneWarnPrefixes[idx]
case ERROR:
idx := rand.Intn(len(stoneErrorPrefixes))
return stoneErrorPrefixes[idx]
case FATAL:
idx := rand.Intn(len(stonePanicPrefixes))
return stonePanicPrefixes[idx]
default:
idx := rand.Intn(len(stoneInfoPrefixes))
return stoneInfoPrefixes[idx]
}
}
// getRandomQuote returns a random character quote based on success or failure.
// The isSuccess parameter indicates if the quote is for a success (true) or failure.
func getRandomQuote(isSuccess bool) string {
if isSuccess {
idx := rand.Intn(len(characterSuccessQuoteSuffixes))
return characterSuccessQuoteSuffixes[idx]
} else {
idx := rand.Intn(len(characterFailQuoteSuffixes))
return characterFailQuoteSuffixes[idx]
}
}
// stoneFormat formats a log message with level, timestamp, caller, and color.
func stoneFormat(level StoneLevel, msg string) string {
now := time.Now().UTC().Format(time.RFC3339)
caller := getCallerInfo()
return fmt.Sprintf(
"%s%s [%s] [%s] %s%s", level.Color(), now, level.String(), caller, msg,
colorReset,
)
}

View File

@ -1,10 +1,17 @@
package stonelog package stonelog
// stoneTracePrefixes contains prefixes for trace-level scientific messages.
// stoneDebugPrefixes contains prefixes for debug-level diagnostics and processes.
// stoneInfoPrefixes contains prefixes for informational scientific outcomes.
// stoneWarnPrefixes contains prefixes for warning-level messages of potential risks.
// stoneErrorPrefixes contains prefixes for error-level critical issues detected.
// stoneFatalPrefixes contains prefixes for fatal-level critical failures.
// stonePanicPrefixes contains prefixes for panic-level catastrophic failures.
var ( var (
stoneTracePrefixes = []string{ stoneTracePrefixes = []string{
"Science traces", "Science traces:",
"Lab sensors detect", "Lab sensors detect:",
"Microscope focus on", "Microscope focus on:",
"Quantum scanner active:", "Quantum scanner active:",
"Data particles observed:", "Data particles observed:",
} }
@ -41,10 +48,19 @@ var (
"Hypothesis disproven:", "Hypothesis disproven:",
} }
stoneFatalPrefixes = []string{
"SCIENTIFIC APOCALYPSE:",
"FINAL EXPERIMENT FAILED:",
"LABORATORY SHUTDOWN:",
"CORE CRITICAL:",
"RADIOACTIVE TERMINATION:",
}
stonePanicPrefixes = []string{ stonePanicPrefixes = []string{
"‘‘‘CATASTROPHIC FAILURE!!!", "CHAIN REACTION DETECTED:",
"Emergency protocol FAILED:", "SYSTEMIC COLLAPSE:",
"LEAVE THE LAB!", "QUANTUM CATASTROPHE:",
"‘‘‘IMMINENT NUCLEAR FUSION!!!", "GALACTIC-LEVEL BUG DETECTED:",
"T-REX IN THE DATACENTER:",
} }
) )

47
suffixes.go Normal file
View File

@ -0,0 +1,47 @@
package stonelog
// characterSuccessQuoteSuffixes contains success quote suffixes by characters.
// characterFailQuoteSuffixes contains failure quote suffixes by characters.
var (
characterSuccessQuoteSuffixes = []string{
" // Senku: '10 BILLION POINTS FOR SCIENCE! REVIVAL SUCCESSFUL!'",
" // Senku: 'Mwa-ha-ha! Another victory for the Kingdom of Science!'",
" // Senku: 'E=mcΒ², baby! That’s how you optimize!'",
" // Senku: 'This experiment... is a 10 billion percent success!'",
" // Chrome: 'SO BADASS! SENKU, YOU’RE A GENIUS!'",
" // Chrome: 'HOLY CRAP, SCIENCE JUST PUNCHED THE SKY!'",
" // Chrome: 'WE’RE OFFICIALLY WIZARDS NOW!'",
" // Kohaku: 'Heh. Even I could’ve done that... maybe.'",
" // Kohaku: 'Science + fists = unstoppable!'",
" // Ryusui: 'NAVIGATION SUCCESSFUL! Time to monetize this!'",
" // Ryusui: 'Money can’t buy this... BUT I’LL TRY!'",
" // Kaseki: 'HOT BLOODED ENGINEERING... PERFECTED! (α—’α—£α—•)՞'",
" // Kaseki: 'I’LL CARVE A STATUE TO COMMEMORATE THIS MOMENT!'",
}
characterFailQuoteSuffixes = []string{
" // Senku: '10 BILLION REASONS TO FIX THIS... NOW.'",
" // Senku: 'This failure is... statistically impressive.'",
" // Senku: 'Mwa-ha-ha... *nervous laugh*... reboot everything.'",
" // Chrome: 'NOT BADASS! NOT BADASS AT ALL! (β•₯﹏β•₯)'",
" // Chrome: 'MY BRAIN HURTS! IS THIS HOW SCIENCE WORKS?!'",
" // Kohaku: 'Ugh. Can I just smash the server with a rock?'",
" // Kohaku: 'Senku, your science is broken. FIX IT.'",
" // Gen: 'Ah~... so this is how the world ends~?'",
" // Gen: 'Mentally calculating... yep, we’re doomed~.'",
" // Tsukasa: '...This is why I opposed technology.'",
" // Kaseki: 'BACK IN MY DAY, ERRORS WERE FIXED WITH A HAMMER! πŸ”¨'",
" // Kaseki: 'MY SOUL... IT BURNS WITH DEBUGGING RAGE!!!'",
" // Francois: 'I’ll prepare a funeral tea for the deceased process.'",
}
)