git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
77
deps/juce/modules/juce_analytics/analytics/juce_Analytics.cpp
vendored
Normal file
77
deps/juce/modules/juce_analytics/analytics/juce_Analytics.cpp
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
void Analytics::addDestination (AnalyticsDestination* destination)
|
||||
{
|
||||
destinations.add (destination);
|
||||
}
|
||||
|
||||
OwnedArray<AnalyticsDestination>& Analytics::getDestinations()
|
||||
{
|
||||
return destinations;
|
||||
}
|
||||
|
||||
void Analytics::setUserId (String newUserId)
|
||||
{
|
||||
userId = newUserId;
|
||||
}
|
||||
|
||||
void Analytics::setUserProperties (StringPairArray properties)
|
||||
{
|
||||
userProperties = properties;
|
||||
}
|
||||
|
||||
void Analytics::logEvent (const String& eventName,
|
||||
const StringPairArray& parameters,
|
||||
int eventType)
|
||||
{
|
||||
if (! isSuspended)
|
||||
{
|
||||
AnalyticsDestination::AnalyticsEvent event
|
||||
{
|
||||
eventName,
|
||||
eventType,
|
||||
Time::getMillisecondCounter(),
|
||||
parameters,
|
||||
userId,
|
||||
userProperties
|
||||
};
|
||||
|
||||
for (auto* destination : destinations)
|
||||
destination->logEvent (event);
|
||||
}
|
||||
}
|
||||
|
||||
void Analytics::setSuspended (bool shouldBeSuspended)
|
||||
{
|
||||
isSuspended = shouldBeSuspended;
|
||||
}
|
||||
|
||||
JUCE_IMPLEMENT_SINGLETON (Analytics)
|
||||
|
||||
}
|
116
deps/juce/modules/juce_analytics/analytics/juce_Analytics.h
vendored
Normal file
116
deps/juce/modules/juce_analytics/analytics/juce_Analytics.h
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A singleton class to manage analytics data.
|
||||
|
||||
Use an Analytics object to manage sending analytics data to one or more
|
||||
AnalyticsDestinations.
|
||||
|
||||
@see AnalyticsDestination, ThreadedAnalyticsDestination,
|
||||
AnalyticsDestination::AnalyticsEvent
|
||||
|
||||
@tags{Analytics}
|
||||
*/
|
||||
class JUCE_API Analytics : public DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Adds an AnalyticsDestination to the list of AnalyticsDestinations
|
||||
managed by this Analytics object.
|
||||
|
||||
The Analytics class will take ownership of the AnalyticsDestination
|
||||
passed to this function.
|
||||
|
||||
@param destination the AnalyticsDestination to manage
|
||||
*/
|
||||
void addDestination (AnalyticsDestination* destination);
|
||||
|
||||
/** Returns the array of AnalyticsDestinations managed by this class.
|
||||
|
||||
If you have added any subclasses of ThreadedAnalyticsDestination to
|
||||
this class then you can remove them from this list to force them to
|
||||
flush any pending events.
|
||||
*/
|
||||
OwnedArray<AnalyticsDestination>& getDestinations();
|
||||
|
||||
/** Sets a user ID that will be added to all AnalyticsEvents sent to
|
||||
AnalyticsDestinations.
|
||||
|
||||
@param newUserId the userId to add to AnalyticsEvents
|
||||
*/
|
||||
void setUserId (String newUserId);
|
||||
|
||||
/** Sets some user properties that will be added to all AnalyticsEvents sent
|
||||
to AnalyticsDestinations.
|
||||
|
||||
@param properties the userProperties to add to AnalyticsEvents
|
||||
*/
|
||||
void setUserProperties (StringPairArray properties);
|
||||
|
||||
/** Sends an AnalyticsEvent to all AnalyticsDestinations.
|
||||
|
||||
The AnalyticsEvent will be timestamped, and will have the userId and
|
||||
userProperties populated by values previously set by calls to
|
||||
setUserId and setUserProperties. The name, parameters and type will be
|
||||
populated by the arguments supplied to this function.
|
||||
|
||||
@param eventName the event name
|
||||
@param parameters the event parameters
|
||||
@param eventType (optional) an integer to indicate the event
|
||||
type, which will be set to 0 if not supplied.
|
||||
*/
|
||||
void logEvent (const String& eventName, const StringPairArray& parameters, int eventType = 0);
|
||||
|
||||
/** Suspends analytics submissions to AnalyticsDestinations.
|
||||
|
||||
@param shouldBeSuspended if event submission should be suspended
|
||||
*/
|
||||
void setSuspended (bool shouldBeSuspended);
|
||||
|
||||
#ifndef DOXYGEN
|
||||
JUCE_DECLARE_SINGLETON (Analytics, false)
|
||||
#endif
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Analytics() = default;
|
||||
~Analytics() override { clearSingletonInstance(); }
|
||||
|
||||
String userId;
|
||||
StringPairArray userProperties;
|
||||
|
||||
bool isSuspended = false;
|
||||
|
||||
OwnedArray<AnalyticsDestination> destinations;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Analytics)
|
||||
};
|
||||
|
||||
} // namespace juce
|
60
deps/juce/modules/juce_analytics/analytics/juce_ButtonTracker.cpp
vendored
Normal file
60
deps/juce/modules/juce_analytics/analytics/juce_ButtonTracker.cpp
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
ButtonTracker::ButtonTracker (Button& buttonToTrack,
|
||||
const String& triggeredEventName,
|
||||
const StringPairArray& triggeredEventParameters,
|
||||
int triggeredEventType)
|
||||
: button (buttonToTrack),
|
||||
eventName (triggeredEventName),
|
||||
eventParameters (triggeredEventParameters),
|
||||
eventType (triggeredEventType)
|
||||
{
|
||||
button.addListener (this);
|
||||
}
|
||||
|
||||
ButtonTracker::~ButtonTracker()
|
||||
{
|
||||
button.removeListener (this);
|
||||
}
|
||||
|
||||
void ButtonTracker::buttonClicked (Button* b)
|
||||
{
|
||||
if (b == &button)
|
||||
{
|
||||
auto params = eventParameters;
|
||||
|
||||
if (button.getClickingTogglesState())
|
||||
params.set ("ButtonState", button.getToggleState() ? "On" : "Off");
|
||||
|
||||
Analytics::getInstance()->logEvent (eventName, params, eventType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace juce
|
79
deps/juce/modules/juce_analytics/analytics/juce_ButtonTracker.h
vendored
Normal file
79
deps/juce/modules/juce_analytics/analytics/juce_ButtonTracker.h
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class that automatically sends analytics events to the Analytics singleton
|
||||
when a button is clicked.
|
||||
|
||||
@see Analytics, AnalyticsDestination::AnalyticsEvent
|
||||
|
||||
@tags{Analytics}
|
||||
*/
|
||||
class JUCE_API ButtonTracker : private Button::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/**
|
||||
Creating one of these automatically sends analytics events to the Analytics
|
||||
singleton when the corresponding button is clicked.
|
||||
|
||||
The name and parameters of the analytics event will be populated from the
|
||||
variables supplied here. If clicking changes the button's state then the
|
||||
parameters will have a {"ButtonState", "On"/"Off"} entry added.
|
||||
|
||||
@param buttonToTrack the button to track
|
||||
@param triggeredEventName the name of the generated event
|
||||
@param triggeredEventParameters the parameters to add to the generated
|
||||
event
|
||||
@param triggeredEventType (optional) an integer to indicate the event
|
||||
type, which will be set to 0 if not supplied.
|
||||
|
||||
@see Analytics, AnalyticsDestination::AnalyticsEvent
|
||||
*/
|
||||
ButtonTracker (Button& buttonToTrack,
|
||||
const String& triggeredEventName,
|
||||
const StringPairArray& triggeredEventParameters = {},
|
||||
int triggeredEventType = 0);
|
||||
|
||||
/** Destructor. */
|
||||
~ButtonTracker() override;
|
||||
|
||||
private:
|
||||
/** @internal */
|
||||
void buttonClicked (Button*) override;
|
||||
|
||||
Button& button;
|
||||
const String eventName;
|
||||
const StringPairArray eventParameters;
|
||||
const int eventType;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonTracker)
|
||||
};
|
||||
|
||||
} // namespace juce
|
97
deps/juce/modules/juce_analytics/destinations/juce_AnalyticsDestination.h
vendored
Normal file
97
deps/juce/modules/juce_analytics/destinations/juce_AnalyticsDestination.h
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An interface for handling analytics events collected by an Analytics object.
|
||||
|
||||
For basic analytics logging you can implement this interface and add your
|
||||
class to an Analytics object.
|
||||
|
||||
For more advanced logging you may want to subclass
|
||||
ThreadedAnalyticsDestination instead, which is more suitable for interacting
|
||||
with web servers and other time consuming destinations.
|
||||
|
||||
@see Analytics, ThreadedAnalyticsDestination
|
||||
|
||||
@tags{Analytics}
|
||||
*/
|
||||
struct JUCE_API AnalyticsDestination
|
||||
{
|
||||
/** Contains information about an event to be logged. */
|
||||
struct AnalyticsEvent
|
||||
{
|
||||
/** The name of the event. */
|
||||
String name;
|
||||
|
||||
/** An optional integer representing the type of the event. You can use
|
||||
this to indicate if the event was a screenview, session start,
|
||||
exception, etc.
|
||||
*/
|
||||
int eventType;
|
||||
|
||||
/**
|
||||
The timestamp of the event.
|
||||
|
||||
Timestamps are automatically applied by an Analytics object and are
|
||||
derived from Time::getMillisecondCounter(). As such these timestamps
|
||||
do not represent absolute times, but relative timings of events for
|
||||
each user in each session will be accurate.
|
||||
*/
|
||||
uint32 timestamp;
|
||||
|
||||
/** The parameters of the event. */
|
||||
StringPairArray parameters;
|
||||
|
||||
/** The user ID associated with the event. */
|
||||
String userID;
|
||||
|
||||
/** Properties associated with the user. */
|
||||
StringPairArray userProperties;
|
||||
};
|
||||
|
||||
/** Constructor. */
|
||||
AnalyticsDestination() = default;
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~AnalyticsDestination() = default;
|
||||
|
||||
/**
|
||||
When an AnalyticsDestination is added to an Analytics object this method
|
||||
is called when an analytics event is triggered from the Analytics
|
||||
object.
|
||||
|
||||
Override this method to log the event information somewhere useful.
|
||||
*/
|
||||
virtual void logEvent (const AnalyticsEvent& event) = 0;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnalyticsDestination)
|
||||
};
|
||||
|
||||
|
||||
} // namespace juce
|
291
deps/juce/modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.cpp
vendored
Normal file
291
deps/juce/modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.cpp
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
ThreadedAnalyticsDestination::ThreadedAnalyticsDestination (const String& threadName)
|
||||
: dispatcher (threadName, *this)
|
||||
{}
|
||||
|
||||
ThreadedAnalyticsDestination::~ThreadedAnalyticsDestination()
|
||||
{
|
||||
// If you hit this assertion then the analytics thread has not been shut down
|
||||
// before this class is destroyed. Call stopAnalyticsThread() in your destructor!
|
||||
jassert (! dispatcher.isThreadRunning());
|
||||
}
|
||||
|
||||
void ThreadedAnalyticsDestination::setBatchPeriod (int newBatchPeriodMilliseconds)
|
||||
{
|
||||
dispatcher.batchPeriodMilliseconds = newBatchPeriodMilliseconds;
|
||||
}
|
||||
|
||||
void ThreadedAnalyticsDestination::logEvent (const AnalyticsEvent& event)
|
||||
{
|
||||
dispatcher.addToQueue (event);
|
||||
}
|
||||
|
||||
void ThreadedAnalyticsDestination::startAnalyticsThread (int initialBatchPeriodMilliseconds)
|
||||
{
|
||||
setBatchPeriod (initialBatchPeriodMilliseconds);
|
||||
dispatcher.startThread();
|
||||
}
|
||||
|
||||
void ThreadedAnalyticsDestination::stopAnalyticsThread (int timeout)
|
||||
{
|
||||
dispatcher.signalThreadShouldExit();
|
||||
stopLoggingEvents();
|
||||
dispatcher.stopThread (timeout);
|
||||
|
||||
if (dispatcher.eventQueue.size() > 0)
|
||||
saveUnloggedEvents (dispatcher.eventQueue);
|
||||
}
|
||||
|
||||
ThreadedAnalyticsDestination::EventDispatcher::EventDispatcher (const String& dispatcherThreadName,
|
||||
ThreadedAnalyticsDestination& destination)
|
||||
: Thread (dispatcherThreadName),
|
||||
parent (destination)
|
||||
{}
|
||||
|
||||
void ThreadedAnalyticsDestination::EventDispatcher::run()
|
||||
{
|
||||
// We may have inserted some events into the queue (on the message thread)
|
||||
// before this thread has started, so make sure the old events are at the
|
||||
// front of the queue.
|
||||
{
|
||||
std::deque<AnalyticsEvent> restoredEventQueue;
|
||||
parent.restoreUnloggedEvents (restoredEventQueue);
|
||||
|
||||
const ScopedLock lock (queueAccess);
|
||||
|
||||
for (auto rit = restoredEventQueue.rbegin(); rit != restoredEventQueue.rend(); ++rit)
|
||||
eventQueue.push_front (*rit);
|
||||
}
|
||||
|
||||
const int maxBatchSize = parent.getMaximumBatchSize();
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
{
|
||||
const ScopedLock lock (queueAccess);
|
||||
|
||||
const auto numEventsInBatch = eventsToSend.size();
|
||||
const auto freeBatchCapacity = maxBatchSize - numEventsInBatch;
|
||||
|
||||
if (freeBatchCapacity > 0)
|
||||
{
|
||||
const auto numNewEvents = (int) eventQueue.size() - numEventsInBatch;
|
||||
|
||||
if (numNewEvents > 0)
|
||||
{
|
||||
const auto numEventsToAdd = jmin (numNewEvents, freeBatchCapacity);
|
||||
const auto newBatchSize = numEventsInBatch + numEventsToAdd;
|
||||
|
||||
for (auto i = numEventsInBatch; i < newBatchSize; ++i)
|
||||
eventsToSend.add (eventQueue[(size_t) i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto submissionTime = Time::getMillisecondCounter();
|
||||
|
||||
if (! eventsToSend.isEmpty())
|
||||
{
|
||||
if (parent.logBatchedEvents (eventsToSend))
|
||||
{
|
||||
const ScopedLock lock (queueAccess);
|
||||
|
||||
for (auto i = 0; i < eventsToSend.size(); ++i)
|
||||
eventQueue.pop_front();
|
||||
|
||||
eventsToSend.clearQuick();
|
||||
}
|
||||
}
|
||||
|
||||
while (Time::getMillisecondCounter() - submissionTime < (uint32) batchPeriodMilliseconds.get())
|
||||
{
|
||||
if (threadShouldExit())
|
||||
return;
|
||||
|
||||
Thread::sleep (100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadedAnalyticsDestination::EventDispatcher::addToQueue (const AnalyticsEvent& event)
|
||||
{
|
||||
const ScopedLock lock (queueAccess);
|
||||
eventQueue.push_back (event);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
namespace DestinationTestHelpers
|
||||
{
|
||||
//==============================================================================
|
||||
struct BasicDestination : public ThreadedAnalyticsDestination
|
||||
{
|
||||
BasicDestination (std::deque<AnalyticsEvent>& loggedEvents,
|
||||
std::deque<AnalyticsEvent>& unloggedEvents)
|
||||
: ThreadedAnalyticsDestination ("ThreadedAnalyticsDestinationTest"),
|
||||
loggedEventQueue (loggedEvents),
|
||||
unloggedEventStore (unloggedEvents)
|
||||
{
|
||||
startAnalyticsThread (20);
|
||||
}
|
||||
|
||||
~BasicDestination() override
|
||||
{
|
||||
stopAnalyticsThread (1000);
|
||||
}
|
||||
|
||||
int getMaximumBatchSize() override
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
void saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) override
|
||||
{
|
||||
unloggedEventStore = eventsToSave;
|
||||
}
|
||||
|
||||
void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override
|
||||
{
|
||||
restoredEventQueue = unloggedEventStore;
|
||||
}
|
||||
|
||||
bool logBatchedEvents (const Array<AnalyticsEvent>& events) override
|
||||
{
|
||||
jassert (events.size() <= getMaximumBatchSize());
|
||||
|
||||
if (loggingIsEnabled)
|
||||
{
|
||||
const ScopedLock lock (eventQueueChanging);
|
||||
|
||||
for (auto& event : events)
|
||||
loggedEventQueue.push_back (event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void stopLoggingEvents() override {}
|
||||
|
||||
void setLoggingEnabled (bool shouldLogEvents)
|
||||
{
|
||||
loggingIsEnabled = shouldLogEvents;
|
||||
}
|
||||
|
||||
std::deque<AnalyticsEvent>& loggedEventQueue;
|
||||
std::deque<AnalyticsEvent>& unloggedEventStore;
|
||||
bool loggingIsEnabled = true;
|
||||
CriticalSection eventQueueChanging;
|
||||
};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct ThreadedAnalyticsDestinationTests : public UnitTest
|
||||
{
|
||||
ThreadedAnalyticsDestinationTests()
|
||||
: UnitTest ("ThreadedAnalyticsDestination", UnitTestCategories::analytics)
|
||||
{}
|
||||
|
||||
void compareEventQueues (const std::deque<AnalyticsDestination::AnalyticsEvent>& a,
|
||||
const std::deque<AnalyticsDestination::AnalyticsEvent>& b)
|
||||
{
|
||||
const auto numEntries = a.size();
|
||||
expectEquals ((int) b.size(), (int) numEntries);
|
||||
|
||||
for (size_t i = 0; i < numEntries; ++i)
|
||||
{
|
||||
expectEquals (a[i].name, b[i].name);
|
||||
expect (a[i].timestamp == b[i].timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
std::deque<AnalyticsDestination::AnalyticsEvent> testEvents;
|
||||
|
||||
for (int i = 0; i < 7; ++i)
|
||||
testEvents.push_back ({ String (i), 0, Time::getMillisecondCounter(), {}, "TestUser", {} });
|
||||
|
||||
std::deque<AnalyticsDestination::AnalyticsEvent> loggedEvents, unloggedEvents;
|
||||
|
||||
beginTest ("New events");
|
||||
|
||||
{
|
||||
DestinationTestHelpers::BasicDestination destination (loggedEvents, unloggedEvents);
|
||||
|
||||
for (auto& event : testEvents)
|
||||
destination.logEvent (event);
|
||||
|
||||
size_t waitTime = 0, numLoggedEvents = 0;
|
||||
|
||||
while (numLoggedEvents < testEvents.size())
|
||||
{
|
||||
if (waitTime > 4000)
|
||||
{
|
||||
expect (waitTime < 4000);
|
||||
break;
|
||||
}
|
||||
|
||||
Thread::sleep (40);
|
||||
waitTime += 40;
|
||||
|
||||
const ScopedLock lock (destination.eventQueueChanging);
|
||||
numLoggedEvents = loggedEvents.size();
|
||||
}
|
||||
}
|
||||
|
||||
compareEventQueues (loggedEvents, testEvents);
|
||||
expect (unloggedEvents.size() == 0);
|
||||
|
||||
loggedEvents.clear();
|
||||
|
||||
beginTest ("Unlogged events");
|
||||
{
|
||||
DestinationTestHelpers::BasicDestination destination (loggedEvents, unloggedEvents);
|
||||
destination.setLoggingEnabled (false);
|
||||
|
||||
for (auto& event : testEvents)
|
||||
destination.logEvent (event);
|
||||
}
|
||||
|
||||
compareEventQueues (unloggedEvents, testEvents);
|
||||
expect (loggedEvents.size() == 0);
|
||||
}
|
||||
};
|
||||
|
||||
static ThreadedAnalyticsDestinationTests threadedAnalyticsDestinationTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
217
deps/juce/modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.h
vendored
Normal file
217
deps/juce/modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.h
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A base class for dispatching analytics events on a dedicated thread.
|
||||
|
||||
This class is particularly useful for sending analytics events to a web
|
||||
server without blocking the message thread. It can also save (and restore)
|
||||
events that were not dispatched so no information is lost when an internet
|
||||
connection is absent or something else prevents successful logging.
|
||||
|
||||
Once startAnalyticsThread is called the logBatchedEvents method is
|
||||
periodically invoked on an analytics thread, with the period determined by
|
||||
calls to setBatchPeriod. Here events are grouped together into batches, with
|
||||
the maximum batch size set by the implementation of getMaximumBatchSize.
|
||||
|
||||
It's important to call stopAnalyticsThread in the destructor of your
|
||||
subclass (or before then) to give the analytics thread time to shut down.
|
||||
Calling stopAnalyticsThread will, in turn, call stopLoggingEvents, which
|
||||
you should use to terminate the currently running logBatchedEvents call.
|
||||
|
||||
@see Analytics, AnalyticsDestination, AnalyticsDestination::AnalyticsEvent
|
||||
|
||||
@tags{Analytics}
|
||||
*/
|
||||
class JUCE_API ThreadedAnalyticsDestination : public AnalyticsDestination
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/**
|
||||
Creates a ThreadedAnalyticsDestination.
|
||||
|
||||
@param threadName used to identify the analytics
|
||||
thread in debug builds
|
||||
*/
|
||||
ThreadedAnalyticsDestination (const String& threadName = "Analytics thread");
|
||||
|
||||
/** Destructor. */
|
||||
~ThreadedAnalyticsDestination() override;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Override this method to provide the maximum batch size you can handle in
|
||||
your subclass.
|
||||
|
||||
Calls to logBatchedEvents will contain no more than this number of events.
|
||||
*/
|
||||
virtual int getMaximumBatchSize() = 0;
|
||||
|
||||
/**
|
||||
This method will be called periodically on the analytics thread.
|
||||
|
||||
If this method returns false then the subsequent call of this function will
|
||||
contain the same events as previous call, plus any new events that have been
|
||||
generated in the period between calls. The order of events will not be
|
||||
changed. This allows you to retry logging events until they are logged
|
||||
successfully.
|
||||
|
||||
@param events a list of events to be logged
|
||||
@returns if the events were successfully logged
|
||||
*/
|
||||
virtual bool logBatchedEvents (const Array<AnalyticsEvent>& events) = 0;
|
||||
|
||||
/**
|
||||
You must always call stopAnalyticsThread in the destructor of your subclass
|
||||
(or before then) to give the analytics thread time to shut down.
|
||||
|
||||
Calling stopAnalyticsThread triggers a call to this method. At this point
|
||||
you are guaranteed that logBatchedEvents has been called for the last time
|
||||
and you should make sure that the current call to logBatchedEvents finishes
|
||||
as quickly as possible. This method and a subsequent call to
|
||||
saveUnloggedEvents must both complete before the timeout supplied to
|
||||
stopAnalyticsThread.
|
||||
|
||||
In a normal use case stopLoggingEvents will be called on the message thread
|
||||
from the destructor of your ThreadedAnalyticsDestination subclass, and must
|
||||
stop the logBatchedEvents method which is running on the analytics thread.
|
||||
|
||||
@see stopAnalyticsThread
|
||||
*/
|
||||
virtual void stopLoggingEvents() = 0;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Call this to set the period between logBatchedEvents invocations.
|
||||
|
||||
This method is thread safe and can be used to implements things like
|
||||
exponential backoff in logBatchedEvents calls.
|
||||
|
||||
@param newSubmissionPeriodMilliseconds the new submission period to
|
||||
use in milliseconds
|
||||
*/
|
||||
void setBatchPeriod (int newSubmissionPeriodMilliseconds);
|
||||
|
||||
/**
|
||||
Adds an event to the queue, which will ultimately be submitted to
|
||||
logBatchedEvents.
|
||||
|
||||
This method is thread safe.
|
||||
|
||||
@param event the analytics event to add to the queue
|
||||
*/
|
||||
void logEvent (const AnalyticsEvent& event) override final;
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/**
|
||||
Starts the analytics thread, with an initial event batching period.
|
||||
|
||||
@param initialBatchPeriodMilliseconds the initial event batching period
|
||||
in milliseconds
|
||||
*/
|
||||
void startAnalyticsThread (int initialBatchPeriodMilliseconds);
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Triggers the shutdown of the analytics thread.
|
||||
|
||||
You must call this method in the destructor of your subclass (or before
|
||||
then) to give the analytics thread time to shut down.
|
||||
|
||||
This method invokes stopLoggingEvents and you should ensure that both the
|
||||
analytics thread and a call to saveUnloggedEvents are able to finish before
|
||||
the supplied timeout. This timeout is important because on platforms like
|
||||
iOS an app is killed if it takes too long to shut down.
|
||||
|
||||
@param timeoutMilliseconds the number of milliseconds before
|
||||
the analytics thread is forcibly
|
||||
terminated
|
||||
*/
|
||||
void stopAnalyticsThread (int timeoutMilliseconds);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
/**
|
||||
This method will be called when the analytics thread is shut down,
|
||||
giving you the chance to save any analytics events that could not be
|
||||
logged. Once saved these events can be put back into the queue of events
|
||||
when the ThreadedAnalyticsDestination is recreated via
|
||||
restoreUnloggedEvents.
|
||||
|
||||
This method should return as quickly as possible, as both
|
||||
stopLoggingEvents and this method need to complete inside the timeout
|
||||
set in stopAnalyticsThread.
|
||||
|
||||
@param eventsToSave the events that could not be logged
|
||||
|
||||
@see stopAnalyticsThread, stopLoggingEvents, restoreUnloggedEvents
|
||||
*/
|
||||
virtual void saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) = 0;
|
||||
|
||||
/**
|
||||
The counterpart to saveUnloggedEvents.
|
||||
|
||||
Events added to the event queue provided by this method will be the
|
||||
first events supplied to logBatchedEvents calls. Use this method to
|
||||
restore any unlogged events previously stored in a call to
|
||||
saveUnloggedEvents.
|
||||
|
||||
This method is called on the analytics thread.
|
||||
|
||||
@param restoredEventQueue place restored events into this queue
|
||||
|
||||
@see saveUnloggedEvents
|
||||
*/
|
||||
virtual void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) = 0;
|
||||
|
||||
struct EventDispatcher : public Thread
|
||||
{
|
||||
EventDispatcher (const String& threadName, ThreadedAnalyticsDestination&);
|
||||
|
||||
void run() override;
|
||||
void addToQueue (const AnalyticsEvent&);
|
||||
|
||||
ThreadedAnalyticsDestination& parent;
|
||||
|
||||
std::deque<AnalyticsEvent> eventQueue;
|
||||
CriticalSection queueAccess;
|
||||
|
||||
Atomic<int> batchPeriodMilliseconds { 1000 };
|
||||
|
||||
Array<AnalyticsEvent> eventsToSend;
|
||||
};
|
||||
|
||||
const String destinationName;
|
||||
EventDispatcher dispatcher;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadedAnalyticsDestination)
|
||||
};
|
||||
|
||||
} // namespace juce
|
39
deps/juce/modules/juce_analytics/juce_analytics.cpp
vendored
Normal file
39
deps/juce/modules/juce_analytics/juce_analytics.cpp
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifdef JUCE_ANALYTICS_H_INCLUDED
|
||||
/* When you add this cpp file to your project, you mustn't include it in a file where you've
|
||||
already included any other headers - just put it inside a file on its own, possibly with your config
|
||||
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
|
||||
header files that the compiler may be using.
|
||||
*/
|
||||
#error "Incorrect use of JUCE cpp file"
|
||||
#endif
|
||||
|
||||
#include "juce_analytics.h"
|
||||
|
||||
#include "destinations/juce_ThreadedAnalyticsDestination.cpp"
|
||||
#include "analytics/juce_Analytics.cpp"
|
||||
#include "analytics/juce_ButtonTracker.cpp"
|
60
deps/juce/modules/juce_analytics/juce_analytics.h
vendored
Normal file
60
deps/juce/modules/juce_analytics/juce_analytics.h
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
The block below describes the properties of this module, and is read by
|
||||
the Projucer to automatically generate project code that uses it.
|
||||
For details about the syntax and how to create or use a module, see the
|
||||
JUCE Module Format.md file.
|
||||
|
||||
|
||||
BEGIN_JUCE_MODULE_DECLARATION
|
||||
|
||||
ID: juce_analytics
|
||||
vendor: juce
|
||||
version: 6.1.2
|
||||
name: JUCE analytics classes
|
||||
description: Classes to collect analytics and send to destinations
|
||||
website: http://www.juce.com/juce
|
||||
license: GPL/Commercial
|
||||
minimumCppStandard: 14
|
||||
|
||||
dependencies: juce_gui_basics
|
||||
|
||||
END_JUCE_MODULE_DECLARATION
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
#define JUCE_ANALYTICS_H_INCLUDED
|
||||
|
||||
#include <juce_gui_basics/juce_gui_basics.h>
|
||||
|
||||
#include "destinations/juce_AnalyticsDestination.h"
|
||||
#include "destinations/juce_ThreadedAnalyticsDestination.h"
|
||||
#include "analytics/juce_Analytics.h"
|
||||
#include "analytics/juce_ButtonTracker.h"
|
Reference in New Issue
Block a user