Skip to content

Commit 3f40759

Browse files
authored
Logs, Traces, and Metrics improvements
Logs and metrics can now have labels applied to them, traces auto-end when the block they are in terminates and context is propagated correctly
1 parent 1730724 commit 3f40759

File tree

9 files changed

+1113
-464
lines changed

9 files changed

+1113
-464
lines changed

.github/workflows/validate.yml

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,41 @@ jobs:
1111
runs-on: ubuntu-latest
1212

1313
steps:
14-
- uses: actions/checkout@v3
14+
- uses: actions/checkout@v4
1515

1616
- name: Setup Python
17-
uses: actions/setup-python@v4
17+
uses: actions/setup-python@v5
1818
with:
1919
python-version: '3.11'
2020

2121
- name: Install PlatformIO
22+
run: python -m pip install -U platformio
23+
24+
# Make repo Variables + Secrets available to all subsequent steps
25+
- name: Export env for build
2226
run: |
23-
python -m pip install -U platformio
27+
echo "::add-mask::${{ secrets.WIFI_PASS }}"
28+
{
29+
echo "WIFI_SSID=${{ vars.WIFI_SSID }}"
30+
echo "WIFI_PASS=${{ secrets.WIFI_PASS }}"
31+
echo "OTEL_COLLECTOR_HOST=${{ vars.OTEL_COLLECTOR_HOST }}"
32+
echo "OTEL_COLLECTOR_PORT=${{ vars.OTEL_COLLECTOR_PORT }}"
33+
echo "OTEL_SERVICE_NAME=${{ vars.OTEL_SERVICE_NAME }}"
34+
echo "OTEL_SERVICE_NAMESPACE=${{ vars.OTEL_SERVICE_NAMESPACE }}"
35+
echo "OTEL_SERVICE_VERSION=${{ vars.OTEL_SERVICE_VERSION }}"
36+
echo "OTEL_SERVICE_INSTANCE=${{ vars.OTEL_SERVICE_INSTANCE }}"
37+
echo "OTEL_DEPLOY_ENV=${{ vars.OTEL_DEPLOY_ENV }}"
38+
} >> "$GITHUB_ENV"
2439
2540
- name: PlatformIO Update
26-
run: |
27-
pio update
41+
run: pio update
2842

2943
- name: Build for ESP32 (esp32dev)
30-
run: |
31-
platformio ci examples/basic/main.cpp --project-conf platformio.ini --lib "." -e esp32dev
44+
run: platformio ci src/main.cpp --project-conf platformio.ini --lib "." -e esp32dev
3245

3346
- name: Build for Pico W (rpipicow)
34-
run: |
35-
platformio ci examples/basic/main.cpp --project-conf platformio.ini --lib "." -e rpipicow
47+
run: platformio ci src/main.cpp --project-conf platformio.ini --lib "." -e rpipicow
3648

3749
- name: Build for ESP8266 (esp8266 d1_mini)
38-
run: |
39-
platformio ci examples/basic/main.cpp --project-conf platformio.ini --lib "." -e esp8266
40-
50+
run: platformio ci src/main.cpp --project-conf platformio.ini --lib "." -e esp8266
4151

include/OtelDefaults.h

Lines changed: 117 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,128 @@
33

44
#include <map>
55
#include <ArduinoJson.h>
6-
#include <sys/time.h> // for gettimeofday()
6+
#include <sys/time.h> // gettimeofday()
7+
8+
// This header provides:
9+
// - Time helpers (nowUnixNano/Millis)
10+
// - OTLP JSON KeyValue serializers (string/double/int) using ArduinoJson v7 APIs
11+
// - OTelResourceConfig with legacy-compatible helpers used by Metrics/Tracer:
12+
// setAttribute(), addResourceAttributes(JsonObject)
13+
// and newer helpers used by Logger:
14+
// set(), clear(), toJson(resource)
15+
// - defaultResource() and defaultTraceResource() singletons
716

817
namespace OTel {
918

19+
// -------------------------------------------------------------------------------------------------
20+
// Time helpers
21+
// -------------------------------------------------------------------------------------------------
1022

11-
/**
12-
* @brief Get the current UNIX time in nanoseconds.
13-
* Uses the POSIX gettimeofday() clock, which you should have
14-
* synchronized via configTime()/time().
15-
*/
23+
/** UNIX timestamp in nanoseconds. Ensure clock is synced (configTime(), etc.) */
1624
static inline uint64_t nowUnixNano() {
1725
struct timeval tv;
1826
gettimeofday(&tv, nullptr);
19-
// seconds→ns, usec→ns
20-
return uint64_t(tv.tv_sec) * 1000000000ULL
21-
+ uint64_t(tv.tv_usec) * 1000ULL;
27+
return static_cast<uint64_t>(tv.tv_sec) * 1000000000ULL
28+
+ static_cast<uint64_t>(tv.tv_usec) * 1000ULL;
29+
}
30+
31+
/** UNIX timestamp in milliseconds (spare helper) */
32+
static inline uint64_t nowUnixMillis() {
33+
struct timeval tv;
34+
gettimeofday(&tv, nullptr);
35+
return static_cast<uint64_t>(tv.tv_sec) * 1000ULL
36+
+ static_cast<uint64_t>(tv.tv_usec) / 1000ULL;
37+
}
38+
39+
// Portable uint64 -> String (no printf/ULL reliance; RP2040-safe)
40+
inline String u64ToString(uint64_t v) {
41+
if (v == 0) return String("0");
42+
char buf[21]; // max 20 digits + NUL
43+
char* p = &buf[20];
44+
*p = '\0';
45+
while (v > 0) {
46+
*--p = char('0' + (v % 10));
47+
v /= 10;
48+
}
49+
return String(p);
50+
}
51+
52+
// -------------------------------------------------------------------------------------------------
53+
// OTLP JSON KeyValue helpers (ArduinoJson v7 deprecation-safe)
54+
// -------------------------------------------------------------------------------------------------
55+
56+
/**
57+
* Serialise a string KeyValue into an OTLP JSON attributes array:
58+
* {"key":"<key>","value":{"stringValue":"<value>"}}.
59+
*/
60+
inline void serializeKeyValue(JsonArray &arr, const String &key, const String &value) {
61+
JsonObject kv = arr.add<JsonObject>();
62+
kv["key"] = key;
63+
JsonObject any = kv["value"].to<JsonObject>();
64+
any["stringValue"] = value;
2265
}
2366

67+
/** Double-valued KeyValue */
68+
inline void serializeKeyDouble(JsonArray &arr, const String &key, double value) {
69+
JsonObject kv = arr.add<JsonObject>();
70+
kv["key"] = key;
71+
JsonObject any = kv["value"].to<JsonObject>();
72+
any["doubleValue"] = value;
73+
}
74+
75+
/** Int64-valued KeyValue */
76+
inline void serializeKeyInt(JsonArray &arr, const String &key, int64_t value) {
77+
JsonObject kv = arr.add<JsonObject>();
78+
kv["key"] = key;
79+
JsonObject any = kv["value"].to<JsonObject>();
80+
any["intValue"] = value;
81+
}
82+
83+
// -------------------------------------------------------------------------------------------------
84+
// Resource attributes container (back-compat + new helpers)
85+
// -------------------------------------------------------------------------------------------------
86+
87+
/**
88+
* Holds resource attributes (service/host/instance/etc.).
89+
* This struct supports:
90+
* - Legacy calls used by your Metrics/Tracer code:
91+
* setAttribute(k,v), addResourceAttributes(JsonObject target)
92+
* (these write "attributes" directly under the passed object)
93+
* - Newer usage for logs envelope:
94+
* toJson(resource) -> writes into resource["attributes"]
95+
*/
2496
struct OTelResourceConfig {
25-
// internal map of attributes
2697
std::map<String, String> attrs;
2798

28-
void setAttribute(const String& key, const String& value) {
29-
attrs[key] = value;
30-
}
99+
// Newer API
100+
void set(const String &k, const String &v) { attrs[k] = v; }
101+
void set(const char *k, const String &v) { attrs[String(k)] = v; }
102+
void clear() { attrs.clear(); }
103+
bool empty() const { return attrs.empty(); }
31104

32-
void serializeKeyValue(JsonArray &arr, const String &k, const String &v) const {
33-
JsonObject kv = arr.add<JsonObject>();
34-
kv["key"] = k;
35-
JsonObject val = kv["value"].to<JsonObject>();
36-
val["stringValue"] = v;
105+
// Backwards-compatible API expected by existing Metrics/Tracer code
106+
void setAttribute(const String &k, const String &v) { attrs[k] = v; }
107+
void setAttribute(const char *k, const String &v) { attrs[String(k)] = v; }
108+
109+
/**
110+
* Legacy helper used by Metrics/Tracer paths:
111+
* Writes attributes directly under the given target as:
112+
* target["attributes"] = [ {key, value:{stringValue}}, ... ]
113+
*/
114+
void addResourceAttributes(JsonObject target) const {
115+
if (attrs.empty()) return;
116+
JsonArray attributes = target["attributes"].to<JsonArray>();
117+
for (auto &p : attrs) {
118+
serializeKeyValue(attributes, p.first, p.second);
119+
}
37120
}
38121

39-
void addResourceAttributes(JsonObject &resource) const {
122+
/**
123+
* Logs envelope helper:
124+
* Writes into "resource.attributes" of the given resource object:
125+
* resource["attributes"] = [ {key, value:{stringValue}}, ... ]
126+
*/
127+
void toJson(JsonObject resource) const {
40128
if (attrs.empty()) return;
41129
JsonArray attributes = resource["attributes"].to<JsonArray>();
42130
for (auto &p : attrs) {
@@ -45,11 +133,18 @@ struct OTelResourceConfig {
45133
}
46134
};
47135

48-
inline OTelResourceConfig getDefaultResource() {
49-
return OTelResourceConfig();
136+
// -------------------------------------------------------------------------------------------------
137+
// Singletons (headers-only, inline ok)
138+
// -------------------------------------------------------------------------------------------------
139+
140+
/** Default resource for general use (metrics/logs/etc.) */
141+
static inline OTelResourceConfig& defaultResource() {
142+
static OTelResourceConfig rc;
143+
return rc;
50144
}
51145

146+
52147
} // namespace OTel
53148

54-
#endif
149+
#endif // OTEL_DEFAULTS_H
55150

0 commit comments

Comments
 (0)