Skip to content
File

Blob: src/workerd/io/observer.c++

2.0 KB
1#include "observer.h"
2 
3#include "worker-interface.h"
4 
5#include <workerd/util/exception.h>
6 
7#include <kj/common.h>
8#include <kj/debug.h>
9#include <kj/map.h>
10#include <kj/mutex.h>
11 
12namespace workerd {
13 
14namespace {
15kj::Maybe<kj::Own<FeatureObserver>> featureObserver;
16 
17class FeatureObserverImpl final: public FeatureObserver {
18 public:
19 void use(Feature feature) const override {
20 auto lock = counts.lockExclusive();
21 lock->upsert(feature, 1, [](uint64_t& count, uint64_t value) { count += value; });
22 }
23 
24 void collect(CollectCallback&& callback) const override {
25 auto lock = counts.lockShared();
26 for (auto& entry: *lock) {
27 callback(entry.key, entry.value);
28 }
29 }
30 
31 private:
32 kj::MutexGuarded<kj::HashMap<Feature, uint64_t>> counts;
33};
34 
35} // namespace
36 
37kj::Own<FeatureObserver> FeatureObserver::createDefault() {
38 return kj::heap<FeatureObserverImpl>();
39}
40 
41void FeatureObserver::init(kj::Own<FeatureObserver> instance) {
42 KJ_ASSERT(featureObserver == kj::none);
43 featureObserver = kj::mv(instance);
44}
45 
46kj::Maybe<FeatureObserver&> FeatureObserver::get() {
47 KJ_IF_SOME(impl, featureObserver) {
48 return *impl;
49 }
50 return kj::none;
51}
52 
53EventOutcome RequestObserver::outcomeFromException(const kj::Exception& e, FailureSource source) {
54 if (e.getDetail(MEMORY_LIMIT_DETAIL_ID) != kj::none) {
55 return EventOutcome::EXCEEDED_MEMORY;
56 } else if (e.getDetail(CPU_LIMIT_DETAIL_ID) != kj::none) {
57 return EventOutcome::EXCEEDED_CPU;
58 } else if (e.getDetail(SCRIPT_KILLED_DETAIL_ID) != kj::none) {
59 return EventOutcome::KILL_SWITCH;
60 } else if (source == RequestObserver::FailureSource::DEFERRED_PROXY &&
61 e.getType() == kj::Exception::Type::DISCONNECTED) {
62 return EventOutcome::RESPONSE_STREAM_DISCONNECTED;
63 } else if (e.getType() == kj::Exception::Type::OVERLOADED) {
64 // We use exception details to describe some overloaded exceptions more accurately, if no such
65 // detail is present report internalError.
66 return EventOutcome::INTERNAL_ERROR;
67 } else {
68 return EventOutcome::EXCEPTION;
69 }
70}
71 
72}; // namespace workerd