Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
461 changes: 461 additions & 0 deletions source/telemetry/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Telemetry Library Java Bindings
* A Java interface for the MetaCall telemetry and logging system.
*
* Copyright (C) 2025 MetaCall Inc., Dhiren Mhatre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/

package com.metacall.telemetry;

/**
* Logger scoped to a specific category
*/
public class CategoryLogger {
private final String category;

public CategoryLogger(String category) {
this.category = category;
}

public String getCategory() {
return category;
}

public void trace(String message) {
Logger.trace(category, message);
}

public void debug(String message) {
Logger.debug(category, message);
}

public void info(String message) {
Logger.info(category, message);
}

public void warning(String message) {
Logger.warning(category, message);
}

public void error(String message) {
Logger.error(category, message);
}

public void critical(String message) {
Logger.critical(category, message);
}
}
68 changes: 68 additions & 0 deletions source/telemetry/bindings/java/com/metacall/telemetry/Counter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Telemetry Library Java Bindings
* A Java interface for the MetaCall telemetry and logging system.
*
* Copyright (C) 2025 MetaCall Inc., Dhiren Mhatre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/

package com.metacall.telemetry;

import java.util.concurrent.atomic.AtomicLong;

/**
* Counter metric - monotonically increasing value
*/
public class Counter extends Metric {
private final AtomicLong value;

public Counter(String name) {
this(name, "", "");
}

public Counter(String name, String description) {
this(name, description, "");
}

public Counter(String name, String description, String unit) {
super(name, description, unit);
this.value = new AtomicLong(0);
}

/**
* Increment the counter by 1
*/
public void increment() {
increment(1);
}

/**
* Increment the counter by a specific value
* @param delta The value to add
*/
public void increment(long delta) {
// TODO: Call native C library function
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability

The class contains TODO comments indicating that native C library functions should be called, but these are not yet implemented. This can lead to incomplete functionality and confusion for future developers.

Code Suggestion or Comments
// Implement the call to the native C library function here

Like Dislike

value.addAndGet(delta);
}

/**
* Get the current counter value
* @return The current value
*/
public long get() {
// TODO: Call native C library function
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability

The class contains TODO comments indicating that native C library functions should be called, but these are not yet implemented. This can lead to incomplete functionality and confusion for future developers.

Code Suggestion or Comments
// Implement the call to the native C library function here

Like Dislike

return value.get();
}

/**
* Reset the counter to zero
*/
public void reset() {
// TODO: Call native C library function
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability

The class contains TODO comments indicating that native C library functions should be called, but these are not yet implemented. This can lead to incomplete functionality and confusion for future developers.

Code Suggestion or Comments
// Implement the call to the native C library function here

Like Dislike

value.set(0);
}
}
118 changes: 118 additions & 0 deletions source/telemetry/bindings/java/com/metacall/telemetry/Gauge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Telemetry Library Java Bindings
* A Java interface for the MetaCall telemetry and logging system.
*
* Copyright (C) 2025 MetaCall Inc., Dhiren Mhatre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/

package com.metacall.telemetry;

import java.util.concurrent.atomic.AtomicReference;

/**
* Gauge metric - value that can go up and down
*/
public class Gauge extends Metric {
private final AtomicReference<Double> value;
private volatile double minValue;
private volatile double maxValue;

public Gauge(String name) {
this(name, "", "");
}

public Gauge(String name, String description) {
this(name, description, "");
}

public Gauge(String name, String description, String unit) {
super(name, description, unit);
this.value = new AtomicReference<>(0.0);
this.minValue = Double.MAX_VALUE;
this.maxValue = -Double.MAX_VALUE;
}

/**
* Set the gauge value
* @param newValue The new value
*/
public void set(double newValue) {
// TODO: Call native C library function
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability

The TODO comments indicate that native C library functions should be called, but no implementation is provided. This can lead to confusion about the intended functionality.

Code Suggestion or Comments
// TODO: Implement the call to the native C library function here

Like Dislike

value.set(newValue);
updateMinMax(newValue);
}

/**
* Increment the gauge by 1.0
*/
public void increment() {
increment(1.0);
}

/**
* Increment the gauge by a specific value
* @param delta The value to add
*/
public void increment(double delta) {
double newValue;
do {
double current = value.get();
newValue = current + delta;
} while (!value.compareAndSet(value.get(), newValue));
Comment on lines +62 to +66
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionality

The increment method uses value.get() twice in the compareAndSet loop, which can lead to incorrect behavior if the value changes between the two calls.

Code Suggestion or Comments
public void increment(double delta) {
        double newValue;
        double current;
        do {
            current = value.get();
            newValue = current + delta;
        } while (!value.compareAndSet(current, newValue));
        updateMinMax(newValue);
    }

Like Dislike

updateMinMax(newValue);
}

/**
* Decrement the gauge by 1.0
*/
public void decrement() {
decrement(1.0);
}

/**
* Decrement the gauge by a specific value
* @param delta The value to subtract
*/
public void decrement(double delta) {
increment(-delta);
}

/**
* Get the current gauge value
* @return The current value
*/
public double get() {
// TODO: Call native C library function
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability

The TODO comments indicate that native C library functions should be called, but no implementation is provided. This can lead to confusion about the intended functionality.

Code Suggestion or Comments
// TODO: Implement the call to the native C library function here

Like Dislike

return value.get();
}

/**
* Get the minimum observed value
* @return The minimum value
*/
public double getMin() {
return minValue;
}

/**
* Get the maximum observed value
* @return The maximum value
*/
public double getMax() {
return maxValue;
}

private void updateMinMax(double newValue) {
if (newValue < minValue) {
minValue = newValue;
}
if (newValue > maxValue) {
maxValue = newValue;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Telemetry Library Java Bindings
*/

package com.metacall.telemetry;

public enum HandlerType {
CONSOLE, FILE, SYSLOG, NETWORK, CUSTOM
}
131 changes: 131 additions & 0 deletions source/telemetry/bindings/java/com/metacall/telemetry/Histogram.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Telemetry Library Java Bindings
* A Java interface for the MetaCall telemetry and logging system.
*
* Copyright (C) 2025 MetaCall Inc., Dhiren Mhatre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/

package com.metacall.telemetry;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

/**
* Histogram metric - statistical distribution
*/
public class Histogram extends Metric {
private final double[] buckets;
private final AtomicLong[] bucketCounts;
private final AtomicLong totalCount;
private final AtomicReference<Double> sum;
private volatile double min;
private volatile double max;

private static final double[] DEFAULT_BUCKETS = {
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0
};

public Histogram(String name) {
this(name, "", "", DEFAULT_BUCKETS);
}

public Histogram(String name, String description) {
this(name, description, "", DEFAULT_BUCKETS);
}

public Histogram(String name, String description, String unit) {
this(name, description, unit, DEFAULT_BUCKETS);
}

public Histogram(String name, String description, String unit, double[] buckets) {
super(name, description, unit);
this.buckets = Arrays.copyOf(buckets, buckets.length);
this.bucketCounts = new AtomicLong[buckets.length];
for (int i = 0; i < buckets.length; i++) {
this.bucketCounts[i] = new AtomicLong(0);
}
this.totalCount = new AtomicLong(0);
this.sum = new AtomicReference<>(0.0);
this.min = Double.MAX_VALUE;
this.max = -Double.MAX_VALUE;
}

/**
* Observe a value
* @param value The value to observe
*/
public void observe(double value) {
// TODO: Call native C library function

// Update sum and count
double oldSum;
do {
oldSum = sum.get();
} while (!sum.compareAndSet(oldSum, oldSum + value));
totalCount.incrementAndGet();

// Update min and max
if (value < min) {
min = value;
}
if (value > max) {
max = value;
}

// Update buckets
for (int i = 0; i < buckets.length; i++) {
if (value <= buckets[i]) {
bucketCounts[i].incrementAndGet();
}
}
Comment on lines +82 to +86
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness

The observe method does not handle the case where the value is greater than all bucket upper bounds, which could lead to incorrect bucket counts.

Code Suggestion or Comments
boolean bucketUpdated = false;
        for (int i = 0; i < buckets.length; i++) {
            if (value <= buckets[i]) {
                bucketCounts[i].incrementAndGet();
                bucketUpdated = true;
                break;
            }
        }
        if (!bucketUpdated) {
            // Handle the case where the value is greater than all bucket upper bounds
            // This could be logging or incrementing a special overflow bucket
        }

Like Dislike

}

/**
* Get histogram statistics
* @return Statistics object
*/
public HistogramStats getStats() {
// TODO: Call native C library function
return new HistogramStats(totalCount.get(), sum.get(), min, max);
}

/**
* Get the bucket configuration
* @return Array of bucket upper bounds
*/
public double[] getBuckets() {
return Arrays.copyOf(buckets, buckets.length);
}

/**
* Get the count for a specific bucket
* @param index The bucket index
* @return The count for that bucket
*/
public long getBucketCount(int index) {
if (index < 0 || index >= bucketCounts.length) {
throw new IndexOutOfBoundsException("Bucket index out of range");
}
return bucketCounts[index].get();
}

/**
* Reset the histogram
*/
public void reset() {
// TODO: Call native C library function
totalCount.set(0);
sum.set(0.0);
min = Double.MAX_VALUE;
max = -Double.MAX_VALUE;
for (AtomicLong count : bucketCounts) {
count.set(0);
}
}
Comment on lines +121 to +130
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness

The reset method does not reset the min and max values correctly if the histogram is reused, which could lead to incorrect statistics.

Code Suggestion or Comments
public void reset() {
        // TODO: Call native C library function
        totalCount.set(0);
        sum.set(0.0);
        min = Double.MAX_VALUE;
        max = -Double.MAX_VALUE;
        for (AtomicLong count : bucketCounts) {
            count.set(0);
        }
        // Ensure min and max are reset correctly
        min = Double.MAX_VALUE;
        max = -Double.MAX_VALUE;
    }

Like Dislike

}
Loading