From 7d1bcf07eff866aa9ee7285dd90b2e53521f145b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 11 Jun 2013 17:09:39 -0700 Subject: [PATCH] add a Logstash class to prepare for sending stats over UDP --- audio-mixer/src/main.cpp | 37 ++++++++++++++++++++++++ libraries/shared/src/Logstash.cpp | 45 +++++++++++++++++++++++++++++ libraries/shared/src/Logstash.h | 25 ++++++++++++++++ libraries/shared/src/SharedUtil.cpp | 9 ++++++ libraries/shared/src/SharedUtil.h | 1 + 5 files changed, 117 insertions(+) create mode 100644 libraries/shared/src/Logstash.cpp create mode 100644 libraries/shared/src/Logstash.h diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index b7ca6d1f41..8cd2abc2d9 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "InjectedAudioRingBuffer.h" #include "AvatarAudioRingBuffer.h" @@ -100,7 +101,17 @@ int main(int argc, const char* argv[]) { timeval lastDomainServerCheckIn = {}; + timeval beginSendTime, endSendTime; + + // if we'll be sending stats, call the Logstash::socket() method to make it load the logstash IP outside the loop + if (Logstash::shouldSendStats()) { + Logstash::socket(); + } + while (true) { + if (Logstash::shouldSendStats()) { + gettimeofday(&beginSendTime, NULL); + } // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { @@ -344,6 +355,32 @@ int main(int argc, const char* argv[]) { } } + if (Logstash::shouldSendStats()) { + // send a packet to our logstash instance + + // calculate the percentage value for time elapsed for this send (of the max allowable time) + gettimeofday(&endSendTime, NULL); + + float percentageOfMaxElapsed = (usecTimestamp(&endSendTime) - usecTimestamp(&beginSendTime)) + / BUFFER_SEND_INTERVAL_USECS * 100.0f; + + if (percentageOfMaxElapsed < 0) { + percentageOfMaxElapsed = 0.0f; + } + + const char MIXER_LOGSTASH_METRIC_NAME[] = "audio-mixer-frame-time-usage"; + + // we're sending a floating point percentage with two mandatory numbers after decimal point + // that could be up to 6 bytes + const int MIXER_LOGSTASH_PACKET_BYTES = strlen(MIXER_LOGSTASH_METRIC_NAME) + 7; + char logstashPacket[MIXER_LOGSTASH_PACKET_BYTES]; + + sprintf(logstashPacket, "%s %.2f", MIXER_LOGSTASH_METRIC_NAME, percentageOfMaxElapsed); + +// agentList->getAgentSocket()->send(Logstash::socket(), logstashPacket, MIXER_LOGSTASH_PACKET_BYTES); + + } + double usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); if (usecToSleep > 0) { diff --git a/libraries/shared/src/Logstash.cpp b/libraries/shared/src/Logstash.cpp new file mode 100644 index 0000000000..dbbf7f8ec3 --- /dev/null +++ b/libraries/shared/src/Logstash.cpp @@ -0,0 +1,45 @@ +// +// Logstash.cpp +// hifi +// +// Created by Stephen Birarda on 6/11/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include + +#include "SharedUtil.h" + +#include "Logstash.h" + +sockaddr_in Logstash::logstashSocket = {}; + +sockaddr* Logstash::socket() { + + if (logstashSocket.sin_addr.s_addr == 0) { + // we need to construct the socket object + + // assume IPv4 + logstashSocket.sin_family = AF_INET; + + // use the constant port + logstashSocket.sin_port = htons(LOGSTASH_UDP_PORT); + + // lookup the IP address for the constant hostname + struct hostent* logstashHostInfo; + if ((logstashHostInfo = gethostbyname(LOGSTASH_HOSTNAME))) { + memcpy(&logstashSocket.sin_addr, logstashHostInfo->h_addr_list[0], logstashHostInfo->h_length); + } else { + printf("Failed to lookup logstash IP - will try again on next log attempt.\n"); + } + } + + return (sockaddr*) &logstashSocket; +} + +bool Logstash::shouldSendStats() { + static bool shouldSendStats = isInEnvironment("production"); + return shouldSendStats; +} \ No newline at end of file diff --git a/libraries/shared/src/Logstash.h b/libraries/shared/src/Logstash.h new file mode 100644 index 0000000000..20f58b8057 --- /dev/null +++ b/libraries/shared/src/Logstash.h @@ -0,0 +1,25 @@ +// +// Logstash.h +// hifi +// +// Created by Stephen Birarda on 6/11/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__Logstash__ +#define __hifi__Logstash__ + +#include + +const int LOGSTASH_UDP_PORT = 9500; +const char LOGSTASH_HOSTNAME[] = "graphite.highfidelity.io"; + +class Logstash { +public: + static sockaddr* socket(); + static bool shouldSendStats(); +private: + static sockaddr_in logstashSocket; +}; + +#endif /* defined(__hifi__Logstash__) */ diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 30aa75b461..66a3ba0012 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -110,6 +110,15 @@ void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) { byte += ((value & 3) << (7 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 } +bool isInEnvironment(const char* environment) { + char* environmentString = getenv("HIFI_ENVIRONMENT"); + + if (environmentString && strcmp(environmentString, environment) == 0) { + return true; + } else { + return false; + } +} void switchToResourcesParentIfRequired() { #ifdef __APPLE__ diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 28c4adb296..ba531d23cc 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -57,6 +57,7 @@ void setAtBit(unsigned char& byte, int bitIndex); int getSemiNibbleAt(unsigned char& byte, int bitIndex); void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value); +bool isInEnvironment(const char* environment); void switchToResourcesParentIfRequired();