github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/FlameGraph/FlameGraphComponent/color.spec.ts (about) 1 import Color from 'color'; 2 import { 3 colorBasedOnDiffPercent, 4 NewDiffColor, 5 getPackageNameFromStackTrace, 6 } from './color'; 7 import { DefaultPalette } from './colorPalette'; 8 9 describe.each([ 10 // red (diff > 0) 11 [30, 60, DefaultPalette.badColor.toString()], 12 13 // green (diff < 0%) 14 [60, 0, DefaultPalette.goodColor.toString()], 15 16 // grey (diff == 0) 17 [0, 0, DefaultPalette.neutralColor.toString()], 18 ])('.colorBasedOnDiffPercent(%i, %i)', (a, b, expected) => { 19 it(`returns ${expected}`, () => { 20 expect(colorBasedOnDiffPercent(DefaultPalette, a, b).rgb().toString()).toBe( 21 expected 22 ); 23 }); 24 }); 25 26 describe('NewDiffColor with white-to-black example palette', () => { 27 describe.each([ 28 [-100, 'rgb(255, 255, 255)'], 29 [0, 'rgb(128, 128, 128)'], 30 [100, 'rgb(0, 0, 0)'], 31 ])('.NewDiffColor(%i)', (a, expected) => { 32 it(`returns ${expected}`, () => { 33 const color = NewDiffColor({ 34 name: 'my palette', 35 goodColor: Color('white'), 36 neutralColor: Color('grey'), 37 badColor: Color('black'), 38 }); 39 40 expect(color(a).rgb().toString()).toBe(expected); 41 }); 42 }); 43 }); 44 45 describe('getPackageNameFromStackTrace', () => { 46 describe('golang', () => { 47 describe.each([ 48 ['bufio.(*Reader).fill', 'bufio.'], 49 ['cmpbody', 'cmpbody'], 50 ['bytes.Compare', 'bytes.'], 51 ['crypto/tls.(*Conn).clientHandshake', 'crypto/tls.'], 52 [ 53 'github.com/DataDog/zstd._Cfunc_ZSTD_compress_wrapper', 54 'github.com/DataDog/zstd.', 55 ], 56 [ 57 'github.com/dgraph-io/badger/v2.(*DB).calculateSize', 58 'github.com/dgraph-io/badger/v2.', 59 ], 60 [ 61 'github.com/dgraph-io/badger/v2/table.(*blockIterator).next', 62 'github.com/dgraph-io/badger/v2/table.', 63 ], 64 ['path/filepath.walk', 'path/filepath.'], 65 ['os.(*File).write', 'os.'], 66 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 67 it(`returns '${expected}'`, () => { 68 expect(getPackageNameFromStackTrace('gospy', a)).toBe(expected); 69 }); 70 }); 71 }); 72 73 describe('pyspy', () => { 74 describe.each([ 75 ['total', 'total'], 76 [ 77 'System.Private.CoreLib!System.Threading.TimerQueue.FireNextTimers()', 78 'System.Private.CoreLib!System.Threading', 79 ], 80 [ 81 'StackExchange.Redis!StackExchange.Redis.ConnectionMultiplexer.OnHeartbeat()', 82 'StackExchange.Redis!StackExchange.Redis', 83 ], 84 [ 85 'Microsoft.AspNetCore.Server.Kestrel.Core!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestPipeReader.ReadAsync(value class System.Threading.CancellationToken)', 86 'Microsoft.AspNetCore.Server.Kestrel.Core!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http', 87 ], 88 [ 89 'Google.Protobuf!Google.Protobuf.ParsingPrimitivesMessages.ReadRawMessage(value class Google.Protobuf.ParseContext\u0026,class Google.Protobuf.IMessage)', 90 'Google.Protobuf!Google.Protobuf', 91 ], 92 [ 93 'Grpc.AspNetCore.Server!Grpc.AspNetCore.Server.Internal.PipeExtensions.ReadSingleMessageAsync(class System.IO.Pipelines.PipeReader,class Grpc.AspNetCore.Server.Internal.HttpContextServerCallContext,class System.Func`2\u003cclass Grpc.Core.DeserializationContext,!!0\u003e)', 94 'Grpc.AspNetCore.Server!Grpc.AspNetCore.Server.Internal', 95 ], 96 [ 97 'System.Private.CoreLib!System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.__Canon].GetStateMachineBox(!!0\u0026,class System.Threading.Tasks.Task`1\u003c!0\u003e\u0026)', 98 'System.Private.CoreLib!System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System', 99 ], 100 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 101 it(`returns '${expected}'`, () => { 102 expect(getPackageNameFromStackTrace('dotnetspy', a)).toBe(expected); 103 }); 104 }); 105 }); 106 107 describe('pyspy', () => { 108 describe.each([ 109 ['total', 'total'], 110 ['urllib3/response.py:579 - stream', 'urllib3/'], 111 ['requests/models.py:580 - prepare_cookies', 'requests/'], 112 ['logging/__init__.py:1548 - findCaller', 'logging/'], 113 [ 114 'jaeger_client/thrift_gen/jaeger/ttypes.py:147 - write', 115 'jaeger_client/thrift_gen/jaeger/', 116 ], 117 118 // TODO: this one looks incorrect, but keeping in the test for now 119 [ 120 '\u003cfrozen importlib._bootstrap\u003e:1030 - _gcd_import', 121 '<frozen importlib._bootstrap>:1030 - _gcd_import', 122 ], 123 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 124 it(`returns '${expected}'`, () => { 125 expect(getPackageNameFromStackTrace('pyspy', a)).toBe(expected); 126 }); 127 }); 128 }); 129 130 describe('rbspy', () => { 131 describe.each([ 132 ['total', 'total'], 133 ['webrick/utils.rb:194 - watch', 'webrick/'], 134 ['webrick/server.rb:190 - block (2 levels) in start', 'webrick/'], 135 [ 136 'gems/sinatra-2.0.3/lib/sinatra/base.rb:1537 - start_server', 137 'gems/sinatra-2.0.3/lib/sinatra/', 138 ], 139 ['services/driver/client.rb:34 - get_drivers', 'services/driver/'], 140 ['uri/common.rb:742 - URI', 'uri/'], 141 ['net/protocol.rb:299 - block in write0', 'net/'], 142 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 143 it(`returns '${expected}'`, () => { 144 expect(getPackageNameFromStackTrace('rbspy', a)).toBe(expected); 145 }); 146 }); 147 }); 148 149 describe('ebpfspy', () => { 150 describe.each([ 151 ['total', 'total'], 152 ['entry_SYSCALL_64_after_hwframe', 'entry_SYSCALL_64_after_hwframe'], 153 ['[unknown]', '[unknown]'], 154 [ 155 'QApplicationPrivate::notify_helper(QObject*, QEvent*)', 156 'QApplicationPrivate::notify_helper(QObject*, QEvent*)', 157 ], 158 [ 159 'v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&)', 160 'v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&)', 161 ], 162 [ 163 'github.com/pyroscope-io/pyroscope/pkg/agent.(*ProfileSession).Start.dwrap.3', 164 'github.com/pyroscope-io/pyroscope/pkg/agent.(*ProfileSession).Start.dwrap.3', 165 ], 166 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 167 it(`returns '${expected}'`, () => { 168 expect(getPackageNameFromStackTrace('ebpfspy', a)).toBe(expected); 169 }); 170 }); 171 }); 172 173 describe('default', () => { 174 describe.each([ 175 ['total', 'total'], 176 ['entry_SYSCALL_64_after_hwframe', 'entry_SYSCALL_64_after_hwframe'], 177 ['[unknown]', '[unknown]'], 178 [ 179 'QApplicationPrivate::notify_helper(QObject*, QEvent*)', 180 'QApplicationPrivate::notify_helper(QObject*, QEvent*)', 181 ], 182 [ 183 'v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&)', 184 'v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&)', 185 ], 186 [ 187 'github.com/pyroscope-io/pyroscope/pkg/agent.(*ProfileSession).Start.dwrap.3', 188 'github.com/pyroscope-io/pyroscope/pkg/agent.(*ProfileSession).Start.dwrap.3', 189 ], 190 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 191 it(`returns '${expected}'`, () => { 192 expect(getPackageNameFromStackTrace('unknown', a)).toBe(expected); 193 }); 194 }); 195 }); 196 197 describe('rust', () => { 198 describe.each([ 199 ['total', 'total'], 200 ['std::thread::local::LocalKey<T>::with', 'std'], 201 [ 202 'tokio::runtime::basic_scheduler::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}', 203 'tokio', 204 ], 205 [ 206 '<core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll', 207 '<core', 208 ], 209 [ 210 'reqwest::blocking::client::ClientHandle::new::{{closure}}::{{closure}}', 211 'reqwest', 212 ], 213 ['core::time::Duration::as_secs', 'core'], 214 ['clock_gettime@GLIBC_2.2.5', 'clock_gettime@GLIBC_2.2.5'], 215 [ 216 'hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_catch debugger eval code', 217 'hyper', 218 ], 219 ['openssl::ssl::connector::SslConnector::builder', 'openssl'], 220 221 // TODO looks incorrect 222 [ 223 '<F as futures_core::future::TryFuture>::try_poll', 224 '<F as futures_core', 225 ], 226 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 227 it(`returns '${expected}'`, () => { 228 expect(getPackageNameFromStackTrace('pyroscope-rs', a)).toBe(expected); 229 }); 230 }); 231 }); 232 233 describe('scrape (pull mode)', () => { 234 describe.each([ 235 ['bufio.(*Reader).fill', 'bufio.'], 236 ['cmpbody', 'cmpbody'], 237 ['bytes.Compare', 'bytes.'], 238 ['crypto/tls.(*Conn).clientHandshake', 'crypto/tls.'], 239 [ 240 'github.com/DataDog/zstd._Cfunc_ZSTD_compress_wrapper', 241 'github.com/DataDog/zstd.', 242 ], 243 [ 244 'github.com/dgraph-io/badger/v2.(*DB).calculateSize', 245 'github.com/dgraph-io/badger/v2.', 246 ], 247 [ 248 'github.com/dgraph-io/badger/v2/table.(*blockIterator).next', 249 'github.com/dgraph-io/badger/v2/table.', 250 ], 251 ['path/filepath.walk', 'path/filepath.'], 252 ['os.(*File).write', 'os.'], 253 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 254 it(`returns '${expected}'`, () => { 255 expect(getPackageNameFromStackTrace('scrape', a)).toBe(expected); 256 }); 257 }); 258 }); 259 260 describe('nodejs spy', () => { 261 describe.each([ 262 ['total', 'total'], 263 ['./node_modules/node-fetch/lib/index.js:fetch:1493', 'node-fetch'], 264 [ 265 './node_modules/@pyroscope-node/dist/pull/index.js:sampleFunction:1827', 266 '@pyroscope-node', 267 ], 268 ['node:net:Socket:320', 'node:net'], 269 [':(idle):0', ''], 270 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 271 it(`returns '${expected}'`, () => { 272 expect(getPackageNameFromStackTrace('nodespy', a)).toBe(expected); 273 }); 274 }); 275 }); 276 277 describe('java spy', () => { 278 describe.each([ 279 [ 280 'org/apache/catalina/core/ApplicationFilterChain.doFilter', 281 'org/apache/catalina/core/', 282 ], 283 [ 284 'org/apache/catalina/core/ApplicationFilterChain.internalDoFilter', 285 'org/apache/catalina/core/', 286 ], 287 [ 288 'org/apache/coyote/AbstractProcessorLight.process', 289 'org/apache/coyote/', 290 ], 291 [ 292 'org/springframework/web/servlet/DispatcherServlet.doService', 293 'org/springframework/web/servlet/', 294 ], 295 [ 296 'org/example/rideshare/RideShareController.orderCar', 297 'org/example/rideshare/', 298 ], 299 ['org/example/rideshare/OrderService.orderCar', 'org/example/rideshare/'], 300 ['total', 'total'], 301 ])(`.getPackageNameFromStackTrace('%s')`, (a, expected) => { 302 it(`returns '${expected}'`, () => { 303 expect(getPackageNameFromStackTrace('javaspy', a)).toBe(expected); 304 }); 305 }); 306 }); 307 });